6月 182019
 

参照 RFC7231 6.2, 5.1.1

  • 1xx ステータスコードのレスポンスは、最終的なレスポンスに先立って情報を伝達するために返される
    • つまり 1xx レスポンスが返される時は、1リクエストに対して2レスポンス返されたりする
  • HTTP/1.0 ではサポートされない
  • RFC7231 は HTTP/2 でも変わっていない

  • Expect: 100-continue リクエストに対して 417 レスポンスが返された場合、クライアントは Expect ヘッダーを除いたリクエスト全体を送信すべきである

  • これらの動作はプロキシがクライアント・サーバー双方に対して代行することも有り得る
6月 172019
 

参照 RFC7230 6.7

  • Upgrade ヘッダーは、1つの HTTP/1.1 コネクション上で他のプロトコルへ移行するのに用いられる
  • HTTP/2 にはこの仕組みはなく、CONNECT メソッド拡張の protocol 擬似ヘッダーにて実現される [RFC8441 4]

  • クライアントは、Upgrade ヘッダーに優先度の高い順にプロトコル名のリストを設定し、送信する
  • サーバーは、リストから移行するプロトコルを選択して Upgrade ヘッダーに設定し、101 Switching Protocols レスポンスを返す
  • サーバー側からプロトコルの移行を指示する場合、426 Upgrade Required レスポンスを用いる

  • Upgrade ヘッダーは hop-by-hop ヘッダーであり、指定されたプロトコルに対応していない中継者による回送を防ぐために、Connection ヘッダーに upgrade を指定しなければならない

  • サーバーが Upgrade と Expect を同時に受信した場合、101 Switching Protocols より先に 100 Continue を送信しなければならない
  • 利用できるプロトコルのリストは、IANA に登録されなければならない
6月 142019
 

HTTP フォワードプロキシが介在する場合、単に通信を中継するだけでなく通信される内容も変化する。
もちろんプロキシの機能として HTTP メッセージの改変が行われる場合はあるが、それ以外の場合でも変化する部分はある。

  • request-target の形式
    • クライアントが送信するリクエストラインが変更される
    • サーバー直アクセス: GET /hoge HTTP/1.1
    • プロキシ経由アクセス: GET http://example.com/hoge HTTP/1.1
  • Transfer Codings の変更
    • chunked から Content-Length 形式に変更される、圧縮が解除されるといったことはあり得る
  • HTTP コネクションの持続的接続の有無
    • client-proxy 間と proxy-server 間では TCP コネクションの持続方法が異なる場合がある

いずれも HTTP の意味論的な変更ではなく、通信上の都合により変更が許されている部分である。

6月 142019
 

参照 RFC7230 5.3

  • HTTP リクエストメッセージのリクエストラインは、method request-target HTTP-version で構成される
    • GET / HTTP/1.1
  • この内の request-target にはいくつかの形式が存在する
型式名 用途
origin-form GET /where?q=now HTTP/1.1 最もよくある形式
absolute-form GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1 プロキシ向けリクエストはこの形式でなければならない
authority-form CONNECT www.example.com:80 HTTP/1.1 CONNECT メソッドでは必須。CONNECT メソッド限定。
asterisk-form OPTIONS * HTTP/1.1 OPTIONS メソッドでは必須。OPTIONS メソッド限定。リソースのワイルドカード的に用いられる。

このうち、absolute-form は原則プロキシ向けのリクエストにのみ用いられるが、サーバーは absolute-form を受容可能でなければならない。
理由は将来の HTTP バージョンでは全て absolute-form への移行を可能にするためとされている。
実際に HTTP/2 では、リクエストラインに相当する機能は擬似ヘッダーフィールドに変更されているものの、absolute-form に相当するだけの情報を持つようになっている。

しかし実際に absolute-form を送信すると正しく動作しないサーバーが非常に多い。
恐らくはリバースプロキシでのリライトルールあたりとの相性が悪いせいではないかと考えられる。

6月 132019
 

概要

参照 RFC7230 4, 3.3.1

  • HTTP メッセージボディーの転送は、HTTP/1.0 までは Content-Length で指定した長さのデータを転送する方式しかなかった
    • 転送が終わるまでボディーデータの全てをメモリ上にとどめておく必要があるなどした
  • HTTP/1.1 にて chunked transfer coding (chunked) ができるようになり、ボディーデータを分割して転送することができるようになった
    • 事前に最終的な長さが分からなくても転送可能
  • HTTP/2 には Transfer Codings の仕組み自体がない
    • Stream に取って代わられたため

  • Transfer Codings の方式は、TE および Transfer-Encoding ヘッダーにて指定する
    • TE ヘッダーでクライアントが受入可能な方式を指定
    • Transfer-Encoding ヘッダーで送信するメッセージの符号化方式を指定
  • 受信者は chunked を復号化できなければならない [RFC7230 4.1]
  • Transfer-Encoding は hop-by-hop ヘッダーであり、隣接ノード間にのみ適用される [RFC7230 3.3.1]
    • 故に、プロキシなどの中継者は Transfer-Encoding を復号化し、Content-Length 方式や別の Transfer-Encoding に変換するなどしても良い
    • Content-Encoding ヘッダーは end-to-end ヘッダーである点に注意

Continue reading »

6月 102019
 

コンポーネント凝集性の原則に閉鎖性共通の原則(CCP)もあるが、どちらも概念としては同じである。

モジュールはたったひとつのアクターに対して責務を負うべきである。
(Clean Architecture / Robert C.Martin)

クラスレベルでは、単一責任の原則(Single Responsibility Principle)。
コンポーネントレベルでは、閉鎖性共通の原則(Common Closure Principle)。

SOLID 原則は知っていても、どのようにクラスを定義するか、コンポーネントを分割するか、つまりどこに境界線を引くべきかを悩むことは多い。
単一責任、変更する理由は一つだけであるべきと言われても、その「責任」がふわっとしていて定まらないなんてことはよくある。

Clean Architecture の上記部分を読んでようやく、「責任」には当然「対象」が存在する事に気付いた。
つまりクラスにしろコンポーネントにしろ、必ず利用するアクターは存在する。

アクターとは、同じ変更理由を持ったユーザー等の集まりだ。
となると、モジュールが複数のアクターに対して責任を持ってしまうと複数の変更理由が発生する可能性が出てくる。
なので、モジュールが単一のアクターに対して責任を持つように境界線を引くべきなのだ。
一見よく似た処理や画面だったとしても、アクターが異なれば異なる変更理由で変更が入ることがあるため、分けた方が良い。

複数のアクターが全く同じように使う共通的なモジュールもあるだろうが、それは恐らくより抽象化されたアクター(汎化アクター)がそれに対応するのだろう。

5月 132019
 

概要

参照 RFC7230 6

  • HTTP は、リクエスト・レスポンスのセットを TCP コネクション上で送受信する
  • HTTP/1.0 の既定では、1 つのリクエスト・レスポンスが完了したら TCP コネクションは閉じられる
    • Connection: keep-alive リクエストヘッダーにより TCP コネクションを閉じず再利用する持続的接続 (Persistent Connection) ができるようになった
  • HTTP/1.1 では持続的接続は既定で有効であり、 Connection: keep-alive は必要ない
    • HTTP/1.0 サーバーとの持続的接続を望む場合は送信される
  • HTTP/1.1 における「コネクション」とは、メッセージ経路全体ではなく隣接ノード間 (クライアントとプロキシ間など) のコネクションのことを指す

Continue reading »

5月 082019
 

自作プロキシ (Nekoxy2) の WebSocket (RFC6455) 対応にあたっての私なりの理解をまとめました。

概要

WebSocket 自体はかなり単純で、TCP 上で投げっぱなし全二重通信をする方法と、HTTP/1.1 からのプロトコル アップグレード方法 (WebSocket の開始方法) が定義されているだけです。
実際に何を通信するかはサブプロトコル等のアプリケーション側にお任せとなります。

WebSocket over HTTP/2 (RFC8441) では、この内アップグレード方法が HTTP/2 向けに新しく定義されただけで、通信方法は同一となります。
※ 詳細は HTTP/2 理解メモ 参照。

注意点としては、接続・切断については到達保証がありますが、それ以外のメッセージには到達保証がないため、必要に応じてアプリケーション等で実装する必要があります。

また HTTP が利用するコネクションを再利用する形となるため、経路上に非対応の透過プロキシなどが存在する場合に通信が失敗する可能性があります。

Continue reading »