インターネット技術タスクフォース (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 の実装は、整数の大きな値、整数の長いエンコード、または長い文字列リテラルがセキュリティ上の弱点を生まないようにする必要があります。

実装は、受け入れる整数の値およびエンコード長に対して上限を設定しなければなりません(セクション 5.1参照)。同様に、文字列リテラルの受け入れ長にも上限を設定する必要があります(セクション 5.2参照)。

8. 参考文献

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 は静的テーブルを構成する事前定義されたヘッダフィールドを一覧にし、各エントリのインデックスを示します。

表 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(ハフマン符号の統計)。

著者の連絡先

Roberto Peon
Google, Inc
Email: fenix@google.com
Hervé Ruellan
Canon CRF
Email: herve.ruellan@crf.canon.fr