| インターネット技術タスクフォース (IETF) | R. Peon |
| Request for Comments: 7541 | Google, Inc |
| カテゴリ: 標準トラック | H. Ruellan |
| ISSN: 2070-1721 | Canon CRF |
| 2015年5月 |
HPACK: HTTP/2 のヘッダー圧縮
概要
本仕様書は、HTTP/2 で使用される HTTP ヘッダフィールドを効率的に表現するための圧縮形式である HPACK を定義します。
本メモの状態
これはインターネット標準トラックの文書です。
この文書はインターネット技術タスクフォース (IETF) の成果物です。IETF コミュニティのコンセンサスを示しています。公開レビューを受け、Internet Engineering Steering Group (IESG) によって公開が承認されています。インターネット標準に関する詳細は RFC 5741 のセクション 2 を参照してください。
この文書の現在の状態、訂正情報 (errata)、およびフィードバックの提供方法に関する情報は、http://www.rfc-editor.org/info/rfc7541 で入手できます。
Copyright Notice
Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
1. 導入
HTTP/1.1([RFC7230]参照)では、ヘッダフィールドは圧縮されません。ウェブページが数十から数百に及ぶリクエストを必要とするようになるにつれて、これらのリクエストに含まれる冗長なヘッダフィールドは不要に帯域を消費し、遅延を明確に増大させます。
SPDY [SPDY] は当初、ヘッダフィールドを DEFLATE [DEFLATE] 形式で圧縮することでこの冗長性に対処しましたが、この手法は CRIME(Compression Ratio Info-leak Made Easy)攻撃によって示されたとおり、セキュリティ上のリスクを露呈しました([CRIME]参照)。
本仕様は HPACK を定義します。HPACK は冗長なヘッダフィールドを排除し、既知のセキュリティ攻撃に対する脆弱性を制限し、資源が限られた環境での使用に適した有界のメモリ要件を持ちます。HPACK に関する潜在的なセキュリティ上の懸念は セクション 7 に記載されています。
HPACK フォーマットは意図的に単純で柔軟性を持たないように設計されています。これらの特性は実装エラーによる相互運用性やセキュリティの問題のリスクを低減します。拡張機構は定義されておらず、フォーマットの変更は完全な置換を定義することによってのみ可能です。
1.1. 概要
本仕様で定義される形式は、ヘッダフィールドのリストを重複するペアを含むことができる順序付けられた名前と値のペアの集合として扱います。名前と値はオクテットの不透明な列として扱われ、圧縮および伸長後もヘッダフィールドの順序は保持されます。
エンコードはヘッダフィールドをインデックス値にマップするヘッダフィールドテーブルによって情報が提供されます。これらのヘッダフィールドテーブルは、新しいヘッダフィールドがエンコードまたはデコードされる際に逐次的に更新できます。
エンコード形式では、ヘッダフィールドはリテラルとして表現されるか、ヘッダフィールドテーブル中のエントリへの参照として表現されます。したがって、ヘッダフィールドのリストは参照とリテラル値の混合でエンコードできます。
リテラル値は直接エンコードされるか、静的ハフマン符号を使用します。
どのヘッダフィールドをヘッダフィールドテーブルの新しいエントリとして挿入するかはエンコーダの責任です。デコーダはエンコーダによって指示されたヘッダフィールドテーブルへの修正を実行し、その過程でヘッダフィールドのリストを再構築します。これによりデコーダは単純なままで、さまざまなエンコーダと相互運用できるようになります。
ヘッダフィールドを表現するためのこれらのさまざまなメカニズムの使用例は、付録 C にあります。
1.2. 規約
本書で用いるキーワード「MUST」「MUST NOT」「REQUIRED」「SHALL」「SHALL NOT」「SHOULD」「SHOULD NOT」「RECOMMENDED」「MAY」「OPTIONAL」は、RFC 2119 に記載されているとおりに解釈されるものとします。
すべての数値はネットワークバイトオーダーで表されます。値は特に明示されない限り符号なしです。リテラル値は適切に10進または16進で示されます。
1.3. 用語
本仕様では次の用語を使用します:
- Header Field:
- 名前と値のペア。名前と値はともにオクテットの不透明な列として扱われます。
- Dynamic Table:
- 動的テーブル(セクション 2.3.2参照)は、格納されたヘッダフィールドをインデックス値に関連付けるテーブルです。このテーブルは動的で、エンコードまたはデコードのコンテキストに特有です。
- Static Table:
- 静的テーブル(セクション 2.3.1参照)は、頻繁に出現するヘッダフィールドを静的にインデックス値に関連付けたテーブルです。このテーブルは順序付けられ、読み取り専用で常にアクセス可能であり、すべてのエンコードまたはデコードのコンテキスト間で共有される場合があります。
- Header List:
- ヘッダリストは、共同でエンコードされる順序付けられたヘッダフィールドの集合で、重複するヘッダフィールドを含むことがあります。HTTP/2 ヘッダブロックに含まれる完全なヘッダフィールドの一覧はヘッダリストです。
- Header Field Representation:
- ヘッダフィールドは、エンコードされた形式でリテラルとして、またはインデックスとして表現できます(セクション 2.4参照)。
- Header Block:
- ヘッダフィールド表現の順序付けられたリストで、これをデコードすると完全なヘッダリストが得られます。
2. 圧縮プロセスの概要
本仕様はエンコーダのための特定のアルゴリズムを記述するものではありません。代わりに、デコーダがどのように動作すべきかを正確に定義し、この定義が許す任意のエンコードをエンコーダが生成できるようにします。
2.1. ヘッダリストの順序
HPACK はヘッダリスト内のヘッダフィールドの順序を保持します。エンコーダはヘッダリスト中の元の順序に従ってヘッダブロック内のヘッダフィールド表現を順序付けなければなりません。デコーダはヘッダブロック内の順序に従ってデコードされたヘッダリスト内のヘッダフィールドを順序付けなければなりません。
2.2. エンコードおよびデコードのコンテキスト
ヘッダブロックを伸長するために、デコーダはデコードコンテキストとして動的テーブル(セクション 2.3.2参照)を維持するだけで十分です。他の動的状態は必要ありません。
HTTP のような双方向通信で使用される場合、エンドポイントが維持するエンコード用とデコード用の動的テーブルは完全に独立しています。つまり、リクエストとレスポンスの動的テーブルは別々です。
2.3. インデックステーブル
HPACK はヘッダフィールドをインデックスに関連付けるために二つのテーブルを使用します。静的テーブル(セクション 2.3.1参照)は事前定義され、一般的なヘッダフィールド(その多くは空の値)を含みます。動的テーブル(セクション 2.3.2参照)は動的で、エンコーダがエンコードされたヘッダリストで繰り返されるヘッダフィールドをインデックスするために使用できます。
これら二つのテーブルは、インデックス値を定義するために単一のアドレス空間に結合されます(セクション 2.3.3参照)。
2.3.1. 静的テーブル
静的テーブルは事前定義された静的なヘッダフィールドのリストで構成されます。そのエントリは 付録 A に定義されています。
2.3.2. 動的テーブル
動的テーブルは先入れ先出し(FIFO)順で維持されるヘッダフィールドのリストで構成されます。動的テーブルの最初で最新のエントリは最も低いインデックスにあり、動的テーブルの最も古いエントリは最も高いインデックスにあります。
動的テーブルは最初は空です。各ヘッダブロックが伸長されるたびにエントリが追加されます。
動的テーブルは重複するエントリ(同じ名前かつ同じ値を持つエントリ)を含むことができます。したがって、デコーダは重複エントリをエラーとして扱ってはなりません。
エンコーダは動的テーブルをどのように更新するかを決定できるため、動的テーブルが使用するメモリ量を制御できます。デコーダのメモリ要件を制限するために、動的テーブルのサイズは厳密に制限されます(セクション 4.2参照)。
デコーダはヘッダフィールド表現のリストを処理する過程で動的テーブルを更新します(セクション 3.2参照)。
2.3.3. インデックスアドレス空間
静的テーブルと動的テーブルは単一のインデックスアドレス空間に結合されます。
静的テーブルの長さ(含む)までの 1 からのインデックスは静的テーブル内の要素を参照します(セクション 2.3.1参照)。
静的テーブルの長さより大きいインデックスは動的テーブル内の要素を参照します(セクション 2.3.2参照)。動的テーブルへのインデックスを求めるには静的テーブルの長さを差し引きます。
両テーブルの長さの合計を超えるインデックスはデコードエラーとして扱われなければなりません。
静的テーブルのサイズを s、動的テーブルのサイズを k とした場合、次の図は有効なインデックスアドレス空間全体を示します。
<---------- Index Address Space ---------->
<-- Static Table --> <-- Dynamic Table -->
+---+-----------+---+ +---+-----------+---+
| 1 | ... | s | |s+1| ... |s+k|
+---+-----------+---+ +---+-----------+---+
^ |
| V
Insertion Point Dropping Point
図 1: インデックスアドレス空間
2.4. ヘッダフィールド表現
エンコードされたヘッダフィールドは、インデックスまたはリテラルのいずれかで表現できます。
インデックス表現は、ヘッダフィールドを静的テーブルまたは動的テーブル内のエントリへの参照として定義します(セクション 6.1参照)。
リテラル表現は、その名前と値を指定することでヘッダフィールドを定義します。ヘッダフィールド名はリテラルとして表現するか、静的テーブルまたは動的テーブル内のエントリへの参照として表現できます。ヘッダフィールド値はリテラルとして表現されます。
三種類の異なるリテラル表現が定義されています:
- 動的テーブルの先頭にヘッダフィールドを新しいエントリとして追加するリテラル表現(セクション 6.2.1参照)。
- ヘッダフィールドを動的テーブルに追加しないリテラル表現(セクション 6.2.2参照)。
- ヘッダフィールドを動的テーブルに追加しないリテラル表現で、さらにこのヘッダフィールドは常にリテラル表現を使用するという条件(特に仲介者によって再エンコードされる場合)を付けたもの(セクション 6.2.3参照)。この表現は、圧縮によって危険にさらされてはならないヘッダフィールド値を保護することを目的としています(詳細は セクション 7.1.3 を参照)。
これらのリテラル表現の選択は、機密性の高いヘッダフィールド値を保護するためにセキュリティ上の考慮に基づいて行われることがあります(セクション 7.1参照)。
ヘッダフィールド名またはヘッダフィールド値のリテラル表現は、オクテット列を直接エンコードするか、静的ハフマン符号を使用してエンコードすることができます(セクション 5.2参照)。
3. ヘッダブロックのデコード
3.1. ヘッダブロック処理
デコーダは元のヘッダリストを再構築するためにヘッダブロックを順次処理します。
ヘッダブロックはヘッダフィールド表現の連結です。さまざまなヘッダフィールド表現の詳細は セクション 6 に記述されています。
ヘッダフィールドがデコードされて再構築されたヘッダリストに追加されると、そのヘッダフィールドを取り除くことはできません。ヘッダリストに追加されたヘッダフィールドは安全にアプリケーションに渡すことができます。
結果のヘッダフィールドをアプリケーションに渡すことにより、デコーダは動的テーブルに必要なメモリに加えて最小限の一時的メモリコミットで実装できます。
3.2. ヘッダフィールド表現の処理
ヘッダブロックを処理してヘッダリストを得る方法は本節で定義されています。デコードが正常にヘッダリストを生成することを確実にするために、デコーダは以下の規則に従わなければなりません。
ヘッダブロックに含まれるすべてのヘッダフィールド表現は、以下に指定されたとおりに出現順に処理されます。さまざまなヘッダフィールド表現の書式や追加の処理指示の詳細は セクション 6 にあります。
強調された indexed representation(インデックス表現)は次の動作を伴います:
- 静的テーブルまたは動的テーブルで参照されたエントリに対応するヘッダフィールドがデコード済みヘッダリストに追加されます。
強調された literal representation でかつ 動的テーブルに追加されない 表現は次の動作を伴います:
- ヘッダフィールドがデコード済みヘッダリストに追加されます。
強調された literal representation でかつ 動的テーブルに追加される 表現は次の動作を伴います:
- ヘッダフィールドがデコード済みヘッダリストに追加されます。
- ヘッダフィールドが動的テーブルの先頭に挿入されます。この挿入は動的テーブル内の以前のエントリの追い出しを引き起こす可能性があります(セクション 4.4参照)。
4. 動的テーブル管理
デコーダ側のメモリ要件を制限するために、動的テーブルのサイズは制約されます。
4.1. テーブルサイズの計算
動的テーブルのサイズは、そのエントリのサイズの合計です。
エントリのサイズは、その名前のオクテット長(セクション 5.2で定義される)、値のオクテット長、および 32 の合計です。
エントリのサイズは、名前と値の長さをハフマン符号化を適用しない状態で用いて計算されます。
4.2. 最大テーブルサイズ
HPACK を使用するプロトコルは、エンコーダが動的テーブルに使用できる最大サイズを決定します。HTTP/2 では、この値は SETTINGS_HEADER_TABLE_SIZE 設定によって決定されます(RFC 7540 セクション 6.5.2参照)。
エンコーダはこの最大サイズより小さい容量を使用することを選択できます(セクション 6.3参照)が、選択したサイズはプロトコルで定められた最大値以下でなければなりません。
動的テーブルの最大サイズの変更は、動的テーブルサイズ更新によって通知されます(セクション 6.3参照)。この動的テーブルサイズ更新は、サイズ変更に続く最初のヘッダブロックの冒頭で発生しなければなりません。HTTP/2 では、これは設定の確認応答に続きます(RFC 7540 セクション 6.5.3参照)。
複数の最大テーブルサイズの更新が 2 つのヘッダブロックの送信間に発生することがあります。この間にサイズが複数回変更された場合、その間に発生した最小の最大テーブルサイズを動的テーブルサイズ更新で通知しなければなりません。最終的な最大サイズは常に通知されるため、結果として最大で 2 回の動的テーブルサイズ更新が行われます。これによりデコーダは動的テーブルサイズの縮小に基づく追い出しを実行できます(セクション 4.3参照)。
この仕組みは最大サイズを 0 に設定することで動的テーブルからエントリを完全にクリアするために使用でき、その後復元することができます。
4.3. 動的テーブルサイズ変更時のエントリ削除
動的テーブルの最大サイズが縮小されるたびに、動的テーブルの末尾からエントリが削除され、動的テーブルのサイズが最大サイズ以下になるまで続けられます。
4.4. 新しいエントリ追加時のエントリ削除
新しいエントリを動的テーブルに追加する前に、動的テーブルのサイズが (最大サイズ - 新しいエントリのサイズ) 以下になるか、テーブルが空になるまで、動的テーブルの末尾からエントリが削除されます。
新しいエントリのサイズが最大サイズ以下であれば、そのエントリはテーブルに追加されます。新しいエントリが最大サイズより大きい場合に追加を試みてもエラーにはなりませんが、その試みは既存のすべてのエントリをテーブルから空にする結果となり、空のテーブルになります。
新しいエントリは、動的テーブルにこの新しいエントリを追加するときに追い出される動的テーブル内のエントリの名前を参照することがあります。実装は、参照されたエントリが新しいエントリを挿入する前に追い出される場合に、参照された名前を削除しないよう注意する必要があります。
5. 原始型の表現
HPACK エンコーディングは 2 つの原始型を使用します:符号なし可変長整数とオクテット列の文字列です。
5.1. 整数表現
整数は名前インデックス、ヘッダフィールドインデックス、または文字列長を表すために使用されます。整数表現はオクテット内の任意の位置から開始できます。最適化された処理を可能にするため、整数表現は常にオクテットの終わりで終了します。
整数は 2 部分で表されます:現在のオクテットを埋めるプレフィックスと、整数値がプレフィックスに収まらない場合に使用されるオプションのオクテット列です。プレフィックスのビット数(N と呼ばれる)は整数表現のパラメータです。
整数値が十分小さい場合、すなわち 2N-1 より厳密に小さい場合は、N ビットのプレフィックス内にエンコードされます。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | ? | ? | ? | Value | +---+---+---+-------------------+
図 2: プレフィックス内にエンコードされた整数値(N = 5 の例)
それ以外の場合、プレフィックスのすべてのビットは 1 に設定され、値は 2N-1 減算され、1 個以上のオクテットからなるリストを使ってエンコードされます。各オクテットの最上位ビットは継続フラグとして使用され、リスト内の最後のオクテットを除いて 1 に設定されます。オクテットの残りのビットは、減算後の値をエンコードするために使用されます。
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| ? | ? | ? | 1 1 1 1 1 |
+---+---+---+-------------------+
| 1 | Value-(2^N-1) LSB |
+---+---------------------------+
...
+---+---------------------------+
| 0 | Value-(2^N-1) MSB |
+---+---------------------------+
図 3: プレフィックスの後にエンコードされた整数値(N = 5 の例)
オクテット列から整数値をデコードする際は、まずリスト内のオクテットの順序を逆にします。次に各オクテットについてその最上位ビットを取り除きます。オクテットの残りのビットを連結し、得られた値に 2N-1 を加えて整数値を得ます。
プレフィックスのサイズ N は常に 1 から 8 ビットの間です。オクテット境界で始まる整数は 8 ビットのプレフィックスを持ちます。
整数 I を表す擬似コードは次のとおりです:
if I < 2^N - 1, encode I on N bits
else
encode (2^N - 1) on N bits
I = I - (2^N - 1)
while I >= 128
encode (I % 128 + 128) on 8 bits
I = I / 128
encode I on 8 bits
整数 I をデコードする擬似コードは次のとおりです:
decode I from the next N bits
if I < 2^N - 1, return I
else
M = 0
repeat
B = next octet
I = I + (B & 127) * 2^M
M = M + 7
while B & 128 == 128
return I
整数のエンコード例は 付録 C.1 にあります。
この整数表現は無限大の大きさの値を許容します。また、エンコーダが大量のゼロ値を送信することも可能で、オクテットを浪費したり整数値をオーバーフローさせたりする可能性があります。実装が許容する限界(値またはオクテット長)を超える整数エンコードはデコードエラーとして扱われなければなりません。用途ごとに実装制約に基づいて異なる上限を設定することができます。
5.2. 文字列リテラル表現
ヘッダフィールド名とヘッダフィールド値は文字列リテラルとして表現できます。文字列リテラルはオクテット列としてエンコードされ、文字列リテラルのオクテットを直接エンコードするか、ハフマン符号を使用してエンコードします(HUFFMAN参照)。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | H | String Length (7+) | +---+---------------------------+ | String Data (Length octets) | +-------------------------------+
図 4: 文字列リテラル表現
文字列リテラル表現は次のフィールドを含みます:
- H:
- 文字列のオクテットがハフマン符号化されているかどうかを示す 1 ビットのフラグ H。
- String Length:
- 文字列リテラルをエンコードするために使われるオクテット数。7 ビットプレフィックスの整数でエンコードされます(セクション 5.1参照)。
- String Data:
- 文字列リテラルのエンコードされたデータ。H が '0' の場合、エンコードデータは文字列リテラルの生のオクテットです。H が '1' の場合、エンコードデータは文字列リテラルのハフマン符号です。
ハフマン符号を用いる文字列リテラルは、付録 B に定義されたハフマン符号でエンコードされます(リクエストの例は 付録 C.4、レスポンスの例は 付録 C.6 を参照)。エンコードデータは文字列リテラルの各オクテットに対応するコードのビット単位での連結です。
ハフマン符号化データは常にオクテット境界で終わるとは限らないため、次のオクテット境界までパディングが挿入されます。このパディングを文字列リテラルの一部と誤解されないようにするため、EOS(end-of-string)シンボルに対応するコードの最上位ビットが使用されます。
デコード時に、エンコードデータの末尾の不完全なコードはパディングと見なして破棄されます。7 ビットを超えるパディングはデコードエラーとして扱われなければなりません。EOS シンボルのコードの最上位ビットに対応しないパディングはデコードエラーとして扱われなければなりません。EOS シンボルを含むハフマン符号化された文字列リテラルはデコードエラーとして扱われなければなりません。
6. バイナリフォーマット
本節では、各種ヘッダフィールド表現と動的テーブルサイズ更新命令の詳細なフォーマットについて説明します。
6.1. インデックス付きヘッダフィールド表現
インデックス付きヘッダフィールド表現は、静的テーブルまたは動的テーブルのエントリを識別します(セクション 2.3参照)。
インデックス付きヘッダフィールド表現は、セクション 3.2に記載されているように、デコード済みヘッダリストにヘッダフィールドを追加する原因となります。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 1 | Index (7+) | +---+---------------------------+
図 5: インデックス付きヘッダフィールド
インデックス付きヘッダフィールドは先頭に '1' の 1 ビットパターンが付き、その後に 7 ビットプレフィックスの整数として表現された一致するヘッダフィールドのインデックスが続きます(セクション 5.1参照)。
インデックス値 0 は使用されません。インデックス付きヘッダフィールド表現で 0 が見つかった場合はデコードエラーとして扱わなければなりません。
6.2. リテラルヘッダフィールド表現
リテラルヘッダフィールド表現はリテラルのヘッダフィールド値を含みます。ヘッダフィールド名はリテラルとして提供されるか、静的テーブルまたは動的テーブル内の既存エントリへの参照として提供されます(セクション 2.3参照)。
本仕様は、インデックス付き、インデックスなし、決してインデックスされない、の 3 形式のリテラルヘッダフィールド表現を定義します。
6.2.1. インクリメンタルインデックス付きリテラルヘッダフィールド
インクリメンタルインデックス付きリテラルヘッダフィールド表現は、ヘッダフィールドをデコード済みヘッダリストに追加し、それを新しいエントリとして動的テーブルに挿入する結果となります。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | Index (6+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 6: インクリメンタルインデックス付きリテラルヘッダフィールド — インデックスされた名前
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 7: インクリメンタルインデックス付きリテラルヘッダフィールド — 新しい名前
インクリメンタルインデックス付きリテラルヘッダフィールド表現は先頭に '01' の 2 ビットパターンで始まります。
ヘッダフィールド名が静的テーブルまたは動的テーブルに格納されたエントリのヘッダフィールド名と一致する場合、そのヘッダフィールド名はそのエントリのインデックスを用いて表現できます。この場合、エントリのインデックスは 6 ビットプレフィックスの整数として表現されます(セクション 5.1参照)。この値は常にゼロでありません。
それ以外の場合、ヘッダフィールド名は文字列リテラルとして表現されます(セクション 5.2参照)。この場合、6 ビットインデックスの代わりに値 0 が使用され、その後にヘッダフィールド名が続きます。
どちらの形式のヘッダフィールド名の表現の後にも、ヘッダフィールド値が文字列リテラルとして続きます(セクション 5.2参照)。
6.2.2. インデックスなしリテラルヘッダフィールド
インデックスなしリテラルヘッダフィールド表現は、動的テーブルを変更せずにヘッダフィールドをデコード済みヘッダリストに追加する結果となります。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 0 | Index (4+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 8: インデックスなしリテラルヘッダフィールド — インデックスされた名前
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 0 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 9: インデックスなしリテラルヘッダフィールド — 新しい名前
インデックスなしリテラルヘッダフィールド表現は先頭に '0000' の 4 ビットパターンで始まります。
ヘッダフィールド名が静的テーブルまたは動的テーブルに格納されたエントリのヘッダフィールド名と一致する場合、そのヘッダフィールド名はそのエントリのインデックスを用いて表現できます。この場合、エントリのインデックスは 4 ビットプレフィックスの整数として表現されます(セクション 5.1参照)。この値は常にゼロでありません。
それ以外の場合、ヘッダフィールド名は文字列リテラルとして表現されます(セクション 5.2参照)。この場合、4 ビットインデックスの代わりに値 0 が使用され、その後にヘッダフィールド名が続きます。
どちらの形式のヘッダフィールド名の表現の後にも、ヘッダフィールド値が文字列リテラルとして続きます(セクション 5.2参照)。
6.2.3. 決してインデックスされないリテラルヘッダフィールド
決してインデックスされないリテラルヘッダフィールド表現は、動的テーブルを変更せずにヘッダフィールドをデコード済みヘッダリストに追加する結果となります。仲介者はこのヘッダフィールドをエンコードする際に同じ表現を使用しなければなりません。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | Index (4+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 10: 決してインデックスされないリテラルヘッダフィールド — インデックスされた名前
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+
図 11: 決してインデックスされないリテラルヘッダフィールド — 新しい名前
決してインデックスされないリテラルヘッダフィールド表現は先頭に '0001' の 4 ビットパターンで始まります。
ヘッダフィールドが決してインデックスされないリテラルとして表現される場合、そのヘッダフィールドは常にこの特定のリテラル表現でエンコードされなければなりません。特に、ピアが決してインデックスされないリテラルとして受信したヘッダフィールドを送信する場合、同じ表現を用いて転送しなければなりません。
この表現は、圧縮によって危険にさらされるべきでないヘッダフィールド値を保護するために意図されています(詳細は セクション 7.1 を参照)。
この表現のエンコードは、インデックスなしリテラルヘッダフィールドのエンコードと同一です(セクション 6.2.2参照)。
6.3. 動的テーブルサイズの更新
動的テーブルサイズ更新は、動的テーブルのサイズの変更を通知します。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 1 | Max size (5+) | +---+---------------------------+
図 12: 最大動的テーブルサイズの変更
動的テーブルサイズ更新は先頭に '001' の 3 ビットパターンが付き、その後に 5 ビットプレフィックスの整数として表現された新しい最大サイズが続きます(セクション 5.1参照)。
新しい最大サイズは、HPACK を使用するプロトコルで決定された制限以下でなければなりません。この制限を超える値はデコードエラーとして扱われなければなりません。HTTP/2 では、この制限はデコーダから受け取られエンコーダが確認した SETTINGS_HEADER_TABLE_SIZE パラメータの最後の値です(RFC 7540 セクション 6.5.2および セクション 6.5.3参照)。
動的テーブルの最大サイズを縮小するとエントリが追い出される可能性があります(セクション 4.3参照)。
7. セキュリティ考慮事項
本節では HPACK に関する潜在的なセキュリティ上の懸念領域について説明します:
- 共有された圧縮コンテキストに圧縮される秘密についての推測を検証するための、長さに基づくオラクルとしての圧縮の利用。
- デコーダ側の処理能力またはメモリ容量を使い果たすことによるサービス拒否(DoS)。
7.1. 動的テーブル状態のプロービング
HPACK は HTTP のようなプロトコルに内在する冗長性を利用してヘッダフィールドのエンコード長を短縮します。最終的な目的は、HTTP リクエストやレスポンスを送信するために必要なデータ量を削減することです。
ヘッダフィールドをエンコードするために使用される圧縮コンテキストは、エンコードされて送信されるヘッダフィールドを定義でき、そのエンコード後の長さを観測できる攻撃者によってプローブされ得ます。攻撃者が双方を行える場合、動的テーブルの状態に関する推測を確認するためにリクエストを適応的に変更できます。推測がより短い長さに圧縮されれば、攻撃者はエンコード長を観測してその推測が正しかったと推論できます。
これはトランスポート層セキュリティ(TLS)([TLS12]参照)上でも可能です。TLS はコンテンツに対する機密性を提供しますが、その長さに対しては限定的な保護しか提供しないためです。
CRIME(CRIME [CRIME])のような攻撃は、これらの一般的な攻撃者能力の存在を実証しました。具体的には、DEFLATE(DEFLATE [DEFLATE])がプレフィックス一致に基づいて冗長性を除去する性質を悪用したため、攻撃者は文字を1つずつ確認でき、指数時間の攻撃を線形時間の攻撃に変換できました。
7.1.1. HPACK および HTTP への適用性
HPACK は、推測を個々の文字ではなくヘッダフィールド値全体に一致させることを強制することで、CRIME に類する攻撃を緩和しますが完全には防止しません。攻撃者は推測が正しいか否かしか学べないため、ヘッダフィールド値に対して総当たり的な推測に頼らざるを得なくなります。
したがって特定のヘッダフィールド値を復元できるかどうかは値のエントロピーに依存します。エントロピーが高い値は復元される可能性が低く、エントロピーが低い値は依然として脆弱です。
この種の攻撃は、2 つの相互に信頼しないエンティティが単一の HTTP/2 接続上に配置される任意のときに可能です。共有された HPACK 圧縮器が一方のエンティティに動的テーブルへエントリを追加させ、他方のエンティティにこれらのエントリへアクセスさせることを許す場合、テーブルの状態を学習され得ます。
相互に信頼しないエンティティからのリクエストやレスポンスが生じるのは、仲介者が次のいずれかを行うときです:
- 複数のクライアントからのリクエストを単一の接続でオリジンサーバに送信する、または
- 複数のオリジンサーバからのレスポンスを集めてクライアントに向けて共有接続に載せる。
また、ウェブブラウザは同一接続上で異なる web origins([ORIGIN])によって行われるリクエストが相互に信頼しないエンティティによるものであると仮定する必要があります。
7.1.2. 緩和策
ヘッダフィールドの機密性を必要とする HTTP の利用者は、推測を事実上不可能にするエントロピーを持つ値を使用できます。しかしこれは一般的な解決策としては実用的ではありません。なぜなら全ての HTTP 利用者に対して攻撃を緩和する手段を講じさせることになり、HTTP の利用方法に新たな制約を課すことになるからです。
HTTP 利用者に制約を課す代わりに、HPACK の実装は圧縮の適用方法を制限して動的テーブルのプロービングの可能性を制限することができます。
理想的な解決策は、ヘッダフィールドを構築する主体に基づいて動的テーブルへのアクセスを分離することです。テーブルに追加されるヘッダフィールド値は主体に帰属させ、その値を作成した主体だけがその値を抽出できるようにします。
圧縮性能を向上させるために、特定のエントリを公開としてタグ付けすることも考えられます。例えば、ウェブブラウザは Accept-Encoding ヘッダフィールドの値を全てのリクエストで利用可能にするかもしれません。
ヘッダフィールドの由来(provenance)に関して十分な知見を持たないエンコーダは、代わりに多様な値を持つヘッダフィールドにペナルティを導入することができます。つまり多くの推測試行が行われたヘッダフィールドは将来的に動的テーブルのエントリと比較されなくなり、結果的にさらなる推測を事実上防止する、という方法です。
この応答はヘッダフィールド値の長さに反比例するように行われるかもしれません。つまり、短い値に対してはより速く、または高い確率で「もはや動的テーブルを使わない」とマークすることが起こり得ます。
7.1.3. インデックスされないリテラル
実装は機密性の高いヘッダフィールドを保護するために、それらを圧縮せず代わりにリテラルとして値をエンコードすることを選択できます。
ヘッダフィールドに対してインデックス表現を生成しないことは、すべてのホップで圧縮を回避する場合にのみ有効です。決してインデックスされないリテラル(セクション 6.2.3参照)は、特定の値が意図的にリテラルとして送信されたことを仲介者に示すために使用できます。
仲介者は、決してインデックスされないリテラル表現で受信した値を、インデックスする別の表現で再エンコードしてはなりません。HPACK が再エンコードに使われる場合、決してインデックスされないリテラル表現を用いなければなりません。
ヘッダフィールドに対して決してインデックスされないリテラル表現を選ぶかどうかは複数の要因によります。HPACK はヘッダフィールド値全体の推測に対して防護しないため、短いまたはエントロピーの低い値は攻撃者により容易に復元され得ます。したがって、エンコーダはエントロピーの低い値をインデックスしないことを選択するかもしれません。
エンコーダはまた、Cookie や Authorization のように回復されると非常に価値がある、あるいは機密と見なされるヘッダフィールドの値をインデックスしないことを選ぶかもしれません。
逆に、露見してもほとんど価値がないヘッダフィールド値に対してはインデックスを好む場合もあります。例えば User-Agent ヘッダフィールドはリクエスト間で一般にあまり変化せず任意のサーバに送信されます。その場合、特定の User-Agent 値が使用されたことを確認できることはほとんど価値を持ちません。
これらの「決してインデックスされないリテラル表現を使用するかどうか」の判断基準は、新たな攻撃が発見されるにつれて時間とともに変化することに注意してください。
7.2. 静的ハフマン符号化
現時点で静的ハフマン符号化に対する既知の攻撃はありません。ある研究では静的ハフマン符号表の使用が情報漏えいを生むことを示しましたが、その研究は攻撃者がその情報漏えいを利用して意味のある量の情報を回復できるとは結論付けていません([PETAL]参照)。
7.3. メモリ消費
攻撃者はエンドポイントのメモリを使い果たそうと試みることができます。HPACK はエンドポイントが割り当てるメモリのピーク量と状態量の両方を制限するように設計されています。
圧縮器が使用するメモリ量は、動的テーブルの最大サイズの定義を通じて HPACK を使用するプロトコルによって制限されます。HTTP/2 ではこの値はデコーダが SETTINGS_HEADER_TABLE_SIZE 設定パラメータで制御します(RFC 7540 セクション 6.5.2参照)。この制限は動的テーブルに格納されるデータのサイズと小さなオーバーヘッドの余裕を考慮に入れています。
デコーダは動的テーブルの最大サイズに適切な値を設定することで状態メモリ量を制限できます。HTTP/2 ではこれは SETTINGS_HEADER_TABLE_SIZE パラメータの適切な値の設定によって実現されます。エンコーダはデコーダが許可するよりも小さい動的テーブルサイズを通知することで自身が使用する状態メモリ量を制限できます(セクション 6.3参照)。
エンコーダやデコーダが消費する一時的メモリ量はヘッダフィールドを逐次処理することで制限できます。実装はヘッダフィールドの完全な一覧を保持する必要はありません。ただし、アプリケーションが他の理由で完全なヘッダリストを保持する必要があるかもしれないことに注意してください。HPACK はこれを強制しませんが、アプリケーションの制約がそれを必要にすることがあります。
7.4. 実装上の制限
HPACK の実装は、整数の大きな値、整数の長いエンコード、または長い文字列リテラルがセキュリティ上の弱点を生まないようにする必要があります。
8. 参考文献
8.1. 規範的参考文献
- [HTTP2]
- Belshe, M., Peon, R., and M. Thomson, Ed., “Hypertext Transfer Protocol Version 2 (HTTP/2)”, RFC 7540, DOI 10.17487/RFC7540, May 2015, <http://www.rfc-editor.org/info/rfc7540>.
- [RFC2119]
- Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.
- [RFC7230]
- Fielding, R., Ed. and J. Reschke, Ed., “Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing”, RFC 7230, DOI 10.17487/RFC7230, June 2014, <http://www.rfc-editor.org/info/rfc7230>.
8.2. 参考資料
- [CANONICAL]
- Schwartz, E. and B. Kallick, “Generating a canonical prefix encoding”, Communications of the ACM, Volume 7 Issue 3, pp. 166-169, March 1964, <https://dl.acm.org/citation.cfm?id=363991>.
- [CRIME]
- Wikipedia, “CRIME”, May 2015, <http://en.wikipedia.org/w/index.php?title=CRIME&oldid=660948120>.
- [DEFLATE]
- Deutsch, P., “DEFLATE Compressed Data Format Specification version 1.3”, RFC 1951, DOI 10.17487/RFC1951, May 1996, <http://www.rfc-editor.org/info/rfc1951>.
- [HUFFMAN]
- Huffman, D., “A Method for the Construction of Minimum-Redundancy Codes”, Proceedings of the Institute of Radio Engineers, Volume 40, Number 9, pp. 1098-1101, September 1952, <http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=4051119>.
- [ORIGIN]
- Barth, A., “The Web Origin Concept”, RFC 6454, DOI 10.17487/RFC6454, December 2011, <http://www.rfc-editor.org/info/rfc6454>.
- [PETAL]
- Tan, J. and J. Nahata, “PETAL: Preset Encoding Table Information Leakage”, April 2013, <http://www.pdl.cmu.edu/PDL-FTP/associated/CMU-PDL-13-106.pdf>.
- [SPDY]
- Belshe, M. and R. Peon, “SPDY Protocol”, Work in Progress, draft-mbelshe-httpbis-spdy-00, February 2012.
- [TLS12]
- Dierks, T. and E. Rescorla, “The Transport Layer Security (TLS) Protocol Version 1.2”, RFC 5246, DOI 10.17487/RFC5246, August 2008, <http://www.rfc-editor.org/info/rfc5246>.
付録 A. 静的テーブル定義
静的テーブル(セクション 2.3.1参照)は、事前定義され変更不可能なヘッダフィールドの一覧で構成されます。
静的テーブルは、一般的なウェブサイトで使用される頻繁なヘッダフィールドに基づいて作成され、HTTP/2 固有の疑似ヘッダフィールド(RFC 7540 セクション 8.1.2.1参照)を追加したものです。頻繁に現れる値がいくつかあるヘッダフィールドについては、それらの頻繁な値ごとにエントリが追加されました。他のヘッダフィールドについては、空の値でエントリが追加されています。
表 1 は静的テーブルを構成する事前定義されたヘッダフィールドを一覧にし、各エントリのインデックスを示します。
| Index | Header Name | Header Value |
|---|---|---|
| 1 | :authority | |
| 2 | :method | GET |
| 3 | :method | POST |
| 4 | :path | / |
| 5 | :path | /index.html |
| 6 | :scheme | http |
| 7 | :scheme | https |
| 8 | :status | 200 |
| 9 | :status | 204 |
| 10 | :status | 206 |
| 11 | :status | 304 |
| 12 | :status | 400 |
| 13 | :status | 404 |
| 14 | :status | 500 |
| 15 | accept-charset | |
| 16 | accept-encoding | gzip, deflate |
| 17 | accept-language | |
| 18 | accept-ranges | |
| 19 | accept | |
| 20 | access-control-allow-origin | |
| 21 | age | |
| 22 | allow | |
| 23 | authorization | |
| 24 | cache-control | |
| 25 | content-disposition | |
| 26 | content-encoding | |
| 27 | content-language | |
| 28 | content-length | |
| 29 | content-location | |
| 30 | content-range | |
| 31 | content-type | |
| 32 | cookie | |
| 33 | date | |
| 34 | etag | |
| 35 | expect | |
| 36 | expires | |
| 37 | from | |
| 38 | host | |
| 39 | if-match | |
| 40 | if-modified-since | |
| 41 | if-none-match | |
| 42 | if-range | |
| 43 | if-unmodified-since | |
| 44 | last-modified | |
| 45 | link | |
| 46 | location | |
| 47 | max-forwards | |
| 48 | proxy-authenticate | |
| 49 | proxy-authorization | |
| 50 | range | |
| 51 | referer | |
| 52 | refresh | |
| 53 | retry-after | |
| 54 | server | |
| 55 | set-cookie | |
| 56 | strict-transport-security | |
| 57 | transfer-encoding | |
| 58 | user-agent | |
| 59 | vary | |
| 60 | via | |
| 61 | www-authenticate |
付録 B. ハフマン符号
以下のハフマン符号は、文字列リテラルをハフマン符号化してエンコードするときに使用されます(セクション 5.2参照)。
このハフマン符号は、大量の HTTP ヘッダのサンプルから得られた統計に基づいて生成されました。これは標準化された(canonical)ハフマン符号であり([CANONICAL]参照)、いくつかの記号が一意の符号長を持たないように調整が加えられています。
表の各行は、記号を表現するために使用される符号を定義します:
- sym:
- 表現される記号。これはオクテットの 10 進数値で、必要に応じてその ASCII 表現が先頭に付されます。特に "EOS" は文字列リテラルの終端を示すために使用されます。
- code as bits:
- 記号のハフマン符号を、最上位ビット(MSB)に揃えた 2 進数として示したもの。
- code as hex:
- 記号のハフマン符号を、最下位ビット(LSB)に揃えた 16 進数として示したもの。
- len:
- その記号を表す符号のビット数。
例として、記号 47(ASCII 文字 "/" に対応)の符号は 6 ビットの "0", "1", "1", "0", "0", "0" から成ります。これは 6 ビットでエンコードされた 0x18(16 進)という値に対応します。
code
code as bits as hex len
sym aligned to MSB aligned in
to LSB bits
( 0) |11111111|11000 1ff8 [13]
( 1) |11111111|11111111|1011000 7fffd8 [23]
( 2) |11111111|11111111|11111110|0010 fffffe2 [28]
( 3) |11111111|11111111|11111110|0011 fffffe3 [28]
( 4) |11111111|11111111|11111110|0100 fffffe4 [28]
( 5) |11111111|11111111|11111110|0101 fffffe5 [28]
( 6) |11111111|11111111|11111110|0110 fffffe6 [28]
( 7) |11111111|11111111|11111110|0111 fffffe7 [28]
( 8) |11111111|11111111|11111110|1000 fffffe8 [28]
( 9) |11111111|11111111|11101010 ffffea [24]
( 10) |11111111|11111111|11111111|111100 3ffffffc [30]
( 11) |11111111|11111111|11111110|1001 fffffe9 [28]
( 12) |11111111|11111111|11111110|1010 fffffea [28]
( 13) |11111111|11111111|11111111|111101 3ffffffd [30]
( 14) |11111111|11111111|11111110|1011 fffffeb [28]
( 15) |11111111|11111111|11111110|1100 fffffec [28]
( 16) |11111111|11111111|11111110|1101 fffffed [28]
( 17) |11111111|11111111|11111110|1110 fffffee [28]
( 18) |11111111|11111111|11111110|1111 fffffef [28]
( 19) |11111111|11111111|11111111|0000 ffffff0 [28]
( 20) |11111111|11111111|11111111|0001 ffffff1 [28]
( 21) |11111111|11111111|11111111|0010 ffffff2 [28]
( 22) |11111111|11111111|11111111|111110 3ffffffe [30]
( 23) |11111111|11111111|11111111|0011 ffffff3 [28]
( 24) |11111111|11111111|11111111|0100 ffffff4 [28]
( 25) |11111111|11111111|11111111|0101 ffffff5 [28]
( 26) |11111111|11111111|11111111|0110 ffffff6 [28]
( 27) |11111111|11111111|11111111|0111 ffffff7 [28]
( 28) |11111111|11111111|11111111|1000 ffffff8 [28]
( 29) |11111111|11111111|11111111|1001 ffffff9 [28]
( 30) |11111111|11111111|11111111|1010 ffffffa [28]
( 31) |11111111|11111111|11111111|1011 ffffffb [28]
' ' ( 32) |010100 14 [ 6]
'!' ( 33) |11111110|00 3f8 [10]
'"' ( 34) |11111110|01 3f9 [10]
'#' ( 35) |11111111|1010 ffa [12]
'$' ( 36) |11111111|11001 1ff9 [13]
'%' ( 37) |010101 15 [ 6]
'&' ( 38) |11111000 f8 [ 8]
''' ( 39) |11111111|010 7fa [11]
'(' ( 40) |11111110|10 3fa [10]
')' ( 41) |11111110|11 3fb [10]
'*' ( 42) |11111001 f9 [ 8]
'+' ( 43) |11111111|011 7fb [11]
',' ( 44) |11111010 fa [ 8]
'-' ( 45) |010110 16 [ 6]
'.' ( 46) |010111 17 [ 6]
'/' ( 47) |011000 18 [ 6]
'0' ( 48) |00000 0 [ 5]
'1' ( 49) |00001 1 [ 5]
'2' ( 50) |00010 2 [ 5]
'3' ( 51) |011001 19 [ 6]
'4' ( 52) |011010 1a [ 6]
'5' ( 53) |011011 1b [ 6]
'6' ( 54) |011100 1c [ 6]
'7' ( 55) |011101 1d [ 6]
'8' ( 56) |011110 1e [ 6]
'9' ( 57) |011111 1f [ 6]
':' ( 58) |1011100 5c [ 7]
';' ( 59) |11111011 fb [ 8]
'<' ( 60) |11111111|1111100 7ffc [15]
'=' ( 61) |100000 20 [ 6]
'>' ( 62) |11111111|1011 ffb [12]
'?' ( 63) |11111111|00 3fc [10]
'@' ( 64) |11111111|11010 1ffa [13]
'A' ( 65) |100001 21 [ 6]
'B' ( 66) |1011101 5d [ 7]
'C' ( 67) |1011110 5e [ 7]
'D' ( 68) |1011111 5f [ 7]
'E' ( 69) |1100000 60 [ 7]
'F' ( 70) |1100001 61 [ 7]
'G' ( 71) |1100010 62 [ 7]
'H' ( 72) |1100011 63 [ 7]
'I' ( 73) |1100100 64 [ 7]
'J' ( 74) |1100101 65 [ 7]
'K' ( 75) |1100110 66 [ 7]
'L' ( 76) |1100111 67 [ 7]
'M' ( 77) |1101000 68 [ 7]
'N' ( 78) |1101001 69 [ 7]
'O' ( 79) |1101010 6a [ 7]
'P' ( 80) |1101011 6b [ 7]
'Q' ( 81) |1101100 6c [ 7]
'R' ( 82) |1101101 6d [ 7]
'S' ( 83) |1101110 6e [ 7]
'T' ( 84) |1101111 6f [ 7]
'U' ( 85) |1110000 70 [ 7]
'V' ( 86) |1110001 71 [ 7]
'W' ( 87) |1110010 72 [ 7]
'X' ( 88) |11111100 fc [ 8]
'Y' ( 89) |1110011 73 [ 7]
'Z' ( 90) |11111101 fd [ 8]
'[' ( 91) |11111111|11011 1ffb [13]
'\' ( 92) |11111111|11111110|000 7fff0 [19]
']' ( 93) |11111111|11100 1ffc [13]
'^' ( 94) |11111111|111100 3ffc [14]
'_' ( 95) |100010 22 [ 6]
'`' ( 96) |11111111|1111101 7ffd [15]
'a' ( 97) |00011 3 [ 5]
'b' ( 98) |100011 23 [ 6]
'c' ( 99) |00100 4 [ 5]
'd' (100) |100100 24 [ 6]
'e' (101) |00101 5 [ 5]
'f' (102) |100101 25 [ 6]
'g' (103) |100110 26 [ 6]
'h' (104) |100111 27 [ 6]
'i' (105) |00110 6 [ 5]
'j' (106) |1110100 74 [ 7]
'k' (107) |1110101 75 [ 7]
'l' (108) |101000 28 [ 6]
'm' (109) |101001 29 [ 6]
'n' (110) |101010 2a [ 6]
'o' (111) |00111 7 [ 5]
'p' (112) |101011 2b [ 6]
'q' (113) |1110110 76 [ 7]
'r' (114) |101100 2c [ 6]
's' (115) |01000 8 [ 5]
't' (116) |01001 9 [ 5]
'u' (117) |101101 2d [ 6]
'v' (118) |1110111 77 [ 7]
'w' (119) |1111000 78 [ 7]
'x' (120) |1111001 79 [ 7]
'y' (121) |1111010 7a [ 7]
'z' (122) |1111011 7b [ 7]
'{' (123) |11111111|1111110 7ffe [15]
'|' (124) |11111111|100 7fc [11]
'}' (125) |11111111|111101 3ffd [14]
'~' (126) |11111111|11101 1ffd [13]
(127) |11111111|11111111|11111111|1100 ffffffc [28]
(128) |11111111|11111110|0110 fffe6 [20]
(129) |11111111|11111111|010010 3fffd2 [22]
(130) |11111111|11111110|0111 fffe7 [20]
(131) |11111111|11111110|1000 fffe8 [20]
(132) |11111111|11111111|010011 3fffd3 [22]
(133) |11111111|11111111|010100 3fffd4 [22]
(134) |11111111|11111111|010101 3fffd5 [22]
(135) |11111111|11111111|1011001 7fffd9 [23]
(136) |11111111|11111111|010110 3fffd6 [22]
(137) |11111111|11111111|1011010 7fffda [23]
(138) |11111111|11111111|1011011 7fffdb [23]
(139) |11111111|11111111|1011100 7fffdc [23]
(140) |11111111|11111111|1011101 7fffdd [23]
(141) |11111111|11111111|1011110 7fffde [23]
(142) |11111111|11111111|11101011 ffffeb [24]
(143) |11111111|11111111|1011111 7fffdf [23]
(144) |11111111|11111111|11101100 ffffec [24]
(145) |11111111|11111111|11101101 ffffed [24]
(146) |11111111|11111111|010111 3fffd7 [22]
(147) |11111111|11111111|1100000 7fffe0 [23]
(148) |11111111|11111111|11101110 ffffee [24]
(149) |11111111|11111111|1100001 7fffe1 [23]
(150) |11111111|11111111|1100010 7fffe2 [23]
(151) |11111111|11111111|1100011 7fffe3 [23]
(152) |11111111|11111111|1100100 7fffe4 [23]
(153) |11111111|11111110|11100 1fffdc [21]
(154) |11111111|11111111|011000 3fffd8 [22]
(155) |11111111|11111111|1100101 7fffe5 [23]
(156) |11111111|11111111|011001 3fffd9 [22]
(157) |11111111|11111111|1100110 7fffe6 [23]
(158) |11111111|11111111|1100111 7fffe7 [23]
(159) |11111111|11111111|11101111 ffffef [24]
(160) |11111111|11111111|011010 3fffda [22]
(161) |11111111|11111110|11101 1fffdd [21]
(162) |11111111|11111110|1001 fffe9 [20]
(163) |11111111|11111111|011011 3fffdb [22]
(164) |11111111|11111111|011100 3fffdc [22]
(165) |11111111|11111111|1101000 7fffe8 [23]
(166) |11111111|11111111|1101001 7fffe9 [23]
(167) |11111111|11111110|11110 1fffde [21]
(168) |11111111|11111111|1101010 7fffea [23]
(169) |11111111|11111111|011101 3fffdd [22]
(170) |11111111|11111111|011110 3fffde [22]
(171) |11111111|11111111|11110000 fffff0 [24]
(172) |11111111|11111110|11111 1fffdf [21]
(173) |11111111|11111111|011111 3fffdf [22]
(174) |11111111|11111111|1101011 7fffeb [23]
(175) |11111111|11111111|1101100 7fffec [23]
(176) |11111111|11111111|00000 1fffe0 [21]
(177) |11111111|11111111|00001 1fffe1 [21]
(178) |11111111|11111111|100000 3fffe0 [22]
(179) |11111111|11111111|00010 1fffe2 [21]
(180) |11111111|11111111|1101101 7fffed [23]
(181) |11111111|11111111|100001 3fffe1 [22]
(182) |11111111|11111111|1101110 7fffee [23]
(183) |11111111|11111111|1101111 7fffef [23]
(184) |11111111|11111110|1010 fffea [20]
(185) |11111111|11111111|100010 3fffe2 [22]
(186) |11111111|11111111|100011 3fffe3 [22]
(187) |11111111|11111111|100100 3fffe4 [22]
(188) |11111111|11111111|1110000 7ffff0 [23]
(189) |11111111|11111111|100101 3fffe5 [22]
(190) |11111111|11111111|100110 3fffe6 [22]
(191) |11111111|11111111|1110001 7ffff1 [23]
(192) |11111111|11111111|11111000|00 3ffffe0 [26]
(193) |11111111|11111111|11111000|01 3ffffe1 [26]
(194) |11111111|11111110|1011 fffeb [20]
(195) |11111111|11111110|001 7fff1 [19]
(196) |11111111|11111111|100111 3fffe7 [22]
(197) |11111111|11111111|1110010 7ffff2 [23]
(198) |11111111|11111111|101000 3fffe8 [22]
(199) |11111111|11111111|11110110|0 1ffffec [25]
(200) |11111111|11111111|11111000|10 3ffffe2 [26]
(201) |11111111|11111111|11111000|11 3ffffe3 [26]
(202) |11111111|11111111|11111001|00 3ffffe4 [26]
(203) |11111111|11111111|11111011|110 7ffffde [27]
(204) |11111111|11111111|11111011|111 7ffffdf [27]
(205) |11111111|11111111|11111001|01 3ffffe5 [26]
(206) |11111111|11111111|11110001 fffff1 [24]
(207) |11111111|11111111|11110110|1 1ffffed [25]
(208) |11111111|11111110|010 7fff2 [19]
(209) |11111111|11111111|00011 1fffe3 [21]
(210) |11111111|11111111|11111001|10 3ffffe6 [26]
(211) |11111111|11111111|11111100|000 7ffffe0 [27]
(212) |11111111|11111111|11111100|001 7ffffe1 [27]
(213) |11111111|11111111|11111001|11 3ffffe7 [26]
(214) |11111111|11111111|11111100|010 7ffffe2 [27]
(215) |11111111|11111111|11110010 fffff2 [24]
(216) |11111111|11111111|00100 1fffe4 [21]
(217) |11111111|11111111|00101 1fffe5 [21]
(218) |11111111|11111111|11111010|00 3ffffe8 [26]
(219) |11111111|11111111|11111010|01 3ffffe9 [26]
(220) |11111111|11111111|11111111|1101 ffffffd [28]
(221) |11111111|11111111|11111100|011 7ffffe3 [27]
(222) |11111111|11111111|11111100|100 7ffffe4 [27]
(223) |11111111|11111111|11111100|101 7ffffe5 [27]
(224) |11111111|11111110|1100 fffec [20]
(225) |11111111|11111111|11110011 fffff3 [24]
(226) |11111111|11111110|1101 fffed [20]
(227) |11111111|11111111|00110 1fffe6 [21]
(228) |11111111|11111111|101001 3fffe9 [22]
(229) |11111111|11111111|00111 1fffe7 [21]
(230) |11111111|11111111|01000 1fffe8 [21]
(231) |11111111|11111111|1110011 7ffff3 [23]
(232) |11111111|11111111|101010 3fffea [22]
(233) |11111111|11111111|101011 3fffeb [22]
(234) |11111111|11111111|11110111|0 1ffffee [25]
(235) |11111111|11111111|11110111|1 1ffffef [25]
(236) |11111111|11111111|11110100 fffff4 [24]
(237) |11111111|11111111|11110101 fffff5 [24]
(238) |11111111|11111111|11111010|10 3ffffea [26]
(239) |11111111|11111111|1110100 7ffff4 [23]
(240) |11111111|11111111|11111010|11 3ffffeb [26]
(241) |11111111|11111111|11111100|110 7ffffe6 [27]
(242) |11111111|11111111|11111011|00 3ffffec [26]
(243) |11111111|11111111|11111011|01 3ffffed [26]
(244) |11111111|11111111|11111100|111 7ffffe7 [27]
(245) |11111111|11111111|11111101|000 7ffffe8 [27]
(246) |11111111|11111111|11111101|001 7ffffe9 [27]
(247) |11111111|11111111|11111101|010 7ffffea [27]
(248) |11111111|11111111|11111101|011 7ffffeb [27]
(249) |11111111|11111111|11111111|1110 ffffffe [28]
(250) |11111111|11111111|11111101|100 7ffffec [27]
(251) |11111111|11111111|11111101|101 7ffffed [27]
(252) |11111111|11111111|11111101|110 7ffffee [27]
(253) |11111111|11111111|11111101|111 7ffffef [27]
(254) |11111111|11111111|11111110|000 7fffff0 [27]
(255) |11111111|11111111|11111011|10 3ffffee [26]
EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]
付録 C. 例
この付録には、整数のエンコード、ヘッダフィールド表現、およびヘッダフィールドのリスト全体のエンコード(リクエストおよびレスポンス、ハフマン符号の有無を含む)に関する例が含まれています。
C.1. 整数表現の例
この節では整数値の表現を詳しく示します(セクション 5.1参照)。
C.1.1. 例 1: 5ビットプレフィックスを使った 10 のエンコード
値 10 を 5 ビットのプレフィックスでエンコードします。
- 10 は 31 (25 - 1) より小さいため、5 ビットのプレフィックスで表現されます。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | X | X | X | 0 | 1 | 0 | 1 | 0 | 10 stored on 5 bits +---+---+---+---+---+---+---+---+
C.1.2. 例 2: 5ビットプレフィックスを使った 1337 のエンコード
値 I = 1337 を 5 ビットのプレフィックスでエンコードします。
- 1337 は 31 (25 - 1) より大きい。
-
- 5 ビットのプレフィックスは最大値 (31) で埋められます。
- I = 1337 - (25 - 1) = 1306。
-
- I (1306) は 128 以上なので while ループ本体が実行されます:
-
- I % 128 == 26
- 26 + 128 == 154
- 154 は 8 ビットで 10011010 としてエンコードされる
- I は 10 に設定される (1306 / 128 == 10)
- I はもはや 128 以上ではないので while ループは終了する。
- I は現在 10 であり、8 ビットで 00001010 としてエンコードされる。
- 処理は終了する。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | X | X | X | 1 | 1 | 1 | 1 | 1 | Prefix = 31, I = 1306 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1306>=128, encode(154), I=1306/128 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 10<128, encode(10), done +---+---+---+---+---+---+---+---+
C.1.3. 例 3: オクテット境界から始める 42 のエンコード
値 42 をオクテット境界からエンコードします。これは 8 ビットのプレフィックスが使われることを意味します。
- 42 は 255 (28 - 1) より小さいため、8 ビットのプレフィックスで表現されます。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 42 stored on 8 bits +---+---+---+---+---+---+---+---+
C.2. ヘッダフィールド表現の例
この節ではいくつかの独立した表現の例を示します。
C.2.1. インデックス付きリテラルヘッダフィールド
ヘッダフィールド表現はリテラル名とリテラル値を使用します。ヘッダフィールドは動的テーブルに追加されます。
エンコードするヘッダリスト:
custom-key: custom-header
エンコードデータの 16 進ダンプ:
400a 6375 7374 6f6d 2d6b 6579 0d63 7573 | @.custom-key.cus 746f 6d2d 6865 6164 6572 | tom-header
デコード手順:
40 | == Literal indexed ==
0a | Literal name (len = 10)
6375 7374 6f6d 2d6b 6579 | custom-key
0d | Literal value (len = 13)
6375 7374 6f6d 2d68 6561 6465 72 | custom-header
| -> custom-key:
| custom-header
デコード後の動的テーブル:
[ 1] (s = 55) custom-key: custom-header
Table size: 55
デコードされたヘッダリスト:
custom-key: custom-header
C.2.2. インデックスなしリテラルヘッダフィールド
ヘッダフィールド表現はインデックスされた名前とリテラル値を使用します。ヘッダフィールドは動的テーブルに追加されません。
エンコードするヘッダリスト:
:path: /sample/path
エンコードデータの 16 進ダンプ:
040c 2f73 616d 706c 652f 7061 7468 | ../sample/path
デコード手順:
04 | == Literal not indexed ==
| Indexed name (idx = 4)
| :path
0c | Literal value (len = 12)
2f73 616d 706c 652f 7061 7468 | /sample/path
| -> :path: /sample/path
デコード後の動的テーブル:空。
デコードされたヘッダリスト:
:path: /sample/path
C.2.3. 決してインデックスされないリテラルヘッダフィールド
ヘッダフィールド表現はリテラル名とリテラル値を使用します。ヘッダフィールドは動的テーブルに追加されず、仲介者により再エンコードされる場合でも同じ表現を使用する必要があります。
エンコードするヘッダリスト:
password: secret
エンコードデータの 16 進ダンプ:
1008 7061 7373 776f 7264 0673 6563 7265 | ..password.secre 74 | t
デコード手順:
10 | == Literal never indexed ==
08 | Literal name (len = 8)
7061 7373 776f 7264 | password
06 | Literal value (len = 6)
7365 6372 6574 | secret
| -> password: secret
デコード後の動的テーブル:空。
デコードされたヘッダリスト:
password: secret
C.2.4. インデックス付きヘッダフィールド
ヘッダフィールド表現は静的テーブルからのインデックス付きヘッダフィールドを使用します。
エンコードするヘッダリスト:
:method: GET
エンコードデータの 16 進ダンプ:
82 | .
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
デコード後の動的テーブル:空。
デコードされたヘッダリスト:
:method: GET
C.3. ハフマン符号なしのリクエスト例
この節では、同一接続上での複数の連続したヘッダリスト(HTTP リクエストに対応する)を示します。
C.3.1. 最初のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com
エンコードデータの 16 進ダンプ:
8286 8441 0f77 7777 2e65 7861 6d70 6c65 | ...A.www.example 2e63 6f6d | .com
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
86 | == Indexed - Add ==
| idx = 6
| -> :scheme: http
84 | == Indexed - Add ==
| idx = 4
| -> :path: /
41 | == Literal indexed ==
| Indexed name (idx = 1)
| :authority
0f | Literal value (len = 15)
7777 772e 6578 616d 706c 652e 636f 6d | www.example.com
| -> :authority:
| www.example.com
デコード後の動的テーブル:
[ 1] (s = 57) :authority: www.example.com
Table size: 57
デコードされたヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com
C.3.2. 2つ目のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com cache-control: no-cache
エンコードデータの 16 進ダンプ:
8286 84be 5808 6e6f 2d63 6163 6865 | ....X.no-cache
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
86 | == Indexed - Add ==
| idx = 6
| -> :scheme: http
84 | == Indexed - Add ==
| idx = 4
| -> :path: /
be | == Indexed - Add ==
| idx = 62
| -> :authority:
| www.example.com
58 | == Literal indexed ==
| Indexed name (idx = 24)
| cache-control
08 | Literal value (len = 8)
6e6f 2d63 6163 6865 | no-cache
| -> cache-control: no-cache
デコード後の動的テーブル:
[ 1] (s = 53) cache-control: no-cache
[ 2] (s = 57) :authority: www.example.com
Table size: 110
デコードされたヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com cache-control: no-cache
C.3.3. 3つ目のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: https :path: /index.html :authority: www.example.com custom-key: custom-value
エンコードデータの 16 進ダンプ:
8287 85bf 400a 6375 7374 6f6d 2d6b 6579 | ....@.custom-key 0c63 7573 746f 6d2d 7661 6c75 65 | .custom-value
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
87 | == Indexed - Add ==
| idx = 7
| -> :scheme: https
85 | == Indexed - Add ==
| idx = 5
| -> :path: /index.html
bf | == Indexed - Add ==
| idx = 63
| -> :authority:
| www.example.com
40 | == Literal indexed ==
0a | Literal name (len = 10)
6375 7374 6f6d 2d6b 6579 | custom-key
0c | Literal value (len = 12)
6375 7374 6f6d 2d76 616c 7565 | custom-value
| -> custom-key:
| custom-value
デコード後の動的テーブル:
[ 1] (s = 54) custom-key: custom-value
[ 2] (s = 53) cache-control: no-cache
[ 3] (s = 57) :authority: www.example.com
Table size: 164
デコードされたヘッダリスト:
:method: GET :scheme: https :path: /index.html :authority: www.example.com custom-key: custom-value
C.4. ハフマン符号ありのリクエスト例
この節では、前節と同じ例を示しますが、リテラル値にハフマン符号を用いています。
C.4.1. 最初のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com
エンコードデータの 16 進ダンプ:
8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 | ...A......:k.... ff | .
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
86 | == Indexed - Add ==
| idx = 6
| -> :scheme: http
84 | == Indexed - Add ==
| idx = 4
| -> :path: /
41 | == Literal indexed ==
| Indexed name (idx = 1)
| :authority
8c | Literal value (len = 12)
| Huffman encoded:
f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
| Decoded:
| www.example.com
| -> :authority:
| www.example.com
デコード後の動的テーブル:
[ 1] (s = 57) :authority: www.example.com
Table size: 57
デコードされたヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com
C.4.2. 2つ目のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com cache-control: no-cache
エンコードデータの 16 進ダンプ:
8286 84be 5886 a8eb 1064 9cbf | ....X....d..
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
86 | == Indexed - Add ==
| idx = 6
| -> :scheme: http
84 | == Indexed - Add ==
| idx = 4
| -> :path: /
be | == Indexed - Add ==
| idx = 62
| -> :authority:
| www.example.com
58 | == Literal indexed ==
| Indexed name (idx = 24)
| cache-control
86 | Literal value (len = 6)
| Huffman encoded:
a8eb 1064 9cbf | ...d..
| Decoded:
| no-cache
| -> cache-control: no-cache
デコード後の動的テーブル:
[ 1] (s = 53) cache-control: no-cache
[ 2] (s = 57) :authority: www.example.com
Table size: 110
デコードされたヘッダリスト:
:method: GET :scheme: http :path: / :authority: www.example.com cache-control: no-cache
C.4.3. 3つ目のリクエスト
エンコードするヘッダリスト:
:method: GET :scheme: https :path: /index.html :authority: www.example.com custom-key: custom-value
エンコードデータの 16 進ダンプ:
8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 | ....@.%.I.[.}..% a849 e95b b8e8 b4bf | .I.[....
デコード手順:
82 | == Indexed - Add ==
| idx = 2
| -> :method: GET
87 | == Indexed - Add ==
| idx = 7
| -> :scheme: https
85 | == Indexed - Add ==
| idx = 5
| -> :path: /index.html
bf | == Indexed - Add ==
| idx = 63
| -> :authority:
| www.example.com
40 | == Literal indexed ==
88 | Literal name (len = 8)
| Huffman encoded:
25a8 49e9 5ba9 7d7f | %.I.[.}.
| Decoded:
| custom-key
89 | Literal value (len = 9)
| Huffman encoded:
25a8 49e9 5bb8 e8b4 bf | %.I.[....
| Decoded:
| custom-value
| -> custom-key:
| custom-value
デコード後の動的テーブル:
[ 1] (s = 54) custom-key: custom-value
[ 2] (s = 53) cache-control: no-cache
[ 3] (s = 57) :authority: www.example.com
Table size: 164
デコードされたヘッダリスト:
:method: GET :scheme: https :path: /index.html :authority: www.example.com custom-key: custom-value
C.5. ハフマン符号なしのレスポンス例
この節では、同一接続上での複数の連続したヘッダリスト(HTTP レスポンスに対応する)を示します。HTTP/2 の設定パラメータ SETTINGS_HEADER_TABLE_SIZE が 256 オクテットに設定されており、いくつかの追い出し(eviction)が発生します。
C.5.1. 最初のレスポンス
エンコードするヘッダリスト:
:status: 302 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
エンコードデータの 16 進ダンプ:
4803 3330 3258 0770 7269 7661 7465 611d | H.302X.privatea. 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 2032 303a 3133 3a32 3120 474d 546e 1768 | 20:13:21 GMTn.h 7474 7073 3a2f 2f77 7777 2e65 7861 6d70 | ttps://www.examp 6c65 2e63 6f6d | le.com
デコード手順:
48 | == Literal indexed ==
| Indexed name (idx = 8)
| :status
03 | Literal value (len = 3)
3330 32 | 302
| -> :status: 302
58 | == Literal indexed ==
| Indexed name (idx = 24)
| cache-control
07 | Literal value (len = 7)
7072 6976 6174 65 | private
| -> cache-control: private
61 | == Literal indexed ==
| Indexed name (idx = 33)
| date
1d | Literal value (len = 29)
4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT
| -> date: Mon, 21 Oct 2013
| 20:13:21 GMT
6e | == Literal indexed ==
| Indexed name (idx = 46)
| location
17 | Literal value (len = 23)
6874 7470 733a 2f2f 7777 2e65 7861 6d70 | https://www.exam
6c65 2e636f6d | ple.com
| -> location:
| https://www.example.com
デコード後の動的テーブル:
[ 1] (s = 63) location: https://www.example.com
[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
[ 3] (s = 52) cache-control: private
[ 4] (s = 42) :status: 302
Table size: 222
デコードされたヘッダリスト:
:status: 302 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
C.5.2. 2つ目のレスポンス
(":status", "302") ヘッダフィールドは、(":status", "307") ヘッダフィールドを追加するためのスペースを確保するために動的テーブルから追い出されます。
エンコードするヘッダリスト:
:status: 307 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
エンコードデータの 16 進ダンプ:
4803 3330 37c1 c0bf | H.307...
デコード手順:
48 | == Literal indexed ==
| Indexed name (idx = 8)
| :status
03 | Literal value (len = 3)
3330 37 | 307
| - evict: :status: 302
| -> :status: 307
c1 | == Indexed - Add ==
| idx = 65
| -> cache-control: private
c0 | == Indexed - Add ==
| idx = 64
| -> date: Mon, 21 Oct 2013
| 20:13:21 GMT
bf | == Indexed - Add ==
| idx = 63
| -> location:
| https://www.example.com
デコード後の動的テーブル:
[ 1] (s = 42) :status: 307
[ 2] (s = 63) location: https://www.example.com
[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
[ 4] (s = 52) cache-control: private
Table size: 222
デコードされたヘッダリスト:
:status: 307 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
C.5.3. 3つ目のレスポンス
このヘッダリストの処理中に、いくつかのヘッダフィールドが動的テーブルから追い出されます。
エンコードするヘッダリスト:
:status: 200 cache-control: private date: Mon, 21 Oct 2013 20:13:22 GMT location: https://www.example.com content-encoding: gzip set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
エンコードデータの 16 進ダンプ:
88c1 611d 4d6f 6e2c 2032 3120 4f63 7420 | ..a.Mon, 21 Oct 3230 3133 2032 303a 3133 3a32 3220 474d | 2013 20:13:22 GM 54c0 5a04 677a 6970 7738 666f 6f3d 4153 | T.Z.gzipw8foo=AS 444a 4b48 514b 425a 584f 5157 454f 5049 | DJKHQKBZXOQWEOPI 5541 5851 5745 4f49 553b 206d 6178 2d61 | UAXQWEOIU; max-a 6765 3d33 3630 303b 2076 6572 7369 6f6e | ge=3600; version 3d31 | =1
デコード手順:
88 | == Indexed - Add ==
| idx = 8
| -> :status: 200
c1 | == Indexed - Add ==
| idx = 65
| -> cache-control: private
61 | == Literal indexed ==
| Indexed name (idx = 33)
| date
1d | Literal value (len = 29)
4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT
| - evict: cache-control:
| private
| -> date: Mon, 21 Oct 2013
| 20:13:22 GMT
c0 | == Indexed - Add ==
| idx = 64
| -> location:
| https://www.example.com
5a | == Literal indexed ==
| Indexed name (idx = 26)
| content-encoding
04 | Literal value (len = 4)
677a 6970 | gzip
| - evict: date: Mon, 21 Oct
| 2013 20:13:21 GMT
| -> content-encoding: gzip
77 | == Literal indexed ==
| Indexed name (idx = 55)
| set-cookie
38 | Literal value (len = 56)
666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO
5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU;
206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v
6572 7369 6f6e 3d31 | ersion=1
| - evict: location:
| https://www.example.com
| - evict: :status: 307
| -> set-cookie: foo=ASDJKHQ
| KBZXOQWEOPIUAXQWEOIU; ma
| x-age=3600; version=1
デコード後の動的テーブル:
[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
max-age=3600; version=1
[ 2] (s = 52) content-encoding: gzip
[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
Table size: 215
デコードされたヘッダリスト:
:status: 200 cache-control: private date: Mon, 21 Oct 2013 20:13:22 GMT location: https://www.example.com content-encoding: gzip set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
C.6. ハフマン符号ありのレスポンス例
この節では前節と同じ例を示しますが、リテラル値にハフマン符号を用いています。HTTP/2 の設定パラメータ SETTINGS_HEADER_TABLE_SIZE は 256 オクテットに設定されており、いくつかの追い出しが発生します。追い出し機構はデコード後のリテラル値の長さを使用するため、前節と同じ追い出しが発生します。
C.6.1. 最初のレスポンス
エンコードするヘッダリスト:
:status: 302 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
エンコードデータの 16 進ダンプ:
4882 6402 5885 aec3 771a 4b61 96d0 7abe | H.d.X...w.Ka..z. 9410 54d4 44a8 2005 9504 0b81 66e0 82a6 | ..T.D. .....f... 2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8 | -..n..)...c..... e9ae 82ae 43d3 | ....C.
デコード手順:
48 | == Literal indexed ==
| Indexed name (idx = 8)
| :status
82 | Literal value (len = 2)
| Huffman encoded:
6402 | d.
| Decoded:
| 302
| -> :status: 302
58 | == Literal indexed ==
| Indexed name (idx = 24)
| cache-control
85 | Literal value (len = 5)
| Huffman encoded:
aec3 771a 4b | ..w.K
| Decoded:
| private
| -> cache-control: private
61 | == Literal indexed ==
| Indexed name (idx = 33)
| date
96 | Literal value (len = 22)
| Huffman encoded:
d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
e082 a62d 1bff | ...-..
| Decoded:
| Mon, 21 Oct 2013 20:13:21
| GMT
| -> date: Mon, 21 Oct 2013
| 20:13:21 GMT
6e | == Literal indexed ==
| Indexed name (idx = 46)
| location
91 | Literal value (len = 17)
| Huffman encoded:
9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
d3 | .
| Decoded:
| https://www.example.com
| -> location:
| https://www.example.com
デコード後の動的テーブル:
[ 1] (s = 63) location: https://www.example.com
[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
[ 3] (s = 52) cache-control: private
[ 4] (s = 42) :status: 302
Table size: 222
デコードされたヘッダリスト:
:status: 302 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
C.6.2. 2つ目のレスポンス
(":status", "302") ヘッダフィールドは、(":status", "307") ヘッダフィールドを追加するためのスペースを確保するために動的テーブルから追い出されます。
エンコードするヘッダリスト:
:status: 307 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
エンコードデータの 16 進ダンプ:
4883 640e ffc1 c0bf | H.d.....
デコード手順:
48 | == Literal indexed ==
| Indexed name (idx = 8)
| :status
83 | Literal value (len = 3)
| Huffman encoded:
640e ff | d..
| Decoded:
| 307
| - evict: :status: 302
| -> :status: 307
c1 | == Indexed - Add ==
| idx = 65
| -> cache-control: private
c0 | == Indexed - Add ==
| idx = 64
| -> date: Mon, 21 Oct 2013
| 20:13:21 GMT
bf | == Indexed - Add ==
| idx = 63
| -> location:
| https://www.example.com
デコード後の動的テーブル:
[ 1] (s = 42) :status: 307
[ 2] (s = 63) location: https://www.example.com
[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
[ 4] (s = 52) cache-control: private
Table size: 222
デコードされたヘッダリスト:
:status: 307 cache-control: private date: Mon, 21 Oct 2013 20:13:21 GMT location: https://www.example.com
C.6.3. 3つ目のレスポンス
このヘッダリストの処理中に、いくつかのヘッダフィールドが動的テーブルから追い出されます。
エンコードするヘッダリスト:
:status: 200 cache-control: private date: Mon, 21 Oct 2013 20:13:22 GMT location: https://www.example.com content-encoding: gzip set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
エンコードデータの 16 進ダンプ:
88c1 6196 d07a be94 1054 d444 a820 0595 | ..a..z...T.D. .. 040b 8166 e084 a62d 1bff c05a 839b d9ab | ...f...-...Z.... 77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b | w..........5...[ 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f | 9`..'..6r..'..). 9587 3160 65c0 03ed 4ee5 b106 3d50 07 | ..1`e...N...=P.
デコード手順:
88 | == Indexed - Add ==
| idx = 8
| -> :status: 200
c1 | == Indexed - Add ==
| idx = 65
| -> cache-control: private
61 | == Literal indexed ==
| Indexed name (idx = 33)
| date
96 | Literal value (len = 22)
| Huffman encoded:
d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
e084 a62d 1bff | ...-..
| Decoded:
| Mon, 21 Oct 2013 20:13:22
| GMT
| - evict: cache-control:
| private
| -> date: Mon, 21 Oct 2013
| 20:13:22 GMT
c0 | == Indexed - Add ==
| idx = 64
| -> location:
| https://www.example.com
5a | == Literal indexed ==
| Indexed name (idx = 26)
| content-encoding
83 | Literal value (len = 3)
| Huffman encoded:
9bd9 ab | ...
| Decoded:
| gzip
| - evict: date: Mon, 21 Oct
| 2013 20:13:21 GMT
77 | == Literal indexed ==
| Indexed name (idx = 55)
| set-cookie
ad | Literal value (len = 45)
| Huffman encoded:
94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
3160 65c0 03ed 4ee5 b106 3d50 07 | 1`e...N...=P.
| Decoded:
| foo=ASDJKHQKBZXOQWEOPIUAXQ
| WEOIU; max-age=3600; versi
| on=1
| - evict: location:
| https://www.example.com
| - evict: :status: 307
| -> set-cookie: foo=ASDJKHQ
| KBZXOQWEOPIUAXQWEOIU; ma
| x-age=3600; version=1
デコード後の動的テーブル:
[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
max-age=3600; version=1
[ 2] (s = 52) content-encoding: gzip
[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
Table size: 215
デコードされたヘッダリスト:
:status: 200 cache-control: private date: Mon, 21 Oct 2013 20:13:22 GMT location: https://www.example.com content-encoding: gzip set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
謝辞
本仕様には以下の個人からの重要な寄与が含まれています:
- Mike Bishop、Jeff Pinner、Julian Reschke、Martin Thomson(大幅な編集上の寄稿)。
- Johnny Graettinger(ハフマン符号の統計)。