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 »

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月 072019
 

HTTP/2 理解メモ同様に、自作プロキシ (Nekoxy2) で実装した際の HPACK (RFC7541) への自分なりの理解をまとめたものです。
解説とかは他サイトのほうが良いかと。

HPACK は RFC の Appendix に具体例がたくさん載っているので、分からなくなったらそこを眺めると良いでしょう。

※RFC7541 ではバイト数は厳密に「オクテット数」と表現されているが、ここではバイト数とオクテット数は同じ意味とする

Continue reading »

4月 262019
 

自作プロキシ (Nekoxy2) の HTTP/2 (RFC7540) 対応にあたっての私なりの理解をまとめました。
HTTP/2 の解説自体は他サイトのほうがわかりやすかったり正確だったりすると思うので、あくまでも参考程度に。

RFC においては SHOULD とか MUST とかの違いは重要ですが、ここに書くの面倒なので必要に応じて調べましょう。

HPACK(RFC7541) については RFC も別だし長いし記事を分けます。
HPACK 理解メモ – CAT EARS

Continue reading »

4月 192019
 

.NET Core 3.0 Preview 4 で HttpClient の HTTP/2 サポートが追加されたようですね。
Announcing .NET Core 3 Preview 4 | .NET Blog

今までの .NET Standard では SslStream 自体が HTTP/2 の事実上必須な機能(ALPN)に対応しておらず、.NET Standard 2.1 でようやくサポートされる見込みだったため、どうやらちゃんとくるようで一安心というところです。
(HttpClient についてはこれのせいかは不明ですが…… SocketsHttpHandler が HTTP/2 対応していなかったのは確か)

しかしながら .NET Framework 4.8 の方は .NET Standard 2.0 止まりになることになっているので、HTTP/2 サポートは今後あるのかどうかすら怪しいですね……

Given many of the API additions in .NET Standard 2.1 require runtime changes in order to be meaningful, .NET Framework 4.8 will remain on .NET Standard 2.0 rather than implement .NET Standard 2.1.
Announcing .NET Standard 2.1 | .NET Blog

とはいえ .NET Standard はあくまでも API 標準を定めただけで実装は各プラットフォーム依存ですから、動くようになる可能性はあるかも?

とりあえず .NET Framework は 4.8 の時点では HttpClient + HttpClientHandler では動作しそうにありません。
BCL 以外でなら WinHttpHandler を使い、HttpRequestMessage のバージョンを明示的に指定することで、利用できます(Win10 1607↑ + .NET FW 4.6↑ に限る)。
参考: How to make the .net HttpClient use http 2.0?

実は Core 2.0 までも Windows 環境に限れば WinHttpHandler に丸投げしていたようで、HttpClient で HTTP/2 が動作します。
Core 2.1 以降 SocketsHttpHandler に移行し、環境依存を減らした為、HTTP/2 に一時的に非対応となっていたようです。

HttpClient の HTTP/2 対応

  • .NET Framework
    • HttpClientHandler では利用不可
    • WinHttpHandler (要NuGet & Win10 1607)を利用すれば利用可
  • .NET Core
    • ~2.0 : Win10 1607~のみ利用可?
      • WinHttpHandler を使ってる模様
    • 2.1~2.2 : 利用不可
      • SocketsHttpHandler に移行したため
      • ただし WinHttpHandler を利用するよう構成すれば Windows では利用可
    • 3.0~ : 利用可
      • SocketsHttpHandler の HTTP/2 対応?

Continue reading »