HTTP/2.0 Header Compressionの個人的メモ

この文書は古くなっています。
HTTP/2のヘッダ圧縮の仕組みはHPACKとしてRFC 7541で標準化されました。下記説明と大分違うものです。



SPDY/3のコピーから始まったHTTP2.0だが、ヘッダの圧縮についても大きく変更が加えられた。
SPDYでは辞書付きのdeflate圧縮方式を使用していたが、CRIME攻撃の存在や、CPUリソースの消費の観点より、別の手法を取ることが決定されていた。


幾つかの仕様が提出され、議論が重ねられ、現在HTTP2.0 draft04では「HTTP/2.0 Header Compression」(URL)という仕様がリファレンスに挙げられている。


現在の「HTTP/2.0 Header Compression」はHeader Diffと言う仕様が元になっていて、以下の2つの特徴を持つ。

  • HTTPで一般的によく使用されるヘッダ(accept-charset、user-agent等)は、辞書情報(Header Table)のindexを用いて送信できる。
  • 1つのコネクション中では、一つ前に送ったヘッダの差分のみを送信する。これにより、同じようなヘッダを毎回送る必要が無くなった。


次に、Header TableとReference Setの説明を行う。

Header Table

Index、Header Name、Header Valueからなる表である。クライアントとサーバ間でそれぞれ保持されており、HTTPリクエスト、HTTPレスポンスでよく使用されるヘッダが事前に入っている(仕様で決められている)。テーブルにないヘッダも、送信するごとにこのテーブルにもそのデータが追加されていく(オプションで指定される)。
初期値は以下のようなデータである。

Index Header Name Header Value
0 :scheme http
1 :scheme https
2 :host
3 :path /
4 :method GET
5 accept
34 te
35 upgrade
36 via
37 warning

送りたいヘッダがこのHeader Tableにあった場合は、indexを指定してヘッダを送ることが出来る。

  • Header NameとHeader Valueの両方がマッチしていれば、indexだけを送信する
  • Header Nameのみマッチしていれば、indexとvalueだけを送信する
  • Header Nameがマッチしなければ、nameとvalue両方を送信する

Reference Set

クライアントとサーバ間でそれぞれ保持している。送信されたHTTPヘッダの情報が格納される(最初は空)。次のHTTPリクエストを送信する際は、このReference Setの差分のみを送信すれば良くなる。

一度目に以下のヘッダを送信する場合

:path /my-example/index.html
user-agent my-user-agent
x-my-header first
  • :path はHeader Tableにあるので、index=3,value=/my-example/index.htmlという情報を送る
  • user-agentは同様に index=12,value=my-user-agentという情報を送る
  • x-my-headerは name=x-my-header,value=firstという情報を送る


この時のReference Setは以下のようになっている(クライアントとサーバでそれぞれ保持している)

:path, /my-example/index.html
user-agent, my-user-agent
x-my-header, first

又、ヘッダを付加する際にHeader Tableへも追加されており(オプションで指定可能)、Header Tableは以下のようになる。

0 :scheme http
1 :scheme https
... ... ...
37 warning
38 :path /my-example/index.html
39 user-agent my-user-agent
40 x-my-header first


なので、二度目に以下のヘッダを送信する場合

:path /my-example/resources/script.js
user-agent my-user-agent
x-my-header second
  • Reference Setより「:path, /my-example/index.html」と「x-my-header, first」を削除(それぞれ1byteで指定出来る)という情報を送る
  • :path はid=38,value=/my-example/resources/script.jsという情報を送る
  • x-my-header はid=40,value=secondという情報を送る


この時のReference Setは以下のようになっている

:path, /my-example/resources/script.js
user-agent, my-user-agent
x-my-header, second