インターネット・エンジニアリング・タスクフォース(IETF) M. Thomson(編集者)
Request for Comments: 9113 Mozilla
Obsoletes: 7540, 8740 C. Benfield(編集者)
Category: Standards Track Apple Inc.
ISSN: 2070-1721 2022年6月

HTTP/2


要約

この仕様は、ハイパーテキスト転送プロトコル(HTTP)のセマンティクスを最適化して表現したもの、HTTP バージョン 2(HTTP/2)について説明します。HTTP/2 はフィールド圧縮を導入し、同一接続上で複数の同時交換を可能にすることで、ネットワークリソースのより効率的な利用と遅延の低減を実現します。

この文書は RFC 7540 および 8740 を廃止します。

このメモのステータス

これはインターネット標準トラック文書です。

この文書はインターネット・エンジニアリング・タスクフォース(IETF)の成果物です。IETF コミュニティのコンセンサスを表しています。公開レビューを受け、インターネット・エンジニアリング・ステアリング・グループ(IESG)によって公開が承認されています。インターネット標準に関するさらなる情報は RFC 7841 のセクション 2 をご覧ください。

この文書の現在のステータス、訂正情報(errata)、およびフィードバックの送付方法に関する情報は https://www.rfc-editor.org/info/rfc9113 で入手できます。

Copyright Notice

Copyright (c) 2022 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 (https://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 Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.


1. はじめに

ハイパーテキスト転送プロトコル(HTTP、[HTTP])を使用するアプリケーションの性能は、各 HTTP バージョンが基盤となるトランスポートをどのように利用するか、およびトランスポートがどのような条件下で動作するかに依存します。

複数の同時リクエストを行うことで遅延を低減し、アプリケーションの性能を改善できます。HTTP/1.0 は特定の TCP [TCP] 接続に対して同時に処理できるリクエストを 1 件にしか許可していませんでした。HTTP/1.1 [HTTP/1.1] はリクエストのパイプライン化を追加しましたが、これはリクエストの並列性を部分的にしか解決せず、アプリケーション層のヘッド・オブ・ライン(head-of-line)ブロッキングの影響を受け続けます。そのため、HTTP/1.0 および HTTP/1.1 のクライアントは並列リクエストを行うためにサーバーへの複数の接続を使用します。

さらに、HTTP フィールドはしばしば冗長で冗長な記述が多く、不要なネットワークトラフィックを引き起こすとともに、初期の TCP 混雑ウィンドウを急速に満たしてしまいます。これにより、新しい TCP 接続で複数のリクエストが行われると過度の遅延が発生することがあります。

HTTP/2 は、HTTP のセマンティクスを基盤接続に最適にマッピングすることでこれらの問題に対処します。具体的には、同一接続上でメッセージのインターリービングを可能にし、HTTP フィールドに対して効率的なエンコーディングを使用します。またリクエストの優先付けを可能にし、重要度の高いリクエストをより早く完了させることで性能をさらに改善します。

結果として、このプロトコルは HTTP/1.x と比較して TCP 接続の数を減らすことができるため、ネットワークに優しくなります。これは他のフローとの競合が減り、接続の寿命が長くなることで利用可能なネットワーク容量のより良い活用につながります。ただし、このプロトコルは TCP のヘッド・オブ・ラインブロッキング自体を解決するものではない点に注意してください。

最後に、HTTP/2 はバイナリメッセージフレーミングを使用することでメッセージ処理の効率化も可能にします。

この文書は RFCs 7540 および 8740 を廃止します。付録 B には顕著な変更点が挙げられています。


2. HTTP/2 プロトコル概要

HTTP/2 は HTTP セマンティクスのための最適化されたトランスポートを提供します。HTTP/2 は HTTP の全てのコア機能をサポートしますが、HTTP/1.1 よりも効率的であることを目指しています。

HTTP/2 は TCP 接続([TCP])上で動作する接続指向のアプリケーション層プロトコルです。クライアントは TCP 接続の開始者です。

HTTP/2 における基本的なプロトコル単位はフレームです(セクション 4.1)。各フレームタイプは異なる目的を持ちます。例えば、HEADERS フレームと DATA フレームは HTTP リクエストおよびレスポンスの基礎を形成します(セクション 8.1)。その他のフレームタイプとしては、SETTINGSWINDOW_UPDATE、および PUSH_PROMISE などがあり、これらは他の HTTP/2 機能を支援するために使用されます。

リクエストの多重化は、各 HTTP リクエスト/レスポンス交換をそれぞれ固有のストリームに関連付けることで実現されます(セクション 5)。ストリームは互いに大部分で独立しているため、あるリクエストやレスポンスがブロックまたは停滞しても他のストリームの進行を妨げません。

多重化を効果的に利用するにはフロー制御と優先付けが重要です。フロー制御(セクション 5.2)は、受信側が処理可能な範囲に送信データを制限することで多重化されたストリームを効率的に利用可能にします。優先付け(セクション 5.3)は、限られた資源が最も効果的に使われるようにします。本改訂では、[RFC7540] の優先度シグナリング方式は非推奨となっています。

接続で使用される HTTP フィールドは冗長なデータを多く含むことがあるため、それらを含むフレームは圧縮されます(セクション 4.3)。これは共通ケースにおけるリクエストサイズに特に有利に働き、多くのリクエストを 1 パケットに圧縮できるようにします。

最後に、HTTP/2 はサーバーがクライアントへレスポンスをプッシュできる新しい(任意の)相互作用モードを追加します(セクション 8.4)。これはサーバーがクライアントが必要とするだろうと推測するデータを投機的に送信することで、ネットワーク使用量を多少増やす代わりに遅延を低減することを意図しています。サーバーは合成リクエストを生成し、それを PUSH_PROMISE フレームとして送信することでこれを行います。その後、サーバーは別のストリーム上で合成リクエストに対するレスポンスを送信できます。

2.1. 文書の構成

HTTP/2 仕様は 4 つの部分に分かれています:

  • Starting HTTP/2(セクション 3)は HTTP/2 接続の開始方法を扱います。
  • フレーム層(セクション 4)とストリーム層(セクション 5)は、HTTP/2 フレームがどのように構造化され、多重化されたストリームに形成されるかを記述します。
  • フレーム(セクション 6)およびエラー(セクション 7)の定義は、HTTP/2 で使用されるフレームとエラータイプの詳細を含みます。
  • HTTP マッピング(セクション 8)および追加要件(セクション 9)は、フレームとストリームを用いて HTTP セマンティクスがどのように表現されるかを説明します。

フレーム層およびストリーム層の概念の一部は HTTP から独立しているものの、本仕様は完全に一般的なフレーム層を定義するものではありません。フレーム層とストリーム層は HTTP のニーズに合わせて調整されています。

2.2. 慣例と用語

本書中のキーワード "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", および "OPTIONAL" は、すべて大文字で表示されている場合に限り、BCP 14[RFC2119])および [RFC8174] に記載されているとおりに解釈されます。

すべての数値はネットワークバイトオーダーです。値は特に示されない限り符号なしです。リテラル値は適切に 10 進または 16 進で示されます。16 進リテラルは 10 進リテラルと区別するために "0x" プレフィックスが付されます。

本仕様はバイナリ形式を RFC 9000 の セクション 1.3 に記載された慣例で記述します。RFC 9000[QUIC])を参照してください。この形式はネットワークバイトオーダーを使用し、高位ビットが低位ビットより前に列挙されることに注意してください。

以下の用語が使用されます:

client:
HTTP/2 接続を開始するエンドポイント。クライアントは HTTP リクエストを送信し、HTTP レスポンスを受信します。
connection:
二つのエンドポイント間のトランスポート層の接続。
connection error:
HTTP/2 接続全体に影響するエラー。
endpoint:
接続のクライアントまたはサーバーのいずれか。
frame:
ヘッダとフレームタイプに従って構造化された可変長のオクテット列から成る、HTTP/2 接続内の最小の通信単位。
peer:
エンドポイント。特定のエンドポイントについて議論する際、「peer」は主要な議論対象から見てリモートなエンドポイントを指します。
receiver:
フレームを受信しているエンドポイント。
sender:
フレームを送信しているエンドポイント。
server:
HTTP/2 接続を受け入れるエンドポイント。サーバーは HTTP リクエストを受信し、HTTP レスポンスを送信します。
stream:
HTTP/2 接続内の双方向のフレームの流れ。
stream error:
個々の HTTP/2 ストリーム上のエラー。

最後に、「gateway」、「intermediary」、「proxy」、および「tunnel」という用語は RFC 9110 のセクション 3.7 に定義されています。インターミディアリは異なる時点でクライアントおよびサーバーとして振る舞います。

メッセージ本文に適用される「content」という用語は RFC 9110 のセクション 6.4 に定義されています。


3. HTTP/2 の開始

HTTP リクエストを生成する実装は、サーバーが HTTP/2 をサポートしているかどうかを検出する必要があります。

HTTP/2 は http および https URI スキーム(RFC 9110 の セクション 4.2 で定義)を使用し、デフォルトのポート番号は HTTP/1.1 と同じです([HTTP/1.1])。これらの URI は、上流のサーバー(クライアントが接続を確立しようとする直近のピア)がサポートする HTTP バージョンについての情報を含みません。

HTTP/2 のサポートを判定する手段は httphttps の URI ごとに異なります。https URI の検出は セクション 3.2 に記述されています。http URI に対する HTTP/2 のサポートはアウトオブバンドな手段でのみ発見可能であり、事前知識に基づくサポートが必要です(セクション 3.3 を参照)。

3.1. HTTP/2 バージョン識別

本書で定義されたプロトコルには二つの識別子があります。いずれかに基づいて接続を作成することは、本書で記述されたトランスポート、フレーミング、およびメッセージのセマンティクスの使用を意味します。

  • 文字列 "h2" は HTTP/2 がトランスポート層セキュリティ(TLS)を使用するプロトコルを識別します(セクション 9.2 を参照)。この識別子は TLS の ALPN フィールドや、HTTP/2 over TLS が識別されるあらゆる場所で使用されます(TLS-ALPN)。

    "h2" 文字列は ALPN プロトコル識別子として 2 バイト列 0x68, 0x32 としてシリアライズされます。

  • 文字列 "h2c" は以前 HTTP Upgrade メカニズムの Upgrade ヘッダーフィールドで使用されていました(RFC 9110 の セクション 7.8)。この使用法は広く展開されることはなく、本書で非推奨とされています。HTTP2-Settings ヘッダーフィールドも "h2c" へのアップグレードで使用されましたが、同様に非推奨です。

3.2. "https" URI のための HTTP/2 の開始

https URI へのリクエストを行うクライアントは、TLS[TLS13])を ALPN 拡張([TLS-ALPN])と共に使用します。

TLS 上の HTTP/2 は "h2" プロトコル識別子を使用します。クライアントが "h2c" を送信したりサーバーがそれを選択したりしてはならず(MUST NOT)、"h2c" は TLS を使用しないプロトコルを記述する識別子です。

TLS ネゴシエーションが完了したら、クライアントとサーバーの両方が接続序文(セクション 3.4)を送信する必要があります(MUST)。

3.3. 事前知識による HTTP/2 の開始

クライアントは他の手段で特定のサーバーが HTTP/2 をサポートしていることを知ることができます。例えば、クライアントがサーバーが HTTP/2 をサポートすると設定されている場合があります。

サーバーが HTTP/2 をサポートするとクライアントが知っている場合、クライアントは TCP 接続を確立して接続序文(セクション 3.4)を送信し、その後に HTTP/2 フレームを送信できます。サーバーは接続序文の存在によってこれらの接続を識別できます。これは平文 TCP 上での HTTP/2 接続の確立にのみ影響し、TLS 上の HTTP/2 接続は TLS におけるプロトコルネゴシエーション([TLS-ALPN])を使用しなければなりません(MUST)。

同様に、サーバーは接続序文(セクション 3.4)を送信しなければなりません(MUST)。

追加情報がない限り、過去に HTTP/2 をサポートしていたという事実は将来の接続で必ずしも同じサーバーが HTTP/2 をサポートする強いシグナルとはなりません。例えば、サーバー構成が変更される可能性や、クラスタ化されたサーバー間で構成が異なる可能性、ネットワーク条件が変化する可能性があります。

3.4. HTTP/2 接続序文

HTTP/2 では、各エンドポイントは使用プロトコルの最終確認としておよび HTTP/2 接続の初期設定を確立するために接続序文を送信することが要求されます。クライアントとサーバーはそれぞれ異なる接続序文を送信します。

クライアント接続序文は 24 オクテットのシーケンスで始まり、16 進表記では次のとおりです:

  0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

すなわち接続序文は文字列 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" で始まります。このシーケンスは SETTINGS フレーム(セクション 6.5)に続かなければならず(MUST)、その SETTINGS フレームは空であっても構いません(MAY)。クライアントはクライアント接続序文を接続の最初のアプリケーションデータオクテットとして送信します。

サーバー接続序文は、最初にサーバーが送信するフレームでなければならない可能性のある空であり得る SETTINGS フレーム(セクション 6.5)で構成されます(MUST)。

接続序文の一部としてピアから受信した SETTINGS フレームは、接続序文を送信した後に確認(acknowledge)されなければなりません(セクション 6.5.3 を参照)(MUST)。

不必要な遅延を避けるため、クライアントはサーバー接続序文を受信するのを待たずにクライアント接続序文送信直後に追加のフレームをサーバーへ送信することが許可されています。ただし、サーバー接続序文の SETTINGS フレームにはクライアントがサーバーと通信する方法を変更する設定が含まれる可能性があることに注意することが重要です。クライアントは SETTINGS フレームを受信したら、確立された設定を尊重することが期待されます。いくつかの構成では、サーバーがクライアントが追加フレームを送信する前に SETTINGS を送信することでこの問題を避けられることがあります。

クライアントとサーバーは、不正な接続序文を接続エラー(セクション 5.4.1)として扱わなければなりません(MUST)。この場合、接続序文が無効であることはピアが HTTP/2 を使用していないことを示すため、GOAWAY フレーム(セクション 6.8)は省略されることがあります(MAY)。


4. HTTP フレーム

HTTP/2 接続が確立されると、エンドポイントはフレームの交換を開始できます。

4.1. フレーム形式

すべてのフレームは固定長の 9 オクテットヘッダで始まり、その後に可変長のフレームペイロードが続きます。

HTTP Frame {
  Length (24),
  Type (8),

  Flags (8),

  Reserved (1),
  Stream Identifier (31),

  Frame Payload (..),
}

図 1: フレームレイアウト

フレームヘッダのフィールドは次のように定義されます:

Length:
フレームペイロードの長さをオクテット単位で表した符号なし 24 ビット整数。受信者が SETTINGS_MAX_FRAME_SIZE に対してより大きな値を設定していない限り、214(16,384)を超える値は送信してはなりません(MUST NOT)。
フレームヘッダの 9 オクテットはこの値に含まれません。
Type:
フレームの 8 ビットの型。フレームタイプはフレームの形式とセマンティクスを決定します。本書で定義されたフレームは セクション 6 に列挙されています。実装は不明な型のフレームを無視して破棄しなければなりません(MUST)。
Flags:
フレームタイプ固有のブールフラグのために予約された 8 ビットフィールド。
フラグには示されたフレームタイプに固有の意味が割り当てられます。未使用のフラグとは、特定のフレームタイプに対して定義された意味を持たないものです。未使用のフラグは受信時に無視され、送信時には未設定(0x00)にしておかなければなりません(MUST)。
Reserved:
予約された 1 ビットフィールド。このビットのセマンティクスは未定義であり、送信時は未設定(0x00)にしておかなければならず、受信時は無視されなければなりません(MUST)。
Stream Identifier:
ストリーム識別子(セクション 5.1.1 を参照)を符号なし 31 ビット整数で表したもの。値 0x00 は個々のストリームではなく接続全体に関連付けられるフレームのために予約されています。

フレームペイロードの構造と内容はフレームタイプに完全に依存します。

4.2. フレームサイズ

フレームペイロードのサイズは、受信者が SETTINGS_MAX_FRAME_SIZE 設定で広告する最大サイズによって制限されます。この設定は 214(16,384)から 224-1(16,777,215)オクテットまでの任意の値を取り得ます。

すべての実装は、9 オクテットのフレームヘッダを除く最大 214 オクテットまでのフレームを受信して最小限に処理できる能力を持たなければなりません(セクション 4.1)。フレームサイズを記述する際にはフレームヘッダのサイズは含まれません。

エンドポイントは、フレームが SETTINGS_MAX_FRAME_SIZE で定義されたサイズを超える場合、フレームタイプに定義されたいかなる制限を超える場合、または必須のフレームデータを含むには小さすぎる場合、FRAME_SIZE_ERROR のエラーコードを送信しなければなりません(MUST)。接続全体の状態を変更し得るフレーム内のフレームサイズエラーは接続エラー(セクション 5.4.1)として扱われなければなりません(MUST)。これにはフィールドブロックを運ぶ任意のフレーム(セクション 4.3、すなわち HEADERS, PUSH_PROMISE, および CONTINUATION)、SETTINGS フレーム、およびストリーム識別子が 0 の任意のフレームが含まれます。

エンドポイントはフレーム内の利用可能なすべての空間を使い切る義務はありません。許容最大サイズより小さいフレームを使用することで応答性が向上することがあります。大きなフレームを送信すると、RST_STREAMWINDOW_UPDATE、または PRIORITY のような時間センシティブなフレームの送信が遅延される可能性があり、大きなフレームの送信によりこれらがブロックされると性能に影響を与える場合があります。

4.3. フィールドセクションの圧縮と解凍

フィールドセクションの圧縮とは、フィールドラインの集合(RFC 9110 の セクション 5.2 を参照)を圧縮してフィールドブロックを形成するプロセスです。フィールドセクションの解凍とは、フィールドブロックをデコードしてフィールドラインの集合に戻すプロセスです。HTTP/2 のフィールドセクション圧縮と解凍の詳細は [COMPRESSION] に定義されており、歴史的理由からこれらのプロセスをヘッダ圧縮およびヘッダ解凍と呼んでいます。

各フィールドブロックは単一のフィールドセクションの圧縮されたフィールドラインをすべて運びます。ヘッダセクションは擬似ヘッダーフィールド(セクション 8.3)というメッセージに関連する制御データも含み、これらはフィールドラインと同じ形式を使用します。

フィールドブロックはリクエスト、レスポンス、約束されたリクエスト、およびプッシュされたレスポンスの制御データとヘッダセクションを運びます(セクション 8.4 を参照)。これらのメッセージはすべて、途中応答および PUSH_PROMISE (セクション 6.6) に含まれるリクエストを除き、トレーラセクションを運ぶフィールドブロックをオプションで含めることができます。

フィールドセクションはフィールドラインの集合です。フィールドブロック内の各フィールドラインは単一の値を運びます。直列化されたフィールドブロックはその後、フィールドブロックフラグメントと呼ばれる 1 つ以上のオクテット列に分割されます。最初のフィールドブロックフラグメントは HEADERS(セクション 6.2)または PUSH_PROMISE(セクション 6.6)のフレームのフレームペイロード内で送信され、その後に続くフィールドブロックフラグメントを運ぶために CONTINUATION(セクション 6.10)フレームが続くことがあります。

Cookie header field([COOKIE])は HTTP マッピングで特別に扱われます(セクション 8.2.3 を参照)。

受信エンドポイントはフィールドブロックをフラグメントを連結して再構成し、その後ブロックを解凍してフィールドセクションを復元します。

完全なフィールドセクションは次のいずれかで構成されます:

  • END_HEADERS フラグが設定された単一の HEADERS または PUSH_PROMISE フレーム、または
  • END_HEADERS フラグが未設定の HEADERS または PUSH_PROMISE フレームと、続く 1 個以上の CONTINUATION フレームで、最後の CONTINUATION フレームに END_HEADERS フラグが設定されている場合。

各フィールドブロックは離散的な単位として処理されます。フィールドブロックは連続したフレーム列として送信されなければならず(MUST)、他の型のフレームや他のストリームからのフレームが途中に挟まってはなりません。HEADERS または CONTINUATION の列の最後のフレームには END_HEADERS フラグが設定されます。PUSH_PROMISE または CONTINUATION の列の最後のフレームにも END_HEADERS フラグが設定されます。これによりフィールドブロックは論理的に単一フレームと同等になります。

フィールドブロックフラグメントは HEADERSPUSH_PROMISE、または CONTINUATION フレームのフレームペイロードとしてのみ送信できます。これらのフレームは受信者が保持する圧縮コンテキストを変更し得るデータを運ぶためです。HEADERSPUSH_PROMISE、または CONTINUATION フレームを受信するエンドポイントは、たとえそれらのフレームが破棄される場合でもフィールドブロックを再構成して解凍を行う必要があります。もし受信者がフィールドブロックを解凍しない場合、受信者は接続エラー(セクション 5.4.1)を COMPRESSION_ERROR の種類で終了しなければなりません(MUST)。

フィールドブロックのデコードエラーは接続エラー(セクション 5.4.1)として扱われ、COMPRESSION_ERROR の種類に該当します(MUST)。

4.3.1. 圧縮状態

フィールド圧縮は状態を持ちます。各エンドポイントは、接続上のすべてのフィールドブロックのエンコードとデコードに使用される HPACK エンコーダコンテキストと HPACK デコーダコンテキストを持ちます。HPACK の セクション 4 は、各コンテキストの主要な状態である動的テーブルを定義します([COMPRESSION])。

動的テーブルにはデコーダが設定する最大サイズがあります。エンドポイントはその HPACK デコーダコンテキストが選択したサイズを SETTINGS_HEADER_TABLE_SIZE 設定を使って伝達します(セクション 6.5.2 を参照)。接続が確立されると、両端の HPACK デコーダおよびエンコーダの動的テーブルサイズは SETTINGS_HEADER_TABLE_SIZE 設定の初期値である 4,096 バイトで開始します。

SETTINGS_HEADER_TABLE_SIZE を使って設定された最大値への任意の変更は、エンドポイントが設定を確認(acknowledge)したときに有効になります(セクション 6.5.3)。そのエンドポイントの HPACK エンコーダはデコーダが設定した最大値までの任意のサイズに動的テーブルを設定できます。HPACK エンコーダは Dynamic Table Size Update 命令で動的テーブルのサイズを宣言します(RFC 7541 セクション 6.3 を参照)。

エンドポイントが SETTINGS_HEADER_TABLE_SIZE の変更を確認し、それによって現在の動的テーブルサイズよりも小さく最大値が低下した場合、そのエンドポイントの HPACK エンコーダは次のフィールドブロックの開始時に動的テーブルを低下後の最大値以下に設定する Dynamic Table Size Update 命令で開始しなければなりません(RFC 7541 セクション 4.2 を参照)。エンドポイントは、最大動的テーブルサイズの縮小を確認した後に続くフィールドブロックが適合する Dynamic Table Size Update 命令で始まらない場合、そのフィールドブロックを接続エラー(セクション 5.4.1)として COMPRESSION_ERROR の種類で扱わなければなりません(MUST)。


5. ストリームと多重化

"stream"(ストリーム)とは、HTTP/2 接続内でクライアントとサーバーの間で交換される独立した双方向のフレーム列を指します。ストリームにはいくつかの重要な特徴があります:

  • 単一の HTTP/2 接続は複数の同時に開かれたストリームを含むことができ、いずれのエンドポイントも複数のストリームからフレームをインターリーブして送信できます。
  • ストリームは一方的に確立して使用することも、いずれのエンドポイントも共有して使用することもできます。
  • ストリームはどちらのエンドポイントによってもクローズできます。
  • フレームが送信される順序は重要です。受信者は受信した順にフレームを処理します。特に、HEADERS および DATA フレームの順序は意味論的に重要です。
  • ストリームは整数で識別されます。ストリーム識別子はストリームを開始するエンドポイントによって割り当てられます。

5.1. ストリームの状態

ストリームのライフサイクルは Figure 2 に示されています。

send PP recv PP idle send H / reserved recv H reserved (local) (remote) recv ES send ES send H open recv H half- half- closed send R / closed (remote) recv R (local) send ES / recv ES / send R / send R / recv R recv R send R / send R / recv R closed recv R

Figure 2: Stream States

send:
endpoint がこのフレームを送信する
recv:
endpoint がこのフレームを受信する
H:
HEADERS フレーム(暗黙の CONTINUATION フレームを含む)
ES:
END_STREAM フラグ
R:
RST_STREAM フレーム
PP:
PUSH_PROMISE フレーム(暗黙の CONTINUATION フレームを含む);状態遷移は約束されたストリームに対するもの

この図はストリーム状態の遷移およびそれらの遷移に影響するフレームとフラグのみを示しています。この点で、CONTINUATION フレームは状態遷移を引き起こさず、実質的にそれに続く HEADERS または PUSH_PROMISE の一部です。状態遷移の目的では、END_STREAM フラグはそれを持つフレームとは別個のイベントとして処理されます。END_STREAM フラグが設定された HEADERS フレームは 2 つの状態遷移を引き起こす可能性があります。

両端点はストリーム状態について主観的な見解を持ち、フレームが転送中の場合にはその見解が異なることがあります。エンドポイントはストリームの作成を協調しません;ストリームはどちらのエンドポイントからも一方的に作成されます。状態の不一致による負の影響は、RST_STREAM を送信した後の "closed" 状態に限定され、クローズ後もしばらくの間フレームが受信される可能性があります。

ストリームは以下の状態を持ちます:

idle:
すべてのストリームは "idle" 状態で開始します。
この状態から有効な遷移は次のとおりです:
  • クライアントとして HEADERS フレームを送信する、またはサーバーとして HEADERS フレームを受信することでストリームは "open" になります。ストリーム識別子は Section 5.1.1 に記載の通り選択されます。同じ HEADERS フレームは直ちにストリームを "half-closed" にすることもできます。
  • 別のストリーム上で PUSH_PROMISE フレームを送信すると、後で使用するためにアイドルストリームが予約されます。予約されたストリームの状態は "reserved (local)" に遷移します。PUSH_PROMISE フレームを送信できるのはサーバーのみです。
  • 別のストリーム上で PUSH_PROMISE フレームを受信すると、後で使用するためにアイドルストリームが予約されます。予約されたストリームの状態は "reserved (remote)" に遷移します。PUSH_PROMISE フレームを受信するのはクライアントのみです。
  • PUSH_PROMISE フレームはアイドルストリーム上で送信されるのではなく、Promised Stream ID フィールドで新しく予約されたストリームを参照する点に注意してください。
  • より大きな値のストリーム識別子でストリームが開かれると、そのストリームは直ちに "closed" 状態に遷移します;この遷移は図には示されていません。
この状態のストリームで HEADERS または PRIORITY 以外の任意のフレームを受信した場合、これは接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱われなければなりません(MUST)。このストリームがサーバーによって開始されたものである場合(Section 5.1.1 を参照)、HEADERS フレームを受信することも接続エラー(PROTOCOL_ERROR)として扱われなければなりません。
reserved (local):
"reserved (local)" 状態のストリームは、PUSH_PROMISE フレームを送信することで約束されたストリームです。PUSH_PROMISE フレームはリモートピアによって開始されたオープンストリームと関連付けることでアイドルストリームを予約します(Section 8.4 を参照)。
この状態では次の遷移のみ可能です:
  • エンドポイントは HEADERS フレームを送信できます。これによりストリームは "half-closed (remote)" でオープンします。
  • いずれのエンドポイントも RST_STREAM フレームを送信してストリームを "closed" にすることができます。これによりストリームの予約は解放されます。
この状態でエンドポイントは HEADERSRST_STREAM、または PRIORITY 以外のフレームを送信してはなりません(MUST NOT)。
PRIORITY または WINDOW_UPDATE フレームはこの状態で受信されてもよい(MAY)。この状態で RST_STREAM、PRIORITY、または WINDOW_UPDATE 以外のフレームを受信した場合は接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません(MUST)。
reserved (remote):
"reserved (remote)" 状態のストリームはリモートピアによって予約されたストリームです。
この状態では次の遷移のみ可能です:
  • HEADERS フレームを受信するとストリームは "half-closed (local)" に遷移します。
  • いずれのエンドポイントも RST_STREAM フレームを送信してストリームを "closed" にし、予約を解除できます。
この状態でエンドポイントは RST_STREAM、WINDOW_UPDATE、または PRIORITY 以外のフレームを送信してはなりません(MUST NOT)。
この状態で HEADERS、RST_STREAM、または PRIORITY 以外のフレームを受信した場合は接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません(MUST)。
open:
"open" 状態のストリームは、両方のピアが任意の型のフレームを送信して使用できます。この状態では送信者は広告されたストリームレベルのフロー制御制限(Section 5.2)を遵守します。
この状態からいずれのエンドポイントも END_STREAM フラグを持つフレームを送信でき、これによりストリームは "half-closed" 状態のいずれかに遷移します。END_STREAM フラグを送信したエンドポイントは "half-closed (local)" となり、END_STREAM フラグを受信したエンドポイントは "half-closed (remote)" となります。
いずれのエンドポイントもこの状態から RST_STREAM フレームを送信でき、これにより直ちに "closed" に遷移します。
half-closed (local):
"half-closed (local)" 状態のストリームは、WINDOW_UPDATE、PRIORITY、および RST_STREAM 以外のフレームを送信することはできません。
この状態からは、END_STREAM フラグを持つフレームを受信するか、いずれのピアが RST_STREAM を送信すると "closed" に遷移します。
この状態では任意の型のフレームを受信できます。フロー制御されたフレームの受信を継続するためには WINDOW_UPDATE フレームでフロー制御クレジットを提供する必要があります。この状態では、END_STREAM フラグが設定されたフレームを送信した後もしばらくの間 WINDOW_UPDATE フレームを無視できる場合があります。
この状態で PRIORITY フレームは受信可能です。
half-closed (remote):
"half-closed (remote)" 状態のストリームは、もはや相手ピアがフレームを送信するために使用していません。この状態では、エンドポイントはもはや受信者フロー制御ウィンドウを維持する義務を負いません。
この状態のストリームに対して WINDOW_UPDATE、PRIORITY、または RST_STREAM 以外の追加フレームを受信した場合、ストリームエラー(Section 5.4.2)の STREAM_CLOSED を送る必要があります(MUST)。
"half-closed (remote)" のストリームは、エンドポイントが任意の型のフレームを送信するために使用できます。この状態ではエンドポイントは引き続き広告されたストリームレベルのフロー制御制限を遵守します(Section 5.2)。
この状態からは、END_STREAM フラグを持つフレームを送信するか、いずれのピアが RST_STREAM フレームを送信すると "closed" に遷移できます。
closed:
"closed" 状態は終端状態です。
ストリームは、両端点が END_STREAM フラグを持つフレームを送受信した後に "closed" になります。また、いずれかのエンドポイントが RST_STREAM を送信または受信した場合も "closed" になります。
閉じられたストリーム上で PRIORITY 以外のフレームを送信してはなりません(MUST NOT)。閉じたストリームで他の型のフレームを受信した場合、エンドポイントはそれを接続エラー(Section 5.4.1)の STREAM_CLOSED として扱ってもよい(MAY)、ただし以下の注意があります。
エンドポイントが END_STREAM フラグ付きフレームまたは RST_STREAM を送信した場合、ピアがそのストリームをクローズするフレームを受信して処理するまでの間に WINDOW_UPDATE や RST_STREAM を受信することがあります。
open または half-closed (local) 状態にあるストリームに対して RST_STREAM を送信したエンドポイントは任意の型のフレームを受信する可能性があります。ピアはこれらのフレームを RST_STREAM を処理する前に送信または送信キューに入れている可能性があるためです。エンドポイントはこの状態で受信したフレームを最小限に処理して破棄しなければなりません。これには HEADERSPUSH_PROMISE フレームのヘッダ圧縮状態の更新が含まれます。閉じられたストリーム上で PUSH_PROMISE を受信すると、約束されたストリームは "reserved (remote)" になります。さらに、DATA フレームの内容は接続フロー制御ウィンドウに対してカウントされます。
エンドポイントは "closed" 状態のすべてのストリームに対してこの最小限の処理を行うことができます。エンドポイントはピアがストリームを閉じるために送ったフレームを受信したことを検出する他の信号を使用して、PRIORITY 以外のフレームを接続エラー(PROTOCOL_ERROR)として扱うことができます。エンドポイントはこの目的のためにタイマを使用すべきではありません。例えば、ストリームを閉じた後に SETTINGS フレームを送信したエンドポイントは、設定の確認を受け取った後にそのストリーム上で DATA フレームを受信した場合にエラーと見なすことができます。その他に使用され得るものとしては PING フレーム、閉じたストリームの後に作成されたストリームでのデータ受信、あるいは閉じた後に作成されたリクエストへのレスポンスなどがあります。

より具体的な規則がない場合、実装は状態の記述で明示的に許可されていないフレームの受信を接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱うべきです(SHOULD)。なお、PRIORITY は任意のストリーム状態で送受信可能です。

この節のルールは本書で定義されたフレームにのみ適用されます。セマンティクスが不明なフレームを受信した場合、それらを送受信する条件も不明なためエラーとして扱うことはできません;詳細は Section 5.5 を参照してください。

HTTP リクエスト/レスポンス交換の状態遷移の例は Section 8.8 にあります。サーバープッシュの状態遷移の例は 8.4.1 および 8.4.2 にあります。

5.1.1. Stream Identifiers

ストリームは符号なし 31 ビット整数で識別されます。クライアントが開始するストリームは奇数の識別子を使用しなければなりません(MUST);サーバーが開始するストリームは偶数の識別子を使用しなければなりません(MUST)。ストリーム識別子ゼロ(0x00)は接続制御メッセージに使用され、新しいストリームを確立するために使用できません。

新しく確立されたストリームの識別子は、そのストリームを開始したエンドポイントが既に開いたまたは予約したすべてのストリームよりも数値的に大きくなければなりません(MUST)。これは HEADERS フレームを用いて開かれるストリームと、PUSH_PROMISE を用いて予約されるストリームの両方に適用されます。予期しないストリーム識別子を受け取ったエンドポイントは接続エラー(Section 5.4.1)の PROTOCOL_ERROR として応答しなければなりません。

HEADERS フレームはフレームヘッダに示されたストリーム識別子を持つクライアント開始ストリームを "idle" から "open" に遷移させます。PUSH_PROMISE フレームはフレームペイロードの Promised Stream ID フィールドに示されたサーバー開始ストリームを "idle" から "reserved (local)" または "reserved (remote)" に遷移させます。ストリームが "idle" 状態を抜けるとき、ピアがより小さな値のストリーム識別子で開く可能性があったすべての "idle" ストリームは直ちに "closed" に遷移します。つまり、エンドポイントはストリーム識別子をスキップでき、その結果スキップされたストリームは即座に閉じられます。

ストリーム識別子は再利用できません。長時間接続によりエンドポイントが利用可能なストリーム識別子の範囲を使い果たすことがあります。新しいストリーム識別子を確立できないクライアントは新しいストリームのために新しい接続を確立できます。新しい識別子を確立できないサーバーは、クライアントが新しいストリームのために新しい接続を開かざるを得ないように GOAWAY フレームを送信できます。

5.1.2. Stream Concurrency

ピアは SETTINGS_MAX_CONCURRENT_STREAMS パラメータ(Section 6.5.2 を参照)を SETTINGS フレーム内で使用して同時にアクティブなストリームの数を制限できます。最大同時ストリーム設定は各エンドポイント固有であり、その設定を受け取るピアにのみ適用されます。つまり、クライアントはサーバーが開始できる同時ストリームの最大数を指定し、サーバーはクライアントが開始できる同時ストリームの最大数を指定します。

"open" 状態またはいずれかの "half-closed" 状態にあるストリームは、エンドポイントが開くことを許可されている最大ストリーム数にカウントされます。これらの三つの状態にあるストリームは SETTINGS_MAX_CONCURRENT_STREAMS 設定で広告された制限にカウントされます。"reserved" 状態のストリームはストリームの制限にカウントされません。

エンドポイントはピアが設定した制限を超えてはならない(MUST NOT)。広告された同時ストリーム制限を超える原因となる HEADERS フレームを受け取ったエンドポイントは、これはストリームエラー(Section 5.4.2)の PROTOCOL_ERROR または REFUSED_STREAM として扱わなければなりません(MUST)。エラーコードの選択は自動再試行を有効にするかどうかを決定します(詳細は Section 8.7 を参照)。

SETTINGS_MAX_CONCURRENT_STREAMS の値を現在のオープンストリーム数より小さく減らしたいエンドポイントは、新しい値を超えるストリームをクローズするか、ストリームが完了するのを許容することができます。

5.2. フロー制御

ストリームを用いた多重化は TCP 接続の使用に関する争奪をもたらし、ストリームがブロックされることがあります。フロー制御スキームは同一接続上のストリームが互いに破壊的に干渉しないようにします。フロー制御は個々のストリームおよび接続全体の両方に対して使用されます。

HTTP/2 は WINDOW_UPDATE フレーム(Section 6.9)を使用してフロー制御を提供します。

5.2.1. フロー制御の原則

HTTP/2 のストリームフロー制御は、プロトコルの変更を必要とせずにさまざまなフロー制御アルゴリズムを使用できるように設計されています。HTTP/2 のフロー制御には次の特徴があります:

  1. フロー制御は接続固有です。HTTP/2 フロー制御は単一ホップのエンドポイント間で動作し、エンドツーエンド経路全体ではありません。
  2. フロー制御は WINDOW_UPDATE フレームに基づいています。受信者はストリームごとおよび接続全体で受信可能なオクテット数を広告します。これはクレジットベースの方式です。
  3. フロー制御は方向性を持ち、全体的な制御は受信者によって提供されます。受信者は各ストリームおよび接続全体に対して任意のウィンドウサイズを設定できる(MAY)。送信者は受信者が課したフロー制御制限を遵守しなければなりません(MUST)。クライアント、サーバー、およびインターミディアリはそれぞれ受信者として自らのフロー制御ウィンドウを広告し、送信時にはピアが設定した制限を守ります。
  4. 新しいストリームおよび接続全体のフロー制御ウィンドウの初期値は 65,535 オクテットです。
  5. フレームタイプがフロー制御を適用するかどうかを決定します。本書で指定されたフレームのうち、フロー制御の対象となるのは DATA フレームのみです;他のすべてのフレームタイプは広告されたフロー制御ウィンドウの空間を消費しません。これにより重要な制御フレームがフロー制御によってブロックされないことが保証されます。
  6. エンドポイントは自分自身のフロー制御を無効にすることを選択できますが、ピアからのフロー制御信号を無視することはできません。
  7. HTTP/2 は WINDOW_UPDATE フレームの形式とセマンティクスのみを定義します(Section 6.9)。受信者がこのフレームをいつ送信するかや、その値をどのように決定するか、送信者がパケット送信をどのように選択するかは規定しません。実装は必要に応じて任意のアルゴリズムを選択できます。

実装者はリクエストやレスポンスの送信優先順位を決め、リクエストのヘッド・オブ・ラインブロッキングを回避する方法を選び、新しいストリームの作成を管理する責任があります。これらのアルゴリズムの選択は任意のフロー制御アルゴリズムと相互作用する可能性があります。

5.2.2. フロー制御の適切な使用

フロー制御は資源制約下で動作するエンドポイントを保護するために定義されています。例えば、プロキシは多数の接続間でメモリを共有する必要があり、上流接続が遅く下流接続が速い場合があります。フロー制御は、受信者があるストリームのデータを処理できないが同じ接続内の他のストリームの処理を継続したいケースを扱います。

この機能を必要としない展開では、受信側は最大サイズ(231-1)のフロー制御ウィンドウを広告し、データを受信するたびに WINDOW_UPDATE フレームを送信してこのウィンドウを維持することができます。これはその受信者にとって実質的にフロー制御を無効にすることになります。逆に、送信者は常に受信者が広告したフロー制御ウィンドウの対象となります。

資源が制約された展開(例えばメモリ)では、フロー制御を利用してピアが消費できるメモリ量を制限できます。ただし、フロー制御が帯域幅×遅延積を考慮せずに有効にされると、利用可能なネットワークリソースの非最適な使用につながる可能性がある点に注意してください([RFC7323] を参照)。

現在の帯域幅×遅延積を完全に把握していたとしても、フロー制御の実装は困難になり得ます。エンドポイントはデータが利用可能になったら直ちに TCP 受信バッファから HTTP/2 フレームを読み取り処理しなければなりません(MUST)。迅速に読まないと WINDOW_UPDATE などの重要なフレームが読まれず作用しないことによるデッドロックが発生する可能性があります。フレームを速やかに読むことは、HTTP/2 のフロー制御が資源コミットを制限するため、エンドポイントが資源枯渇攻撃にさらされることを意味しません。

5.2.3. フロー制御の性能

エンドポイントがピアが常にこの接続上でピアの帯域幅×遅延積より大きなフロー制御ウィンドウ空間を持つことを保証できない場合、受信スループットは HTTP/2 のフロー制御によって制限され、性能が低下します。

適時に WINDOW_UPDATE フレームを送信することで性能は改善できます。エンドポイントは受信スループットの改善と資源枯渇リスクの管理の必要性とのバランスをとる必要があり、ウィンドウサイズ管理戦略を定義する際には Section 10.5 を慎重に考慮するべきです。

5.3. 優先度付け

HTTP/2 のような多重化プロトコルでは、ストリームへの帯域幅や計算資源の割り当てに優先順位を付けることが良好な性能を得るために重要です。優先度付けが不適切だと HTTP/2 の性能が悪くなる可能性があります。TCP 層で並列性がない場合、性能は HTTP/1.1 よりも著しく悪化する可能性があります。

良い優先度付けスキームは、リソースの内容、リソース間の相互関係、それらがピアによってどのように使用されるかといった文脈的知識の適用から恩恵を受けます。特に、クライアントはサーバーの優先度決定に関連するリクエストの優先度に関する知識を持つことがあります。その場合、クライアントが優先度情報を提供することで性能が改善することがあります。

5.3.1. RFC 7540 における優先度の背景

RFC 7540 はリクエストの優先度をシグナリングするための豊富なシステムを定義しました。しかし、このシステムは複雑であり、一様に実装されることはありませんでした。

柔軟なスキームのために、クライアントは非常に異なる方法で優先度を表現することが可能であり、採用されたアプローチに一貫性がほとんどありませんでした。サーバーにとって汎用的なサポートを実装することは複雑でした。クライアントとサーバーの両方で優先度の実装は不均一でした。多くのサーバー展開ではリクエストの扱いに際してクライアントのシグナルを無視していました。

要するに、RFC 7540 の優先度シグナリングは成功しませんでした。

5.3.2. 本書における優先度シグナリング

この HTTP/2 の改訂は RFC 7540 で定義された優先度シグナリングを非推奨にします。優先度信号に関連する本文の大部分は本書に含まれていません。フレームフィールドの記述と一部の必須処理は保持されており、本書の実装が RFC 7540 の優先度シグナリングを使用する実装と相互運用可能であり続けるようにしています。

RFC 7540 の優先度スキームの詳細な説明は RFC 7540 の Section 5.3 に残されています。

優先度情報のシグナリングは多くの場合において良好な性能を得るために必要です。優先度情報のシグナリングが重要な場合、エンドポイントは [HTTP-PRIORITY] に記載されているような代替スキームの使用を検討することが推奨されます。

RFC 7540 の優先度シグナリングは広く採用されませんでしたが、それが提供する情報はより良い代替がない場合にまだ有用であり得ます。HEADERS や PRIORITY フレームで優先度シグナルを受信するエンドポイントは、その情報を適用することで恩恵を受けることができます。特に、これらのシグナルを消すことは代替手段がない場合には恩恵を失うことになります。

サーバーは優先度シグナルがない場合にリクエストの優先度を決定する際、他の文脈情報を使用するべきです(SHOULD)。サーバーはシグナルが完全に存在しないことを、クライアントがその機能を実装していないことの指標と解釈してもよい(MAY)。RFC 7540 のデフォルト(Section 5.3.5)はほとんどの条件下で性能が悪いことが知られており、それらを意図的に使用することは考えにくいです。

5.4. エラー処理

HTTP/2 フレーミングは二つのクラスのエラーを許容します:

  • 接続全体を使用不能にするエラー条件は接続エラーです。
  • 個々のストリームのエラーはストリームエラーです。

エラーコードの一覧は Section 7 に含まれています。

実装は処理中に複数のエラーを検出することがありますが、実装は報告するストリームエラーは最大で 1 件、接続エラーは最大で 1 件に留めるべきです(SHOULD)。

特定のストリームで報告された最初のストリームエラーは、そのストリームで他のエラーが報告されるのを防ぎます。プロトコルは複数の GOAWAY フレームを許可していますが、エンドポイントは優雅な終了中にエラーが発生した場合を除き、通常は一種類の接続エラーのみを報告するべきです(SHOULD)。もしそうなった場合、エンドポイントは既存の GOAWAY(NO_ERROR を含むもの)の他に新しいエラーコードを持つ追加の GOAWAY フレームを送信してもよい(MAY)。

エンドポイントが複数の異なるエラーを検出した場合、任意の一つのエラーを報告することができます(MAY)。フレームが接続エラーを引き起こす場合、そのエラーは必ず報告されなければなりません(MUST)。さらに、エンドポイントは適用可能な任意のエラーコードを使用できます;一般的なエラーコード(PROTOCOL_ERROR や INTERNAL_ERROR など)は、より具体的なエラーコードの代わりに常に使用できます。

5.4.1. 接続エラー処理

接続エラーとは、フレーム層のさらなる処理を阻止するか、接続状態を破壊する任意のエラーです。

接続エラーを検出したエンドポイントは、最初にピアから正常に受信した最後のストリーム識別子を含む GOAWAY フレーム(Section 6.8)を送信することが望ましい(SHOULD)。GOAWAY フレームには接続を終了する理由を示すエラーコード(Section 7)が含まれます。エラー条件のために GOAWAY を送信した後、エンドポイントは TCP 接続を閉じなければなりません(MUST)。

GOAWAY が受信側に確実に届かない可能性があることに注意してください。接続エラーの場合、GOAWAY は接続を終了する理由をピアに伝える最善の試みを提供するに過ぎません。

エンドポイントはいつでも接続を終了できます。特に、エンドポイントはストリームエラーを接続エラーと見なすことができます(MAY)。状況が許せば、エンドポイントは接続を終了するときに GOAWAY フレームを送信するべきです(SHOULD)。

5.4.2. ストリームエラー処理

ストリームエラーとは、他のストリームの処理には影響しない特定のストリームに関連するエラーです。

ストリームエラーを検出したエンドポイントは、エラーが発生したストリームの識別子を含む RST_STREAM フレームを送信します(Section 6.4)。RST_STREAM フレームにはエラーの種類を示すエラーコードが含まれます。

RST_STREAM はエンドポイントがストリーム上で送信できる最後のフレームです。RST_STREAM を送信するピアは、リモートピアが送信したか送信キューに入れたフレームを受信する準備をしていなければなりません。これらのフレームは、フィールドセクション圧縮やフロー制御のような接続状態を変更しない限り無視できます。

通常、エンドポイントは任意のストリームに対して RST_STREAM を複数回送信すべきではありません(SHOULD NOT)。しかし、閉じたストリーム上でラウンドトリップ時間を超えてフレームを受信した場合には追加の RST_STREAM を送信してもよい(MAY)。この挙動は不正な実装に対処するために許可されています。

ループを避けるために、エンドポイントは RST_STREAM に対して RST_STREAM で応答してはなりません(MUST NOT)。

5.4.3. 接続の終了

TCP 接続が閉じられたりリセットされたりしている間にストリームが "open" または "half-closed" の状態にある場合、影響を受けたストリームは自動的に再試行できません(詳細は Section 8.7 を参照)。

5.5. HTTP/2 の拡張

HTTP/2 はプロトコルの拡張を許可します。本節で述べる制限内で、プロトコル拡張は追加のサービスを提供したりプロトコルのあらゆる側面を変更したりするために使用できます。拡張は単一の HTTP/2 接続の範囲内でのみ有効です。

これは本書で定義されたプロトコル要素に適用されます。これは新しいメソッド、ステータスコード、またはフィールドを定義するなど既存の HTTP 拡張オプションに影響を与えるものではありません(詳細は Section 16 を参照)。

拡張は新しいフレームタイプ(Section 4.1)、新しい設定(Section 6.5)、または新しいエラーコード(Section 7)を使用することができます。これら拡張ポイントを管理するためのレジストリは RFC 7540 の Section 11 に定義されています。

実装はすべての拡張可能なプロトコル要素において未知またはサポートされない値を無視しなければなりません(MUST)。実装は未知またはサポートされない型のフレームを破棄しなければなりません(MUST)。これは、これらの拡張ポイントが事前の取り決めやネゴシエーションなしに拡張によって安全に使用できることを意味します。しかし、フィールドブロックの途中に現れる拡張フレームは許可されません;それらは接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱われなければなりません(MUST)。

拡張は本書で定義されたプロトコル要素や拡張機構が定義されていない要素を変更することを避けるべきです(SHOULD)。これにはフレームのレイアウトの変更、フレームが HTTP メッセージにどのように構成されるかの追加または変更(Section 8.1)、擬似ヘッダーフィールドの定義、または準拠エンドポイントが接続エラー(Section 5.4.1)と見なす可能性のあるあらゆるプロトコル要素の変更が含まれます。

既存のプロトコル要素や状態を変更する拡張は、使用される前にネゴシエートされなければなりません(MUST)。例えば、HEADERS フレームのレイアウトを変更する拡張は、ピアがそれを受け入れることを肯定的に示すまでは使用できません。この場合、改訂されたレイアウトがいつ有効になるかを調整する必要があるかもしれません。例えば DATA 以外のフレームをフロー制御の対象とすることは双方の理解を必要とする意味の変更を伴うため、ネゴシエーションを通じてのみ可能です。

本書は拡張の使用をネゴシエートする特定の方法を義務付けていませんが、設定(Section 6.5.2)がその目的に使用できることを指摘します。もし両ピアが拡張の使用を示す値を設定した場合、拡張は使用可能になります。設定が拡張ネゴシエーションに使用される場合、初期値は拡張が最初は無効になるように定義されなければなりません(MUST)。


6. フレーム定義

本仕様は多数のフレームタイプを定義しており、それぞれ一意の 8 ビットのタイプコードで識別されます。各フレームタイプは接続全体または個々のストリームの確立および管理において異なる役割を果たします。

特定のフレームタイプの送受信は接続の状態を変化させることがあります。エンドポイントが接続状態を同期して保持できない場合、接続内での正常な通信は不可能になります。したがって、エンドポイントは任意のフレームの使用によって状態がどのように影響を受けるかを共有して理解していることが重要です。

6.1. DATA

DATA フレーム(type=0x00)は、ストリームに関連する任意の可変長オクテット列を運びます。例えば、HTTP のリクエストまたはレスポンスのメッセージ本文を運ぶために 1 個以上の DATA フレームが使用されます。

DATA フレームはパディングを含めることが MAY あります。パディングはメッセージのサイズを隠すために DATA フレームへ追加できます。パディングはセキュリティ機能です(詳細は Section 10.7 を参照)。

DATA Frame {
  Length (24),
  Type (8) = 0x00,

  Unused Flags (4),
  PADDED Flag (1),
  Unused Flags (2),
  END_STREAM Flag (1),

  Reserved (1),
  Stream Identifier (31),

  [Pad Length (8)],
  Data (..),
  Padding (..2040),
}

図 3: DATA フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。DATA フレームは次の追加フィールドを含みます:

Pad Length:
フレームパディングの長さ(オクテット単位)を含む 8 ビットフィールド。これは PADDED フラグが設定されている場合にのみ存在します。
Data:
アプリケーションデータ。データの量は、存在する他のフィールドの長さを差し引いたフレームペイロードの残りです。
Padding:
アプリケーション的な意味を持たないパディングオクテット。送信時、パディングオクテットはゼロに設定されなければなりません(MUST)。受信者はパディングを検証する義務はありませんが、非ゼロのパディングを Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱うことが MAY あります。

DATA フレームは以下のフラグを定義します:

PADDED (0x08):
設定されていると、PADDED フラグは Pad Length フィールドとそれが示すパディングが存在することを示します。
END_STREAM (0x01):
設定されていると、END_STREAM フラグはこのフレームが識別されたストリームに関して送信者が送る最後のフレームであることを示します。このフラグの設定はストリームを「半クローズ」状態または「クローズ」状態に遷移させます(Section 5.1)。

DATA フレームはストリームに関連付けられていることが MUST です。Stream Identifier フィールドが 0x00 の DATA フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

DATA フレームはフロー制御の対象であり、ストリームが "open" または "half-closed (remote)" の状態にあるときにのみ送信できます。フレームペイロード全体(Pad Length および Padding フィールドを含む)はフロー制御の対象です。ストリームが "open" または "half-closed (local)" でないストリームに対する DATA フレームを受信した場合、受信者は Section 5.4.2 の種類のストリームエラー(STREAM_CLOSED)で応答しなければなりません。

パディングオクテットの総数は Pad Length フィールドの値により決まります。パディングの長さがフレームペイロードの長さ以上である場合、受信者はこれを Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません。

6.2. HEADERS

HEADERS フレーム(type=0x01)はストリームをオープンするために使用され(Section 5.1)、フィールドブロックのフラグメントも運びます。名称に反して、HEADERS フレームはヘッダセクションまたはトレーラセクションのいずれも運ぶことができます。HEADERS フレームは "idle"、"reserved (local)"、"open"、または "half-closed (remote)" の状態にあるストリーム上で送信できます。

HEADERS Frame {
  Length (24),
  Type (8) = 0x01,

  Unused Flags (2),
  PRIORITY Flag (1),
  Unused Flag (1),
  PADDED Flag (1),
  END_HEADERS Flag (1),
  Unused Flag (1),
  END_STREAM Flag (1),

  Reserved (1),
  Stream Identifier (31),

  [Pad Length (8)],
  [Exclusive (1)],
  [Stream Dependency (31)],
  [Weight (8)],
  Field Block Fragment (..),
  Padding (..2040),
}

図 4: HEADERS フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。HEADERS フレームのペイロードは次の追加フィールドを持ちます:

Pad Length:
フレームパディングの長さ(オクテット単位)を含む 8 ビットフィールド。PADDED フラグが設定されている場合にのみ存在します。
Exclusive:
単一ビットのフラグ。これは PRIORITY フラグが設定されている場合にのみ存在します。HEADERS フレームでの優先度シグナルは非推奨です(詳細は Section 5.3.2 を参照)。
Stream Dependency:
31 ビットのストリーム識別子。これは PRIORITY フラグが設定されている場合にのみ存在します。
Weight:
符号なし 8 ビット整数。これは PRIORITY フラグが設定されている場合にのみ存在します。
Field Block Fragment:
フィールドブロックのフラグメント(Section 4.3)。
Padding:
アプリケーション的意味を持たないパディングオクテット。送信時にパディングはゼロに設定されなければなりません(MUST)。受信者は検証義務を負いませんが、非ゼロのパディングを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱うことが MAY あります。

HEADERS フレームは以下のフラグを定義します:

PRIORITY (0x20):
設定されていると、PRIORITY フラグは Exclusive、Stream Dependency、および Weight フィールドが存在することを示します。
PADDED (0x08):
設定されていると、PADDED フラグは Pad Length フィールドとそれが示すパディングが存在することを示します。
END_HEADERS (0x04):
設定されていると、END_HEADERS フラグはこのフレームが完全なフィールドブロック(Section 4.3)を含み、同じストリームに続く CONTINUATION フレームがないことを示します。
END_HEADERS フラグが設定されていない HEADERS フレームは同じストリームの CONTINUATION フレームで続かなければなりません(MUST)。受信者は他の型のフレームや別のストリームのフレームを受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR と扱わなければなりません。
END_STREAM (0x01):
設定されていると、END_STREAM フラグはこのフィールドブロック(Section 4.3)が識別されたストリームに関して送信者が送る最後のものであることを示します。
END_STREAM フラグが設定された HEADERS フレームはストリームの終了を示します。ただし、END_STREAM が設定された HEADERS フレームの後に同じストリーム上で CONTINUATION フレームが続くことがあり得ます。論理的には CONTINUATION フレームは HEADERS フレームの一部です。

HEADERS フレームのフレームペイロードはフィールドブロックのフラグメントを含みます(Section 4.3)。フィールドブロックが HEADERS フレームに収まらない場合、CONTINUATION フレームで継続されます(Section 6.10)。

HEADERS フレームはストリームに関連付けられていることが MUST です。Stream Identifier フィールドが 0x00 の HEADERS フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

HEADERS フレームは Section 4.3 に記述されたとおり接続状態を変更します。

パディングオクテットの総数は Pad Length フィールドの値により決まります。パディングの長さがフレームペイロードの長さ以上である場合、受信者はこれを Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません。

6.3. PRIORITY

PRIORITY フレーム(type=0x02)は非推奨です(参照:Section 5.3.2)。PRIORITY フレームは任意のストリーム状態で送信可能で、idle や closed のストリームでも送信できます。

PRIORITY Frame {
  Length (24) = 0x05,
  Type (8) = 0x02,

  Unused Flags (8),

  Reserved (1),
  Stream Identifier (31),

  Exclusive (1),
  Stream Dependency (31),
  Weight (8),
}

図 5: PRIORITY フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。PRIORITY フレームのペイロードは次の追加フィールドを含みます:

Exclusive:
単一ビットのフラグ。
Stream Dependency:
31 ビットのストリーム識別子。
Weight:
符号なし 8 ビット整数。

PRIORITY フレームはフラグを定義しません。

PRIORITY フレームは常にストリームを識別します。Stream Identifier が 0x00 の PRIORITY フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

PRIORITY フレームの送受信は任意のストリームの状態に影響を与えません(Section 5.1)。PRIORITY フレームは "idle" や "closed" を含む任意の状態のストリーム上で送信できます。PRIORITY フレームは単一のフィールドブロックを構成する連続したフレーム間で送信してはなりません(Section 4.3)。

長さが 5 オクテットでない PRIORITY フレームは、ストリームエラー(Section 5.4.2)の FRAME_SIZE_ERROR として扱われなければなりません(MUST)。

6.4. RST_STREAM

RST_STREAM フレーム(type=0x03)はストリームを即時に終了させるためのものです。RST_STREAM はストリームのキャンセルを要求するため、またはエラー条件が発生したことを示すために送信されます。

RST_STREAM Frame {
  Length (24) = 0x04,
  Type (8) = 0x03,

  Unused Flags (8),

  Reserved (1),
  Stream Identifier (31),

  Error Code (32),
}

図 6: RST_STREAM フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。加えて、RST_STREAM フレームはエラーコードを示す 32 ビット符号なし整数を 1 つ含みます(Section 7)。このエラーコードはストリームが終了される理由を示します。

RST_STREAM フレームはフラグを定義しません。

RST_STREAM フレームは参照されたストリームを完全に終了させ、「closed」状態にします。ストリームで RST_STREAM を受信した後、受信者はそのストリームに対して追加のフレームを送信してはなりません(MUST NOT)、ただし PRIORITY は例外です。しかし、RST_STREAM を送信した後、送信側は RST_STREAM 到着前にピアが既に送信したか送信キューに入れている可能性のある追加フレームを受信して処理する準備を MUST しておかなければなりません。

RST_STREAM フレームはストリームに関連付けられていることが MUST です。Stream Identifier が 0x00 の RST_STREAM フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません。

RST_STREAM フレームは "idle" 状態のストリームに対して送信してはなりません(MUST NOT)。"idle" ストリームを識別する RST_STREAM を受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません。

長さが 4 オクテットでない RST_STREAM フレームは Section 5.4.1 の種類の接続エラー(FRAME_SIZE_ERROR)として扱われなければなりません。

6.5. SETTINGS

SETTINGS フレーム(type=0x04)は、ピアの振る舞いに関する好みや制約など、エンドポイント間の通信に影響を与える構成パラメータを伝達します。SETTINGS フレームはそれらの設定の受領を確認するためにも使用されます。SETTINGS フレーム内の個々の構成パラメータは「setting」と呼ばれます。

設定は交渉されるものではなく、送信ピアの特性を記述して受信ピアが利用します。同じ設定に対して各ピアが異なる値を広告することができます。例えば、クライアントは高い初期フロー制御ウィンドウを設定するかもしれませんが、サーバーは資源を節約するためにより低い値を設定することがあります。

接続開始時に両端点が SETTINGS フレームを MUST 送信し、接続の有効期間中いつでも任意の時点でいずれのエンドポイントも SETTINGS フレームを送信することが MAY あります。実装は本仕様で定義されたすべての設定をサポートしなければなりません(MUST)。

SETTINGS フレーム内の各パラメータはそのパラメータの既存の値を置き換えます。設定は出現順に処理され、SETTINGS フレームの受信者は各設定の現在値以外の状態を保持する必要はありません。したがって、SETTINGS パラメータの値は受信者が最後に見た値となります。

SETTINGS フレームは受信ピアによって確認されます。これを可能にするために、SETTINGS フレームは ACK フラグを定義します:

ACK (0x01):
設定されていると、このフレームがピアの SETTINGS フレームの受領と適用を確認することを示します。このビットが設定されている場合、SETTINGS フレームのフレームペイロードは MUST 空でなければなりません。ACK フラグが設定されており長さフィールド値が 0 でない SETTINGS フレームの受信は、Section 5.4.1 の種類の接続エラー(FRAME_SIZE_ERROR)として扱われなければなりません。詳細は Section 6.5.3 を参照してください(「Settings Synchronization」)。

SETTINGS フレームは常に接続に適用され、単一のストリームには適用されません。SETTINGS フレームの Stream Identifier フィールドは 0x00 でなければなりません(MUST)。Stream Identifier が 0x00 でない SETTINGS フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

SETTINGS フレームは接続状態に影響します。不正に形成されたまたは不完全な SETTINGS フレームは Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱われなければなりません。

長さが 6 オクテットの倍数でない SETTINGS フレームは Section 5.4.1 の種類の接続エラー(FRAME_SIZE_ERROR)として扱われなければなりません。

6.5.1. SETTINGS 形式

SETTINGS フレームのフレームペイロードはゼロ個以上の設定で構成され、各設定は符号なし 16 ビットの設定識別子と符号なし 32 ビットの値から成ります。

SETTINGS Frame {
  Length (24),
  Type (8) = 0x04,

  Unused Flags (7),
  ACK Flag (1),

  Reserved (1),
  Stream Identifier (31) = 0,

  Setting (48) ...,
}

Setting {
  Identifier (16),
  Value (32),
}

図 7: SETTINGS フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記載されています。SETTINGS フレームのペイロードは任意個の Setting フィールドを含み、各フィールドは次の要素で構成されます:

Identifier:
16 ビットの設定識別子(定義は Section 6.5.2 を参照)。
Value:
その設定の 32 ビット値。

6.5.2. 定義された設定

次の設定が定義されています:

SETTINGS_HEADER_TABLE_SIZE (0x01):
この設定は、受信側がフィールドブロックをデコードするために使用する圧縮テーブルの最大サイズをオクテット単位で送信者に通知します。エンコーダはこの値以下の任意のサイズを選択できます(圧縮形式固有のシグナリングを用いる。詳細は [COMPRESSION] を参照)。初期値は 4,096 オクテットです。
SETTINGS_ENABLE_PUSH (0x02):
この設定はサーバープッシュを有効または無効にするために使用できます。サーバーはこのパラメータが 0 に設定されていることを受信した場合、PUSH_PROMISE フレームを送信してはなりません(Section 8.4 を参照)。クライアントがこのパラメータを 0 に設定し確認を受けている場合、PUSH_PROMISE を受信すると接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。
SETTINGS_ENABLE_PUSH の初期値は 1 です。クライアントにとって、この値は PUSH_PROMISE を受け取る意思があることを示します。サーバーにとって、この初期値は無効であり、値 0 と同等です。0 または 1 以外の値は接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱われなければなりません。
サーバーはこの値を明示的に 1 に設定してはなりません。サーバーは SETTINGS フレームでこの設定を省略することが MAY ありますが、もし値を含めるならそれは 0 でなければなりません(MUST)。クライアントは SETTINGS_ENABLE_PUSH を 1 に設定した SETTINGS フレームを受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。
SETTINGS_MAX_CONCURRENT_STREAMS (0x03):
この設定は送信者が許容する同時並行ストリームの最大数を示します。この制限は方向性を持ち、送信者が受信者に対して許可するストリーム数に適用されます。初期状態ではこの値に制限はありません。並列性を不必要に制限しないために、この値は 100 未満にしないことが推奨されます。
SETTINGS_MAX_CONCURRENT_STREAMS に対して 0 の値を特別扱いしては SHOULD NOT という注意が示されています。ゼロ値は新しいストリームの作成を防ぎますが、これはアクティブなストリームで枯渇した任意の制限についても同様に発生し得ます。サーバーは短時間のみゼロ値を設定することが SHOULD されます。長期間リクエストを受け付けたくない場合は、接続を閉じる方が適切です。
SETTINGS_INITIAL_WINDOW_SIZE (0x04):
この設定はストリームレベルのフロー制御のための送信者の初期ウィンドウサイズ(オクテット単位)を示します。初期値は 216-1(65,535)オクテットです。
この設定はすべてのストリームのウィンドウサイズに影響します(詳細は Section 6.9.2 を参照)。
最大フロー制御ウィンドウサイズ 231-1 を超える値は接続エラー(Section 5.4.1)の FLOW_CONTROL_ERROR として扱われなければなりません(MUST)。
SETTINGS_MAX_FRAME_SIZE (0x05):
この設定は、送信者が受信することを望む最大のフレームペイロードサイズをオクテット単位で示します。
初期値は 214(16,384)オクテットです。エンドポイントが広告する値はこの初期値と最大許容フレームサイズ(224-1 または 16,777,215 オクテット)の間でなければなりません(MUST)。この範囲外の値は接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱われなければなりません。
SETTINGS_MAX_HEADER_LIST_SIZE (0x06):
この助言的設定は、送信者が受け入れる準備がある最大のフィールドセクションサイズをオクテット単位でピアに通知します。値は未圧縮のフィールドラインサイズ(名前と値の長さのオクテット単位)に各フィールドラインあたり 32 オクテットのオーバーヘッドを加えたものに基づきます。
任意のリクエストに対して、広告された値より低い上限が適用されることが MAY あります。この設定の初期値は無制限です。

未知またはサポートされない識別子を含む SETTINGS フレームを受け取ったエンドポイントは、その設定を無視しなければなりません(MUST)。

6.5.3. 設定の同期

多くの SETTINGS 値は、ピアが変更されたパラメータ値を受け取り適用した時点を理解することが有益または必要です。そのために、ACK フラグが設定されていない SETTINGS フレームの受信者は、受信後できるだけ速やかに更新された設定を適用しなければなりません(MUST)。SETTINGS フレームは受信順に確認されます。

SETTINGS フレーム内の値は、間に他のフレーム処理を挟まず出現順に処理されなければなりません(MUST)。サポートされない設定は無視されなければなりません。すべての値が処理されたら、受信者は直ちに ACK フラグが設定された SETTINGS フレームを送信しなければなりません。ACK フラグが設定された SETTINGS フレームを受信した送信者は、最も古い未確認の SETTINGS フレームの値が適用されたと見なすことができます。

送信者が合理的な時間内に確認を受け取らない場合、その送信者は接続エラー(Section 5.4.1)の SETTINGS_TIMEOUT を発生させることが MAY あります。タイムアウトを設定する際には、ピア側の処理遅延に対する余裕を考慮する必要があります。往復時間のみを基準にしたタイムアウトは誤検出を招く可能性があります。

6.6. PUSH_PROMISE

PUSH_PROMISE フレーム(type=0x05)は、送信者が開始する意図のあるストリームを事前にピアに通知するために使用されます。PUSH_PROMISE フレームには送信者が作成する予定のストリームの符号なし 31 ビット識別子と、そのストリームに対する追加のコンテキストを提供するフィールドセクションが含まれます。PUSH_PROMISE の詳細な使用法は Section 8.4 にあります。

PUSH_PROMISE Frame {
  Length (24),
  Type (8) = 0x05,

  Unused Flags (4),
  PADDED Flag (1),
  END_HEADERS Flag (1),
  Unused Flags (2),

  Reserved (1),
  Stream Identifier (31),

  [Pad Length (8)],
  Reserved (1),
  Promised Stream ID (31),
  Field Block Fragment (..),
  Padding (..2040),
}

図 8: PUSH_PROMISE フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。PUSH_PROMISE フレームのペイロードは次の追加フィールドを持ちます:

Pad Length:
フレームパディングの長さ(オクテット単位)を含む 8 ビットフィールド。PADDED フラグが設定されている場合にのみ存在します。
Promised Stream ID:
PUSH_PROMISE によって予約されるストリームを識別する符号なし 31 ビット整数。約束されたストリーム識別子は送信者が次に送るストリームとして妥当な選択でなければなりません(Section 5.1.1 の「new stream identifier」を参照)。
Field Block Fragment:
リクエスト制御データとヘッダセクションを含むフィールドブロックのフラグメント(Section 4.3)。
Padding:
アプリケーション的意味を持たないパディングオクテット。送信時、パディングオクテットはゼロに設定されなければなりません(MUST)。受信者は検証義務を負いませんが、非ゼロのパディングを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱うことが MAY あります。

PUSH_PROMISE フレームは次のフラグを定義します:

PADDED (0x08):
設定されていると、PADDED フラグは Pad Length フィールドとそれが示すパディングが存在することを示します。
END_HEADERS (0x04):
設定されていると、END_HEADERS フラグはこのフレームが完全なフィールドブロック(Section 4.3)を含み、同じストリームに続く CONTINUATION フレームがないことを示します。
END_HEADERS フラグが設定されていない PUSH_PROMISE フレームは、同じストリームの CONTINUATION フレームで続かなければなりません(MUST)。受信者は他の型のフレームや別のストリームのフレームを受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR と扱わなければなりません。

PUSH_PROMISE フレームは、送信者がピアによって開始されたストリーム上でかつそのストリームが "open" または "half-closed (remote)" 状態にある場合にのみ送信することが MUST です。PUSH_PROMISE の Stream Identifier フィールドはそれが関連するストリームを示します。Stream Identifier が 0x00 の場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

約束されたストリームは約束された順序で使用される必要はありません。PUSH_PROMISE は単に将来の使用のためにストリーム識別子を予約するだけです。

PUSH_PROMISE はピアの SETTINGS_ENABLE_PUSH 設定が 0 に設定されている場合に送信してはなりません(MUST NOT)。この設定を 0 に設定し確認を受けたエンドポイントは、PUSH_PROMISE を受信した場合それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。

PUSH_PROMISE の受信者は、約束されたストリームを拒否するために、約束されたストリーム識別子を参照する RST_STREAM を送信して送信者に返すことができます。

PUSH_PROMISE フレームは接続状態を二つの方法で変更します。第一に、フィールドブロック(Section 4.3)の包含はフィールドセクション圧縮のために維持される状態を変更する可能性があります。第二に、PUSH_PROMISE はストリームを将来の使用のために予約し、約束されたストリームを "reserved (local)" または "reserved (remote)" 状態にします。送信者は、そのストリームが "open" または "half-closed (remote)" のいずれかでない限り PUSH_PROMISE を送信してはなりません(MUST NOT)。送信者は約束されたストリームが新しいストリーム識別子として妥当な選択であることを確認しなければなりません(Section 5.1.1)。すなわち、約束されたストリームは "idle" 状態でなければなりません(MUST)。

PUSH_PROMISE を無視するとストリームが不定状態になるため、約束されたストリームは無視されるべきではありません。受信者は、PUSH_PROMISE を受信していて関連するストリームが "open" でも "half-closed (local)" でもない場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。しかし、関連するストリームで既に RST_STREAM を送信しているエンドポイントは、RST_STREAM が受信・処理される前に作成された可能性のある PUSH_PROMISE フレームを処理しなければなりません。

約束された不正なストリーム識別子(Section 5.1.1)を約束する PUSH_PROMISE の受信は、接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。ここで不正なストリーム識別子とは現在 "idle" 状態にないストリームの識別子を指します。

パディングオクテットの総数は Pad Length フィールドの値により決まります。パディングの長さがフレームペイロードの長さ以上である場合、受信者はこれを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。

6.7. PING

PING フレーム(type=0x06)は送信者からの最小往復時間を測定し、アイドル接続がまだ機能しているかを確認する手段です。PING フレームは任意のエンドポイントから送信できます。

PING Frame {
  Length (24) = 0x08,
  Type (8) = 0x06,

  Unused Flags (7),
  ACK Flag (1),

  Reserved (1),
  Stream Identifier (31) = 0,

  Opaque Data (64),
}

図 9: PING フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。

フレームヘッダに加えて、PING フレームはペイロードに 8 オクテットの不透明データを MUST 含める必要があります。送信者は任意の値を含め、そのオクテットを任意の方法で使用できます。

ACK フラグを含まない PING フレームを受信した受信者は、同一のフレームペイロードを持ち ACK フラグを設定した PING フレームで応答しなければなりません(MUST)。PING 応答は他のフレームより高い優先度で処理されることが SHOULD あります。

PING フレームは以下のフラグを定義します:

ACK (0x01):
設定されていると、この PING フレームが PING 応答であることを示します。エンドポイントは PING 応答でこのフラグを設定しなければなりません(MUST)。このフラグを含む PING フレームには応答してはなりません(MUST NOT)。

PING フレームは個々のストリームには関連付けられていません。Stream Identifier が 0x00 でない PING フレームを受信した場合、受信者は接続エラー(Section 5.4.1)の PROTOCOL_ERROR として応答しなければなりません。

長さフィールド値が 8 でない PING フレームの受信は、接続エラー(Section 5.4.1)の FRAME_SIZE_ERROR として扱われなければなりません。

6.8. GOAWAY

GOAWAY フレーム(type=0x07)は接続のシャットダウンを開始するか、重大なエラー状態を通知するために使用されます。GOAWAY により、エンドポイントは新しいストリームの受け入れを優雅に停止しつつ、既に確立されたストリームの処理を完了できます。これによりサーバーメンテナンスのような管理操作が可能になります。

エンドポイントが新しいストリームを開始することと、リモートピアが GOAWAY を送信することの間には本質的な競合状態があります。この場合に対処するため、GOAWAY には送信者がこの接続で処理した、または処理する可能性のある最後のピア開始ストリームの識別子が含まれます。例えば、サーバーが GOAWAY を送信する場合、その識別子はクライアントが開始した最大番号のストリームです。

GOAWAY を送信した後、送信者は含まれている last stream identifier より大きな識別子を持つ、受信者が開始したストリーム上で送られたフレームを無視します。GOAWAY を受信した受信者は接続上で追加のストリームを開いてはなりません(MUST NOT)、ただし新しいストリームのために新しい接続を確立することはできます。

GOAWAY の受信者が GOAWAY に示されたものより高いストリーム識別子でストリーム上にデータを送信している場合、それらのストリームは処理されていないか処理されないことになります。GOAWAY の受信者はそれらのストリームを作成されていなかったかのように扱い、新しい接続でそれらのストリームを再試行できます。

エンドポイントは接続を閉じる前に常に GOAWAY を送信することが SHOULD 推奨されます。これによりリモートピアはストリームが部分的に処理されたかどうかを知ることができます。例えば、HTTP クライアントが POST を送信している最中にサーバーが接続を閉じた場合、サーバーがどのストリームに対して処理を始めたかを示す GOAWAY を送信しないとクライアントは判断できません。

不正なピアに対しては、エンドポイントは GOAWAY を送信せずに接続を閉じることを選択する場合があります。

GOAWAY フレームが直ちに接続の終了に先行するとは限りません。GOAWAY を受信して接続を使用しなくなった受信者であっても、接続を終了する前に GOAWAY を送信することが SHOULD 推奨されます。

GOAWAY Frame {
  Length (24),
  Type (8) = 0x07,

  Unused Flags (8),

  Reserved (1),
  Stream Identifier (31) = 0,

  Reserved (1),
  Last-Stream-ID (31),
  Error Code (32),
  Additional Debug Data (..),
}

図 10: GOAWAY フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。

GOAWAY フレームはフラグを定義しません。

GOAWAY フレームは接続に適用され、特定のストリームには適用されません。Stream Identifier が 0x00 でない GOAWAY フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません(MUST)。

GOAWAY の last stream identifier には、送信者が何らかの処理を行った可能性がある、またはこれから行う可能性がある最高番号のストリーム識別子が含まれます。識別されたストリームまでのすべてのストリームは何らかの形で処理されている可能性があります。処理されたストリームがない場合、last stream identifier は 0 に設定できます。

接続が GOAWAY なしで終了した場合、last stream identifier は事実上可能な最高のストリーム識別子と見なされます。

接続が閉じられる前に完全に閉じられなかった last stream identifier 以下のストリームでは、リクエストやトランザクションの再試行は可能ではありません(ただし、HTTP GET、PUT、DELETE のような冪等な操作は例外です)。より大きな番号のストリームに対するプロトコル活動は新しい接続で安全に再試行できます。

last stream identifier 以下のストリーム上の活動はまだ正常に完了する可能性があります。GOAWAY を送信するエンドポイントは、GOAWAY を送信した後に進行中のストリームが完了するまで接続を「open」状態に維持して優雅にシャットダウンすることができます。

状況が変化した場合、エンドポイントは複数の GOAWAY を送信することが MAY あります。例えば、優雅にシャットダウンするために NO_ERROR で GOAWAY を送信した後に、即時の接続終了を要求する条件が発生した場合です。最後に受信した GOAWAY の last stream identifier はどのストリームに対して処理が行われたかを示します。エンドポイントは送信する last stream identifier の値を増加させてはなりません(MUST NOT)、なぜならピアは既に未処理のリクエストを別の接続で再試行している可能性があるためです。

クライアントが再試行できない場合、サーバーが接続を閉じたときに進行中のすべてのリクエストを失います。これは HTTP/2 を使用していないクライアントを扱うインターミディアリに特に当てはまります。サーバーが接続を優雅にシャットダウンしようとする場合、最初に last stream identifier を 231-1 に設定し、NO_ERROR コードを付けた GOAWAY を送信することが SHOULD 推奨されます。これはクライアントにシャットダウンが差し迫っており、さらなるリクエストの開始が禁止されていることを通知します。進行中のストリーム作成のために十分な時間(少なくとも 1 往復時間)を与えた後、サーバーは更新された last stream identifier を持つ別の GOAWAY を送信しても MAY あります。これによりリクエストを失うことなく接続をクリーンにシャットダウンできます。

GOAWAY を送信した後、送信者は識別された last stream より大きな識別子を持つ、受信者が開始したストリームのフレームを破棄することができます。ただし、接続状態を変更するフレームを完全に無視することはできません。例えば、HEADERSPUSH_PROMISE、および CONTINUATION フレームはフィールドセクション圧縮の状態を一貫させるために最小限の処理を MUST 受ける必要があります(Section 4.3 を参照)。同様に、DATA フレームは接続のフロー制御ウィンドウに対してカウントされなければなりません。これらのフレームを処理しないとフロー制御やフィールドセクション圧縮の状態が不整合になります。

GOAWAY フレームには接続を閉じる理由を示す 32 ビットのエラーコード(Section 7)も含まれます。

エンドポイントは任意の GOAWAY フレームのペイロードに不透明データを付加することが MAY あります。追加のデバッグデータは診断目的のみを意図しており意味論的な価値を持ちません。デバッグ情報にはセキュリティやプライバシーに敏感なデータが含まれる可能性があります。ログに保存されるなど永続的に保管されるデバッグデータは不正アクセスを防ぐための適切な保護が MUST 必要です。

6.9. WINDOW_UPDATE

WINDOW_UPDATE フレーム(type=0x08)はフロー制御を実装するために使用されます。概要は Section 5.2 を参照してください。

フロー制御は二つのレベルで動作します:個々のストリームごとと接続全体です。

両方のフロー制御はホップごと(すなわち両端点間)で行われます。インターミディアリは依存関係のある接続間で WINDOW_UPDATE フレームを転送しません。しかし、受信側によるデータ転送の抑制は元の送信者に向けてフロー制御情報の間接的な伝播を引き起こす可能性があります。

フロー制御はフロー制御の対象と識別されるフレームにのみ適用されます。本書で定義されたフレームタイプのうち、フロー制御の対象となるのは DATA フレームのみです。フロー制御の対象外のフレームは、受信者がそのフレームの処理にリソースを割り当てられない場合を除き、受け入れ処理されなければなりません(MUST)。受信者がフレームを受け入れられない場合、ストリームエラー(Section 5.4.2)または接続エラー(Section 5.4.1)の FLOW_CONTROL_ERROR を返すことが MAY あります。

WINDOW_UPDATE Frame {
  Length (24) = 0x04,
  Type (8) = 0x08,

  Unused Flags (8),

  Reserved (1),
  Stream Identifier (31),

  Reserved (1),
  Window Size Increment (31),
}

図 11: WINDOW_UPDATE フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。WINDOW_UPDATE フレームのペイロードは 1 ビットの予約ビットと、送信者が既存のフロー制御ウィンドウに加えて送信できるオクテット数を示す符号なし 31 ビット整数から成ります。フロー制御ウィンドウの増分に対する合法的範囲は 1 から 231-1(2,147,483,647)オクテットです。

WINDOW_UPDATE フレームはフラグを定義しません。

WINDOW_UPDATE フレームはストリーム固有にも接続全体にも適用できます。前者ではフレームのストリーム識別子が影響するストリームを示し、後者では値 "0" が接続全体を示します。

フロー制御ウィンドウ増分が 0 の WINDOW_UPDATE フレームを受信した受信者は、それをストリームエラー(Section 5.4.2)の PROTOCOL_ERROR として扱わなければなりません(MUST)。接続フロー制御ウィンドウに対するエラーは接続エラー(Section 5.4.1)として扱われなければなりません。

WINDOW_UPDATE は END_STREAM フラグを持つフレームを送信したピアによって送信される可能性があります。つまり、受信者が "half-closed (remote)" または "closed" 状態のストリームで WINDOW_UPDATE を受信することがありますが、受信者はこれをエラーとして扱ってはなりません(Section 5.1 を参照)。

フロー制御対象フレームを受信した受信者は、接続フロー制御ウィンドウに対するその寄与を常に勘案しなければなりません(MUST)、ただし受信者がこれを接続エラー(Section 5.4.1)と見なす場合を除きます。これはフレームがエラーであっても必要です。送信者はフレームをフロー制御ウィンドウに対してカウントしますが、受信者がカウントしないと送信者と受信者のフロー制御ウィンドウが不一致になります。

長さが 4 オクテットでない WINDOW_UPDATE フレームは Section 5.4.1 の種類の接続エラー(FRAME_SIZE_ERROR)として扱われなければなりません。

6.9.1. フロー制御ウィンドウ

HTTP/2 におけるフロー制御は、各ストリームごとに各送信者が保持するウィンドウを用いて実装されます。フロー制御ウィンドウは送信者が送信を許可されているオクテット数を示す単純な整数値であり、そのサイズは受信者のバッファ容量の尺度です。

適用されるフロー制御ウィンドウは二つあります:ストリームのフロー制御ウィンドウと接続のフロー制御ウィンドウです。送信者は受信者が広告したいずれのフロー制御ウィンドウにも収まらない長さのフロー制御対象フレームを送信してはなりません(MUST NOT)。END_STREAM フラグを持つゼロ長のフレーム(つまり空の DATA フレーム)は、いずれのフロー制御ウィンドウにも空きがない場合に MAY 送信できます。

フロー制御の計算では、9 オクテットのフレームヘッダはカウントされません。

フロー制御対象フレームを送信した後、送信者は送信したフレームの長さだけ両方のウィンドウの利用可能空間を減らします。

フレームの受信者はデータを消費してフロー制御ウィンドウの空間を解放する際に WINDOW_UPDATE フレームを送信します。ストリームレベルと接続レベルのそれぞれに対して別個の WINDOW_UPDATE が送信されます。受信者は非常に小さな増分の WINDOW_UPDATE を送信しないような仕組みを持つことが推奨されます(参考:RFC 1122 Section 4.2.3.3)。

WINDOW_UPDATE を受け取った送信者は、対応するウィンドウをフレームで指定された量だけ更新します。

送信者はフロー制御ウィンドウを 231-1 オクテットを超えてはいけません(MUST NOT)。WINDOW_UPDATE を受け取りその結果ウィンドウがこの最大値を超える場合、送信者は適切にストリームまたは接続を終了しなければなりません。ストリームの場合は RST_STREAMFLOW_CONTROL_ERROR で送信し、接続の場合は GOAWAY を同じエラーコードで送信します(MUST)。

送信者のフロー制御対象フレームと受信者の WINDOW_UPDATE フレームは完全に非同期です。この特性により、受信者はストリームのスタールを防ぐために送信者が保持するウィンドウサイズを積極的に更新できます。

6.9.2. 初期フロー制御ウィンドウサイズ

HTTP/2 接続が確立されると、新しいストリームは初期フロー制御ウィンドウサイズ 65,535 オクテットで作成されます。接続フロー制御ウィンドウも同様に 65,535 オクテットです。両端点は SETTINGS_INITIAL_WINDOW_SIZESETTINGS フレームに含めることで新しいストリームの初期ウィンドウサイズを調整できます。接続フロー制御ウィンドウは WINDOW_UPDATE フレームを使用してのみ変更できます。

SETTINGS フレームで SETTINGS_INITIAL_WINDOW_SIZE の値が設定される前は、エンドポイントはデフォルトの初期ウィンドウサイズのみを使用してフロー制御対象フレームを送信できます。同様に、接続フロー制御ウィンドウは WINDOW_UPDATE を受け取るまでデフォルト値に基づいて設定されます。

SETTINGS フレームはまだアクティブでないストリームのフロー制御ウィンドウを変更するだけでなく、すでにアクティブなフロー制御ウィンドウを持つストリーム(つまり "open" または "half-closed (remote)" 状態)に対する初期フロー制御ウィンドウサイズも変更できます。SETTINGS_INITIAL_WINDOW_SIZE の値が変化した場合、受信者は保持しているすべてのストリームフロー制御ウィンドウのサイズを新旧の差分だけ調整しなければなりません(MUST)。

SETTINGS_INITIAL_WINDOW_SIZE の変更によりフロー制御ウィンドウの利用可能空間が負の値になることがあります。送信者は負のフロー制御ウィンドウを追跡し、WINDOW_UPDATE によってウィンドウが正の値に戻るまで新しいフロー制御対象フレームを送信してはなりません(MUST NOT)。

例えば、クライアントが接続確立時に直ちに 60 KB を送信し、その後サーバーが初期ウィンドウサイズを 16 KB に設定した場合、クライアントは SETTINGS フレームの受信により利用可能なフロー制御ウィンドウを -44 KB に再計算します。クライアントは WINDOW_UPDATE によってウィンドウが正に回復するまで負のウィンドウを保持し、その後送信を再開できます。

SETTINGS フレームは接続フロー制御ウィンドウを変更できません。

SETTINGS_INITIAL_WINDOW_SIZE の変更が任意のフロー制御ウィンドウを最大サイズを超えるようにする場合、エンドポイントは接続エラー(Section 5.4.1)の FLOW_CONTROL_ERROR として扱わなければなりません(MUST)。

6.9.3. ストリームウィンドウサイズの縮小

受信者が現在のサイズより小さいフロー制御ウィンドウを使用したい場合、新しい SETTINGS フレームを送信できます。ただし、送信者は SETTINGS フレームを処理する前にそのより低い制限を超えるデータを送信する可能性があるため、受信者はそのようなデータを受信する準備を MUST しておかなければなりません。

初期フロー制御ウィンドウサイズを減らす SETTINGS フレームを送信した後も、受信者はフロー制御制限を超えるストリームの処理を継続することが MAY あります。処理を継続することは直ちにフロー制御ウィンドウのために確保する空間を縮小することを許しません。これらのストリームの進行は、送信者が送信を再開するために必要な WINDOW_UPDATE を受け取るまで停滞する可能性があります。受信者は代わりに影響を受けるストリームに対して RST_STREAMFLOW_CONTROL_ERROR のエラーコードで送信しても MAY あります。

6.10. CONTINUATION

CONTINUATION フレーム(type=0x09)はフィールドブロックフラグメントの連続を継続するために使用されます(Section 4.3)。先行するフレームが同じストリーム上であり、END_HEADERS フラグが設定されていない HEADERS、PUSH_PROMISE、または CONTINUATION フレームである限り、任意の数の CONTINUATION フレームを送信できます。

CONTINUATION Frame {
  Length (24),
  Type (8) = 0x09,

  Unused Flags (5),
  END_HEADERS Flag (1),
  Unused Flags (2),

  Reserved (1),
  Stream Identifier (31),

  Field Block Fragment (..),
}

図 12: CONTINUATION フレーム形式

Length、Type、Unused Flag(s)、Reserved、および Stream Identifier フィールドは Section 4 に記述されています。CONTINUATION フレームのペイロードはフィールドブロックのフラグメントを含みます(Section 4.3)。

CONTINUATION フレームは次のフラグを定義します:

END_HEADERS (0x04):
設定されていると、END_HEADERS フラグはこのフレームがフィールドブロックを終了することを示します(Section 4.3)。
END_HEADERS フラグが設定されていない場合、このフレームは次の CONTINUATION フレームで続かなければなりません(MUST)。受信者は他の型のフレームや別のストリーム上のフレームを受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。

CONTINUATION フレームは Section 4.3 に定義されたとおり接続状態を変更します。

CONTINUATION フレームはストリームに関連付けられていることが MUST です。Stream Identifier が 0x00 の CONTINUATION フレームを受信した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。

CONTINUATION フレームは END_HEADERS フラグが設定されていない HEADERS、PUSH_PROMISE、または CONTINUATION フレームに続くものでなければなりません。受信者がこの規則に違反していることを観測した場合、受信者は Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)で応答しなければなりません。


7. エラーコード

エラーコードは 32 ビットのフィールドで、RST_STREAM および GOAWAY フレームで使用され、ストリームや接続エラーの理由を伝達します。

エラーコードは共通のコード空間を共有します。いくつかのエラーコードはストリームにのみ適用されるか接続全体にのみ適用されるもので、他の文脈では定義された意味を持ちません。

次のエラーコードが定義されています:

NO_ERROR (0x00):
関連する状態がエラーの結果ではないことを示します。例えば、GOAWAY が接続の優雅なシャットダウンを示すためにこのコードを含む場合があります。
PROTOCOL_ERROR (0x01):
エンドポイントが特定されないプロトコルエラーを検出したことを示します。より具体的なエラーコードが利用できない場合に使用されます。
INTERNAL_ERROR (0x02):
エンドポイントが予期しない内部エラーに遭遇したことを示します。
FLOW_CONTROL_ERROR (0x03):
ピアがフロー制御プロトコルに違反したことをエンドポイントが検出したことを示します。
SETTINGS_TIMEOUT (0x04):
エンドポイントが SETTINGS フレームを送信したが、タイムリーに応答を受け取らなかったことを示します。詳細は Section 6.5.3(「Settings Synchronization」)を参照してください。
STREAM_CLOSED (0x05):
ストリームが半クローズ状態の後にフレームを受信したことを示します。
FRAME_SIZE_ERROR (0x06):
無効なサイズのフレームを受信したことを示します。
REFUSED_STREAM (0x07):
エンドポイントがアプリケーション処理を行う前にストリームを拒否したことを示します(詳細は Section 8.7 を参照)。
CANCEL (0x08):
ストリームがもはや不要であることを示すためにエンドポイントが使用するエラーコードです。
COMPRESSION_ERROR (0x09):
接続のフィールドセクション圧縮コンテキストを維持できないことを示します。
CONNECT_ERROR (0x0a):
CONNECT リクエスト(Section 8.5)に応じて確立された接続がリセットされたか異常に閉じられたことを示します。
ENHANCE_YOUR_CALM (0x0b):
ピアが過剰な負荷を生成している可能性のある振る舞いを示すことをエンドポイントが検出したことを示します。
INADEQUATE_SECURITY (0x0c):
基盤となるトランスポートが最低限のセキュリティ要件を満たしていない特性を持つことを示します(Section 9.2 を参照)。
HTTP_1_1_REQUIRED (0x0d):
エンドポイントが HTTP/2 の代わりに HTTP/1.1 の使用を要求していることを示します。

未知またはサポートされないエラーコードは特別な動作を引き起こしては MUST NOT なりません。これらは実装によって INTERNAL_ERROR と同等として扱ってもよい(MAY)です。


8. HTTP/2 における HTTP セマンティクスの表現

HTTP/2 は HTTP メッセージ抽象の具現化です(RFC 9110 の Section 6 を参照)。

8.1. HTTP メッセージのフレーミング

クライアントは新しいストリーム上で未使用のストリーム識別子を使って HTTP リクエストを送信します(Section 5.1.1 を参照)。サーバーは同じストリーム上で HTTP レスポンスを送信します。

HTTP メッセージ(リクエストまたはレスポンス)は次で構成されます:

  1. 1 個の HEADERS フレーム(続くゼロ個以上の CONTINUATION フレームを含む)でヘッダセクションを含む(詳細は RFC 9110 の Section 6.3 を参照),
  2. ゼロ個以上の DATA フレームでメッセージ本文を含む(RFC 9110 の Section 6.4 を参照),
  3. オプションで、トレーラセクションが存在する場合は 1 個の HEADERS フレーム(続くゼロ個以上の CONTINUATION フレームを含む)でトレーラを含む(RFC 9110 の Section 6.5 を参照)。

レスポンスに関してのみ、サーバーは最終的なレスポンスを含む HEADERS フレームの前に任意の数の中間レスポンスを送信してもよい(MAY)。中間レスポンスは中間(1xx) HTTP レスポンスの制御データとヘッダセクションを含む HEADERS フレーム(続くゼロ個以上の CONTINUATION フレームを含む)からなります。情報的なステータスコードを持つ HEADERS フレームが END_STREAM フラグを持つ場合は誤形成です(Section 8.1.1)。

シーケンスの最後のフレームは END_STREAM フラグを伴い、HEADERS フレームに END_STREAM が設定されていても残りのフィールドブロック断片を運ぶ CONTINUATION フレームが続く可能性があることを示します。

他のフレーム(任意のストリームからの)は、HEADERS フレームとそれに続く CONTINUATION フレームの間に発生してはなりません(MUST NOT)。

HTTP/2 はメッセージ本文を運ぶために DATA フレームを使用します。chunked 転送エンコーディング(RFC 9112 の Section 7.1)は HTTP/2 では使用できません;詳細は Section 8.2.2 を参照してください。

トレーラフィールドはストリームを終了するフィールドブロック内で運ばれます。つまり、トレーラは END_STREAM フラグを持つ HEADERS フレームで始まり、続けてゼロ個以上の CONTINUATION フレームがあり、HEADERS フレームが END_STREAM を持ちます。トレーラは擬似ヘッダーフィールド(Section 8.3)を含んでは MUST NOT なりません。トレーラ内に擬似ヘッダーフィールドを受信したエンドポイントは、そのリクエストまたはレスポンスを誤形成として扱わなければなりません(Section 8.1.1)。

リクエストまたは最終(情報的でない)ステータスコードを含むレスポンスのオープニングとなる HEADERS フレームの後に、END_STREAM フラグが設定されていない HEADERS フレームを受信したエンドポイントは、その対応するリクエストまたはレスポンスを誤形成として扱わなければなりません(Section 8.1.1)。

HTTP リクエスト/レスポンス交換は単一のストリームを完全に消費します。リクエストはストリームを "open" にする HEADERS フレームで始まり、END_STREAM フラグを持つフレームで終了します。これによりクライアント側は "half-closed (local)"、サーバー側は "half-closed (remote)" になります。レスポンスストリームはゼロ個以上の中間レスポンス(HEADERS フレーム)で始まり、最終ステータスコードを含む HEADERS フレームが続きます。

サーバーが送信する、またはクライアントが受信する END_STREAM フラグを持つフレーム(必要ならそれを完了する CONTINUATION フレームを含む)をもって HTTP レスポンスは完了します。サーバーはリクエストの未送信部分に依存しない場合、クライアントがリクエスト全体を送信する前に完全なレスポンスを送信できる(MAY)ことがあります。この場合、サーバーは完全なレスポンス(END_STREAM を持つフレーム)を送信した後にクライアントにエラーなしで送信の中止を要求するために、RST_STREAMNO_ERROR で送信してもよい(MAY)。クライアントはそのような RST_STREAM を受信したからといってレスポンスを破棄しては MUST NOT なりませんが、他の理由でレスポンスを破棄することは常にできます。

8.1.1. 誤形成メッセージ

誤形成のリクエストまたはレスポンスとは、HTTP/2 フレームの一見有効な列であるが、余分なフレーム、禁止されたフィールドや擬似ヘッダーフィールドの存在、必須擬似ヘッダーフィールドの欠如、大文字のフィールド名の含有、あるいは特定の状況での無効なフィールド名や値のために無効となるものです(詳細は Section 8.2 を参照)。

メッセージ本文を含むリクエストまたはレスポンスは content-length ヘッダフィールドを含めることができます。content-length の値が、コンテンツを構成する DATA フレームのペイロード長の合計と等しくない場合、そのメッセージは誤形成と見なされます(メッセージがコンテンツを持たないと定義されている場合を除く)。例えば 204 や 304 のレスポンスはコンテンツを含まないなどです。コンテンツを持たないと定義されたレスポンスであっても、非ゼロの content-length ヘッダフィールドを持つことは MAY ありますが、その場合 DATA フレームにコンテンツは含まれません。

HTTP リクエストやレスポンスを処理するインターミディアリ(トンネルとして動作していないもの)は、誤形成のリクエストやレスポンスを転送しては MUST NOT なりません。検出された誤形成のリクエストやレスポンスはストリームエラー(Section 5.4.2)の PROTOCOL_ERROR として扱わなければなりません(MUST)。

誤形成のリクエストに対しては、サーバーはストリームを閉じたりリセットする前に HTTP レスポンスを送信してもよい(MAY)。クライアントは誤形成のレスポンスを受け入れては MUST NOT なりません。

メッセージを逐次処理するエンドポイントは、リクエストやレスポンスを誤形成と識別する前に一部を処理している可能性があります。例えば、完全なリクエストを受け取る前に情報的なステータスや 404 を生成することが可能な場合があります。同様に、インターミディアリはエラーを検出する前に不完全なメッセージを転送することがあり得ます。サーバーは、レスポンスが残りのリクエストに依存しない場合に限り、完全なレスポンスを生成してもよい(MAY)。

これらの要件は HTTP に対する一般的な攻撃から保護することを意図しており、寛容にするよりも厳格にする方が脆弱性にさらされにくいため、意図的に厳格に定められています。

8.2. HTTP フィールド

HTTP フィールド(RFC 9110 の Section 5)は HEADERS, CONTINUATION, および PUSH_PROMISE フレームで伝達され、HPACK([COMPRESSION])で圧縮されます。

フィールド名は HTTP/2 メッセージを構築する際に小文字に変換しなければ MUST なりません。

8.2.1. フィールドの妥当性

HPACK が伝達できるいくつかの文字が、HTTP のフィールド名や値の定義では禁止されている場合があります。HTTP/2 実装は RFC 9110 の Sections 5.1 および 5.5 に従ってフィールド名と値を検証することが SHOULD 求められ、禁止文字を含むメッセージは誤形成として扱うべきです(Section 8.1.1)。

フィールドを検証しないとリクエストスマグリング攻撃に悪用される可能性があります。特に、未検証のフィールドは HTTP/1.1 にフォワードされる際に区切り文字として CR、LF、COLON などが使われるため攻撃を可能にすることがあります。実装はフィールド名と値に対して次の最小限の検証を MUST 行う必要があります:

  • フィールド名は 0x00-0x20、0x41-0x5a、または 0x7f-0xff の範囲の文字を含んでは MUST NOT なりません(すべて含む)。これは非表示の ASCII 文字、ASCII SP(0x20)、および大文字字符('A'〜'Z', ASCII 0x41〜0x5a)を除外します。
  • 擬似ヘッダーフィールド(Section 8.3)を除き、フィールド名にコロン(ASCII COLON, 0x3a)を含んでは MUST NOT なりません。
  • フィールド値はゼロ値(ASCII NUL, 0x00)、ラインフィード(ASCII LF, 0x0a)、またはキャリッジリターン(ASCII CR, 0x0d)を任意の位置に含んでは MUST NOT なりません。
  • フィールド値は ASCII 空白文字(ASCII SP または HTAB, 0x20 または 0x09)で始まったり終わったりしては MUST NOT なりません。

これらの条件に違反するフィールドを含むリクエストまたはレスポンスは誤形成として扱われなければなりません(Section 8.1.1)。特に、転送時にフィールドを処理しないインターミディアリは、上で禁止された値を含むフィールドを転送しては MUST NOT なりません。

リクエストメッセージがこれらの要件に違反する場合、実装は 400 (Bad Request) ステータスコードを生成することを SHOULD 勧めます(RFC 9110 の Section 15.5.1 を参照)、ただしより適切なステータスが定義されている場合やステータスを送信できない場合(例えばトレーラフィールドのエラー)を除きます。

8.2.2. 接続特有のヘッダフィールド

HTTP/2 は接続特有のヘッダフィールドを示すために Connection ヘッダフィールドを使用しません(RFC 9110 の Section 7.6.1 を参照)。このプロトコルでは接続特有のメタデータは他の手段で伝達されます。エンドポイントは接続特有のヘッダフィールドを含む HTTP/2 メッセージを生成しては MUST NOT なりません。これには Connection ヘッダと、RFC 9110 の Section 7.6.1 に接続特有の意味を持つと列挙されているもの(Proxy-Connection, Keep-Alive, Transfer-Encoding, Upgrade)が含まれます。これらを含むメッセージは誤形成として扱われなければなりません(Section 8.1.1)。

唯一の例外は TE ヘッダフィールドであり、HTTP/2 リクエストに存在しても MAY です;ただし存在する場合は "trailers" 以外の値を含んでは MUST NOT なりません。

HTTP/1.x メッセージを HTTP/2 に変換するインターミディアリは、RFC 9110 の Section 7.6.1 で議論されているように接続特有のヘッダフィールドを削除しなければなりません(さもなければ、そのメッセージは他の HTTP/2 エンドポイントにより誤形成として扱われます)。

8.2.3. Cookie ヘッダフィールドの圧縮

Cookie header field([COOKIE])はセミコロン(";")で cookie-pair("crumbs")を区切ります。このヘッダは複数の値を含みますが、コンマ(",")を区切りに使用しないため、cookie-pair を複数のフィールド行に分割して送信することを防ぎます(RFC 9110 の Section 5.2 を参照)。これにより圧縮効率が著しく低下する可能性があります。なぜなら個別の cookie-pair の更新が HPACK テーブルに保存されたフィールド行を無効化するからです。

圧縮効率を向上させるために、Cookie ヘッダフィールドは分割され、それぞれが 1 個以上の cookie-pair を持つ別個のヘッダフィールドとして送信されてもよい(MAY)。復号後に複数の Cookie ヘッダフィールドが存在する場合、それらは HTTP/1.1 接続などの非 HTTP/2 コンテキストに渡される前に、2 バイトの区切り 0x3b, 0x20(ASCII 文字列 "; ")で連結されなければ MUST なりません。

したがって、次の 2 つの Cookie ヘッダリストは意味的に等価です。

cookie: a=b; c=d; e=f

cookie: a=b
cookie: c=d
cookie: e=f

8.3. HTTP 制御データ

HTTP/2 は ':'(ASCII 0x3a)で始まる特殊な擬似ヘッダーフィールドを使用してメッセージ制御データを伝達します(RFC 9110 の Section 6.2 を参照)。

擬似ヘッダーフィールドは HTTP ヘッダーフィールドではありません。エンドポイントは本書で定義されたもの以外の擬似ヘッダーフィールドを生成しては MUST NOT なりません。拡張が追加の擬似ヘッダーフィールドの使用をネゴシエートする可能性がある点には注意してください(Section 5.5)。

擬似ヘッダーフィールドは定義されている文脈でのみ有効です。リクエスト用に定義された擬似ヘッダーはレスポンスに現れては MUST NOT ならず、レスポンス用に定義された擬似ヘッダーはリクエストに現れては MUST NOT です。擬似ヘッダーフィールドはトレーラセクションに現れては MUST NOT ならず、未定義または無効な擬似ヘッダーを含むリクエストやレスポンスは誤形成として扱われなければなりません(Section 8.1.1)。

すべての擬似ヘッダーフィールドは、通常のフィールド行よりも前にフィールドブロック内に現れなければ MUST なりません。通常のフィールド行の後に擬似ヘッダーが現れるフィールドブロックは誤形成として扱われなければなりません(Section 8.1.1)。

同じ擬似ヘッダーフィールド名はフィールドブロック内に複数回現れては MUST NOT なりません。リクエストやレスポンスのフィールドブロックに重複した擬似ヘッダーフィールド名が含まれる場合、そのメッセージは誤形成として扱われなければなりません(Section 8.1.1)。

8.3.1. リクエスト擬似ヘッダーフィールド

HTTP/2 リクエストに対して次の擬似ヘッダーフィールドが定義されています:

  • :method」擬似ヘッダーフィールドは HTTP メソッドを含みます(RFC 9110 の Section 9 を参照)。

  • :scheme」擬似ヘッダーフィールドはリクエストターゲットのスキーム部分を含みます。スキームは直接リクエストを生成する場合はターゲット URI から、あるいは変換されたリクエストの場合は変換元のスキームから取られます(CONNECT リクエストでは省略されます;Section 8.5 を参照)。

    ":scheme" は "http" や "https" に限定されません。プロキシやゲートウェイは非 HTTP スキームのリクエストを翻訳して HTTP を用いて非 HTTP サービスとやり取りすることができます。

  • :authority」擬似ヘッダーフィールドはターゲット URI の権限部分(authority)を伝えます。HTTP/2 リクエストの受信者は ":authority" が存在する場合、ターゲット URI を決定するために Host ヘッダフィールドを使用しては MUST NOT です。

    直接 HTTP/2 リクエストを生成するクライアントは、権限情報を伝えるために ":authority" を使用しなければ MUST です。権限情報がない場合は ":authority" を生成しては MUST NOT です。

    クライアントは ":authority" と異なる Host ヘッダを生成しては MUST NOT です。サーバーは ":authority" と異なる Host を含むリクエストを誤形成として扱うべき(SHOULD)です。比較のために値は正規化される必要があります(RFC 3986 Section 6.2 を参照)。オリジンサーバーは任意の正規化を適用できますが、その他のサーバーはスキームベースの正規化を MUST 行わなければなりません。

    HTTP/2 上でリクエストを転送するインターミディアリは、元のリクエストの制御データから権限情報を用いて ":authority" を構築しなければ MUST なり、元リクエストのターゲット URI に権限情報がない場合は生成しては MUST NOT です。Host ヘッダはこの情報の唯一の源ではない点に注意してください。

    インターミディアリが HTTP/1.1 リクエストの構築のために Host フィールドを生成する必要がある場合、インターミディアリは ":authority" の値を Host の値として使用しなければ MUST です(リクエストターゲットを変更する場合を除く)。これは潜在的な HTTP ルーティングの脆弱性を避けるために既存の Host を置き換えます。

    インターミディアリは HTTP/2 上でリクエストを転送する際に既存の Host ヘッダを保持してもよい(MAY)。

    CONNECT またはアスタリスク形式の OPTIONS リクエストのターゲットは権限情報を含まないことに注意してください。

    ":authority" は "http" または "https" スキームの URI に対して廃止された userinfo サブコンポーネントを含んでは MUST NOT です。

  • :path」擬似ヘッダーフィールドはターゲット URI のパスとクエリ部分(absolute-path と、オプションで '?' と query)を含みます。オプションのアスタリスク形式のリクエスト(OPTIONS)の場合は ":path" に '*' を含みます。

    この擬似ヘッダーは "http" または "https" の URI に対して空にしては MUST NOT です。パス成分を持たない "http" や "https" の URI は '/' を含めなければ MUST です。例外は:

    • パス成分を持たない "http" または "https" URI に対する OPTIONS リクエストは ":path" に '*' を含めなければ MUST です。
    • CONNECT リクエストでは ":path" は省略されます。

すべての HTTP/2 リクエストは、CONNECT リクエストを除き、":method", ":scheme", および ":path" の各擬似ヘッダーをちょうど 1 個ずつ持たなければ MUST なり、これらが欠けているリクエストは誤形成と見なされます(Section 8.1.1)。

個々の HTTP/2 リクエストは明示的なプロトコルバージョン指示を持ちません。すべての HTTP/2 リクエストは暗黙にプロトコルバージョン "2.0" を持っています。

8.3.2. レスポンス擬似ヘッダーフィールド

HTTP/2 レスポンスには ":status" という単一の擬似ヘッダーフィールドが定義され、HTTP ステータスコードフィールドを運びます。すべてのレスポンス(中間レスポンスを含む)にこの擬似ヘッダーが含まれていなければ MUST なりません。欠けている場合、そのレスポンスは誤形成です(Section 8.1.1)。

HTTP/2 レスポンスは暗黙にプロトコルバージョン "2.0" を持ちます。

8.4. サーバープッシュ

HTTP/2 はサーバーが先行してレスポンス(それに対応する「約束された」リクエストと共に)をクライアントに送信(「プッシュ」)できる機能を許可します。これは以前のクライアント発行リクエストに関連して行われます。

サーバープッシュは、サーバーが受け取ったリクエストに続いてクライアントが行うであろう追加リクエストを予測することでクライアント側の体感性能を改善するために設計されました。例えば HTML のリクエストにはしばしばスタイルシートやスクリプトへの参照が続きます。これらをプッシュすれば、クライアントは HTML を受け取ってそれらの参照を検出し別途リクエストを出すまで待つ必要がありません。

実際には、サーバープッシュは効果的に使用するのが難しく、キャッシュ、コンテンツネゴシエーション、ユーザーの振る舞いなどを考慮してサーバーが正しく追加リクエストを予測する必要があります。予測の誤りは追加データによる機会費用のために性能低下を招く可能性があります。特に大量のデータをプッシュすると、より重要なレスポンスとの競合を引き起こす場合があります。

クライアントはサーバープッシュを無効にするよう要求できますが、これはそれぞれのホップごとにネゴシエートされます。SETTINGS_ENABLE_PUSH を 0 に設定するとサーバープッシュが無効であることを示します。

約束されたリクエストは安全(safe)でなければ MUST なく、キャッシュ可能でなければ MUST です。約束されたリクエストはコンテンツやトレーラセクションを含めることはできません。クライアントが約束されたリクエストがキャッシュ可能でない、あるいは安全でない、またはリクエストコンテンツの存在を示す場合は、その約束されたストリームを Section 5.4.2PROTOCOL_ERROR でリセットしなければなりません。

キャッシュ可能なプッシュされたレスポンスは、クライアントが HTTP キャッシュを実装している場合にクライアントにより保存できます。プッシュされたレスポンスは、約束されたストリーム識別子で識別されるストリームがまだ開いている間にオリジンサーバーで有効に検証されたと見なされます(例えば "no-cache" がある場合など)。

キャッシュ可能でないプッシュされたレスポンスは HTTP キャッシュによって保存しては MUST NOT なりません。これらはアプリケーションに別個に提供されることが MAY あります。

サーバーは ":authority" 擬似ヘッダーフィールドに対してそのサーバーが権威を持つ値を含めなければ MUST です(Section 10.1 を参照)。クライアントはサーバーが権威を持たない PUSH_PROMISE を受信した場合、それを Section 5.4.2PROTOCOL_ERROR として扱わなければなりません。

インターミディアリはサーバーからのプッシュを受け取り、それをクライアントに転送しないことを選択できます。どのようにプッシュ情報を利用するかはそのインターミディアリ次第です。同様に、インターミディアリはサーバーとは別にクライアントへ追加のプッシュを行うこともできます。

クライアントはプッシュを行えません。したがって、サーバーは PUSH_PROMISE を受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければなりません。サーバーは SETTINGS_ENABLE_PUSH を 0 以外の値に設定してはなりません。

8.4.1. プッシュリクエスト

サーバープッシュはサーバーがリクエストに応答することと意味的に同等ですが、この場合そのリクエストはサーバーによって送信され、PUSH_PROMISE フレームとして送られます。

PUSH_PROMISE フレームは、サーバーがそのリクエストに帰属すると見なす制御データと完全なリクエストヘッダセットを含むフィールドブロックを含みます。メッセージ本文を含むリクエストに対してはレスポンスをプッシュすることはできません。

約束されたリクエストは常にクライアントの明示的なリクエストに関連付けられます。サーバーが送る PUSH_PROMISE フレームはその明示的リクエストのストリーム上で送信されます。PUSH_PROMISE フレームにはサーバーが利用可能なストリーム識別子から選ばれた約束されたストリーム識別子が含まれます(Section 5.1.1 を参照)。

PUSH_PROMISE と続く CONTINUATION フレームのヘッダフィールドは、完全で有効なリクエストヘッダセットでなければ MUST ありません(Section 8.3.1)。サーバーは ":method" に安全でキャッシュ可能なメソッドを含めなければ MUST ません。クライアントが完全かつ有効なヘッダセットを含まない PUSH_PROMISE を受け取るか ":method" が安全でないメソッドを示す場合、クライアントは約束されたストリームで Section 5.4.2PROTOCOL_ERROR で応答しなければなりません。

サーバーは、参照される予定のある約束されたレスポンスを参照するフレームを送信する前に PUSH_PROMISE を送ることを SHOULD 推奨します。これによりクライアントが約束されたフレームを受け取る前にリソースをリクエストしてしまう競合を避けられます。

例えば、サーバーが埋め込みリンクを含むドキュメントへのリクエストを受け取り、その追加イメージをクライアントにプッシュすることを選択する場合、イメージのリンクを含む DATA フレームの前に PUSH_PROMISE を送ることで、クライアントがリソースがプッシュされることを発見する前にそれらをリクエストしてしまう事態を避けられます。

PUSH_PROMISE フレームはクライアントによって送信しては MUST NOT なりません。

PUSH_PROMISE フレームはサーバーが任意のクライアント発行ストリーム上で送信できますが、そのストリームはサーバー側にとって "open" または "half-closed (remote)" でなければ MUST なりません。PUSH_PROMISE はレスポンスを構成するフレームと交錯することはありますが、単一のフィールドブロックを構成する HEADERSCONTINUATION の間には挿入できません。

PUSH_PROMISE の送信は新しいストリームを作成し、サーバー側ではそのストリームを "reserved (local)"、クライアント側では "reserved (remote)" にします。

8.4.2. プッシュされたレスポンス

PUSH_PROMISE を送信した後、サーバーは約束されたストリーム識別子を用いてサーバー起点のストリーム上でプッシュされたレスポンスの送信を開始できます。サーバーはこのストリームで HTTP レスポンスを送信し、Section 8.1 に定義されたのと同じフレーム列を使用します。このストリームは最初の HEADERS フレームが送信されるとクライアントにとって "half-closed (local)" になります。

クライアントが PUSH_PROMISE を受け取り、プッシュされたレスポンスを受け取ることを選択した場合、クライアントは約束されたストリームが閉じられるまでそのレスポンスのためのリクエストを発行しては SHOULD NOT なりません。

クライアントが何らかの理由でプッシュされたレスポンスを受け取りたくないと判断するか、サーバーが約束されたレスポンスの送信を開始するのに時間がかかりすぎる場合、クライアントは RST_STREAM を送信して、CANCEL または REFUSED_STREAM のコードを使用してプッシュされたストリームを参照できます。

クライアントは SETTINGS_MAX_CONCURRENT_STREAMS を用いてサーバーが同時にプッシュできるレスポンス数を制限できます。値を 0 にするとサーバーがプッシュレスポンスのために必要なストリームを同時に開くことを防ぎます。ただし、予約されたストリームは同時ストリーム制限に含まれないため、PUSH_PROMISE による予約は妨げられません。プッシュされたリソースを受け取りたくないクライアントは不要な予約ストリームをリセットするか SETTINGS_ENABLE_PUSH を 0 に設定する必要があります。

プッシュされたレスポンスを受け取るクライアントは、サーバーがそのレスポンスに対して権威があるか(Section 10.1 を参照)あるいはプッシュを提供したプロキシが対応するリクエストに対して構成されているかを検証しなければ MUST なりません。例えば、ある証明書が example.com の DNS-ID のみを提供する場合、そのサーバーは <https://www.example.org/doc> に対するプッシュを行えません。

PUSH_PROMISE ストリームのレスポンスは HEADERS フレームで始まり、これは直ちにストリームをサーバーにとって "half-closed (remote)"、クライアントにとって "half-closed (local)" にし、END_STREAM フラグを持つフレームで終わりストリームを "closed" にします。

8.5. CONNECT メソッド

CONNECT メソッド(RFC 9110 の Section 9.3.6)は、HTTP 接続をリモートホストへのトンネルに変換するために使用されます。CONNECT は主に HTTP プロキシと共に使用され、オリジンサーバーとの TLS セッションを確立して "https" リソースとやり取りするために用いられます。

HTTP/2 では、CONNECT メソッドは接続全体をトンネルに変換するのではなく、単一の HTTP/2 ストリーム上でリモートホストへのトンネルを確立します。CONNECT ヘッダセクションは Section 8.3.1 に定義されたように構築されますが、いくつかの相違があります。具体的には:

  • :method」 擬似ヘッダーは CONNECT に設定されます。
  • :scheme」 および 「:path」 擬似ヘッダーは省略されなければ MUST です。
  • :authority」 擬似ヘッダーには接続するホストとポートが含まれます(CONNECT リクエストの authority-form に相当します)。

これらの制約に従わない CONNECT リクエストは誤形成です(Section 8.1.1)。

CONNECT をサポートするプロキシは ":authority" に示されたホストとポートに対して TCP 接続を確立します。接続が成功すると、プロキシは 2xx 系ステータスコードを含む HEADERS フレームをクライアントに送信します。

各ピアが最初に送る HEADERS フレームの後、以降のすべての DATA フレームは TCP 接続上で送受信されるデータに対応します。クライアントが送る DATA フレームのフレームペイロードはプロキシにより TCP サーバーへ転送され、TCP サーバーから受信したデータはプロキシにより DATA フレームとして組み立てられます。DATA 以外のフレームやストリーム管理フレーム(RST_STREAM、WINDOW_UPDATE、PRIORITY)以外のフレームは接続済みストリームで送信しては MUST NOT であり、受信した場合はストリームエラー(Section 5.4.2)として扱わなければなりません。

TCP 接続はどちらのピアでも閉じることができます。DATA フレームの END_STREAM フラグは TCP の FIN ビットと同等に扱われます。クライアントは END_STREAM を受信した後に END_STREAM を設定した DATA フレームを送信することが期待されます。プロキシは END_STREAM を受け取ると、最後の TCP セグメントに対して FIN を設定してデータを送信します。TCP セグメントで FIN を受信したプロキシは END_STREAM を設定した DATA フレームを送信します。最終の TCP セグメントや DATA フレームは空であり得ることに注意してください。

TCP 接続エラーは RST_STREAM で通知されます。プロキシは TCP 接続におけるエラー(RST ビットを含む TCP セグメントの受信など)を Section 5.4.2CONNECT_ERROR として扱い、対応してストリームエラーを送信しなければなりません。対応して、プロキシはストリームや HTTP/2 接続にエラーを検出した場合に TCP セグメントに RST ビットを設定して送信することが MUST です。

8.6. Upgrade ヘッダフィールド

HTTP/2 は 101 (Switching Protocols) の情報的ステータスコードをサポートしません(RFC 9110 の Section 15.2.2 を参照)。

101 の意味は多重化プロトコルには適用されません。同様の機能は extended CONNECT(RFC 8441)や、HTTP/2 が使用するネゴシエーションメカニズムを利用することで実現できます(Section 3 を参照)。

8.7. リクエストの信頼性

一般に、HTTP クライアントはエラー発生時に非冪等リクエストを再試行できません。なぜならエラーの性質を決定する手段がないためです。サーバーで一部処理が既に行われている可能性があり、再試行すると望ましくない影響をもたらすことがあります。

HTTP/2 はクライアントに対してリクエストが処理されていないことを保証するために二つのメカニズムを提供します:

  • GOAWAY フレームは処理された可能性のある最高のストリーム番号を示します。したがって、より高い番号のストリーム上のリクエストは再試行が安全であると保証されます。
  • REFUSED_STREAM エラーコードは RST_STREAM フレームに含められ、ストリームがいかなる処理も行われる前に閉じられたことを示すことができます。リセットされたストリーム上のリクエストは安全に再試行できます。

処理されていないリクエストは失敗していないため、クライアントは自動的にそれらを再試行してもよい(MAY)、非冪等メソッドのものも含みます。

サーバーはストリームが処理されていないと示す場合、その事実を保証できなければ MUST NOT なりません。ストリーム上のフレームがアプリケーション層に渡された場合、そのストリームに対して REFUSED_STREAM を使用しては MUST NOT であり、GOAWAY フレームは指定したストリーム識別子以上の値を含めなければ MUST なりません。

これらのメカニズムに加えて、PING フレームはクライアントが接続を簡単にテストする方法を提供します。アイドル状態の接続は一部のミドルボックスにより静かに破棄されることがあり得ます。PING フレームにより、クライアントはリクエストを送らずに接続がまだ有効か安全にテストできます。

8.8. 

この節では HTTP/1.1 のリクエストとレスポンスを示し、それに相当する HTTP/2 のリクエストとレスポンスの図示を行います。

8.8.1. 単純なリクエスト

HTTP GET リクエストは制御データとメッセージ本文を持たないリクエストヘッダを含むため、単一の HEADERS フレームとして送信され、続いてゼロ個以上の CONTINUATION フレームがヘッダブロックを含むことがあります。以下の HEADERS フレームは END_HEADERS と END_STREAM の両方が設定されています;CONTINUATION フレームは送信されません。

  GET /resource HTTP/1.1           HEADERS
  Host: example.org          ==>     + END_STREAM
  Accept: image/jpeg                 + END_HEADERS
                                       :method = GET
                                       :scheme = https
                                       :authority = example.org
                                       :path = /resource
                                       host = example.org
                                       accept = image/jpeg

8.8.2. 単純なレスポンス

同様に、制御データとレスポンスヘッダだけを含むレスポンスは、シリアライズされたレスポンスヘッダブロックを含む HEADERS フレームとして送信されます(必要なら CONTINUATION で続きます)。

  HTTP/1.1 304 Not Modified        HEADERS
  ETag: "xyzzy"              ==>     + END_STREAM
  Expires: Thu, 23 Jan ...           + END_HEADERS
                                       :status = 304
                                       etag = "xyzzy"
                                       expires = Thu, 23 Jan ...

8.8.3. 複雑なリクエスト

メッセージ本文を含む HTTP POST リクエストは、1 個の HEADERS フレーム、続いてゼロ個以上の CONTINUATION フレームでヘッダを送り、続いて 1 個以上の DATA フレームを送ります。最後の CONTINUATION(または HEADERS)フレームは END_HEADERS を持ち、最後の DATA フレームは END_STREAM を持ちます:

  POST /resource HTTP/1.1          HEADERS
  Host: example.org          ==>     - END_STREAM
  Content-Type: image/jpeg           - END_HEADERS
  Content-Length: 123                  :method = POST
                                       :authority = example.org
                                       :path = /resource
  {binary data}                        :scheme = https

                                   CONTINUATION
                                     + END_HEADERS
                                       content-type = image/jpeg
                                       host = example.org
                                       content-length = 123

                                   DATA
                                     + END_STREAM
                                   {binary data}

フィールドラインに寄与するデータはフィールドブロック断片間で分散され得る点に注意してください。本例のフレームへの割当は説明のためのものであり例示的です。

8.8.4. 本文を伴うレスポンス

メッセージ本文を含むレスポンスは HEADERS、続いてゼロ個以上の CONTINUATION、続いて 1 個以上の DATA フレームとして送信され、最後の DATA フレームが END_STREAM を持ちます:

  HTTP/1.1 200 OK                  HEADERS
  Content-Type: image/jpeg   ==>     - END_STREAM
  Content-Length: 123                + END_HEADERS
                                       :status = 200
  {binary data}                        content-type = image/jpeg
                                       content-length = 123

                                   DATA
                                     + END_STREAM
                                   {binary data}

8.8.5. 情報的レスポンス

101 を除く 1xx ステータスコードを使う情報的レスポンスは HEADERS フレームとして送信され、続いてゼロ個以上の CONTINUATION フレームが来ます。

トレーラセクションはリクエスト/レスポンスのフィールドブロックおよびすべての DATA フレームの送信後にフィールドブロックとして送られます。トレーラを開始する HEADERS フレームは END_STREAM を持ちます。

次の例は 100 (Continue) ステータスコード(Expect ヘッダに "100-continue" トークンがあるリクエストに対するもの)とトレーラセクションの両方を含みます:

  HTTP/1.1 100 Continue            HEADERS
  Extension-Field: bar       ==>     - END_STREAM
                                     + END_HEADERS
                                       :status = 100
                                       extension-field = bar

  HTTP/1.1 200 OK                  HEADERS
  Content-Type: image/jpeg   ==>     - END_STREAM
  Transfer-Encoding: chunked         + END_HEADERS
  Trailer: Foo                         :status = 200
                                       content-type = image/jpeg
  123                                  trailer = Foo
  {binary data}
  0                                DATA
  Foo: bar                           - END_STREAM
                                   {binary data}

                                   HEADERS
                                     + END_STREAM
                                     + END_HEADERS
                                       foo = bar

9. HTTP/2 接続

本節は、相互運用性を改善し、既知のセキュリティ脆弱性への露出を低減し、また実装差異の可能性を減らす HTTP の属性について概説します。

9.1. 接続管理

HTTP/2 接続は永続的です。最高のパフォーマンスを得るために、クライアントはサーバーとのさらなる通信が不要であると判断されるまで(例えば、ユーザーが特定のウェブページから離れたとき)またはサーバーが接続を閉じるまで、接続を閉じないことが期待されます。

クライアントは、ホストが URI、選択された alternative service [ALT-SVC]、または設定されたプロキシから導出される場合において、特定のホストとポートの組に対して複数の HTTP/2 接続を開いては MUST NOT というわけではありませんが、通常は複数を開くべきではありません(SHOULD NOT)。

クライアントは、ストリーム識別子空間の枯渇が近い接続を置き換えるため(Section 5.1.1)、TLS 接続の鍵素材を更新するため、あるいはエラーが発生した接続を置き換えるため(Section 5.4.1)に追加の接続を作成することができます。

クライアントは異なる Server Name Indication [TLS-EXT] 値を使用したり、異なる TLS クライアント証明書を提供したりするために、同じ IP アドレスと TCP ポートに対して複数の接続を開くことが MAY ありますが、同一の構成で複数の接続を作成することは SHOULD 避けるべきです。

サーバーは可能な限り接続を開いたままにすることが推奨されますが、必要に応じてアイドル接続を終了することが許容されます。いずれかのエンドポイントがトランスポート層の TCP 接続を閉じることを選択した場合、終了するエンドポイントはまず GOAWAYSection 6.8)フレームを送信することが SHOULD 推奨されます。これにより両端点が以前に送信されたフレームが処理されたかどうかを確実に判断し、必要な残作業を優雅に完了または終了できます。

9.1.1. 接続の再利用

CONNECT メソッド(Section 8.5)を使用して作成されたトンネルを介して直接または間接的にオリジンサーバーに接続された接続は、複数の異なる URI authority コンポーネントを持つリクエストに対して MAY 再利用できます。接続はオリジンサーバーが権威を持っている限り再利用可能です(Section 10.1を参照)。TLS を使用しない TCP 接続の場合、これはホストが同じ IP アドレスに解決されることに依存します。

"https" リソースの場合、接続の再利用はさらに URI のホストに対して有効な証明書を持っていることに依存します。サーバーが提示する証明書は、クライアントがそのホストのために新しい TLS 接続を形成する際に実行するチェックを満たさなければ MUST なりませんが、実際にはクライアントはそれらのチェックを満たすことを要求します。単一の証明書は複数のオリジンに対して権威を確立するために使用できます。どのようにクライアントがサーバーが URI に対して権威を持つかを判断するかについては、RFC9110 の Section 4.3 を参照してください。

一部の展開では、複数のオリジンに対して接続を再利用すると、リクエストが誤ったオリジンサーバーに送られてしまう可能性があります。例えば、TLS 終端がミドルボックスによって行われ、その際に TLS の Server Name Indication 拡張がオリジンサーバーの選択に用いられる場合があります。これにより、クライアントが意図したターゲットではないサーバーにリクエストを送ってしまう可能性が残りますが、サーバー自体は他の点では権威を持っていることがあります。

接続の再利用をクライアントに望まないサーバーは、リクエストに対して 421 (Misdirected Request) ステータスコードを返すことで、そのリクエストに対して権威を持たないことを示すことができます(詳細は RFC9110 の Section 15.5.20 を参照)。

プロキシを使用するように構成されたクライアントは、そのプロキシへの単一の接続を通じてリクエストを送信します。つまり、プロキシ経由で送信されるすべてのリクエストはそのプロキシへの接続を再利用します。

9.2. TLS 機能の使用

HTTP/2 の実装は、TLS 経由の HTTP/2 に対して TLS version 1.2 [TLS12] 以上を使用しなければ MUST なりません。一般的な TLS 使用の指針は [TLSBCP] に従うことが SHOULD とされますが、HTTP/2 固有の追加制約がいくつかあります。

TLS 実装は Server Name Indication (SNI) [TLS-EXT] 拡張をサポートしなければ MUST なりません。サーバーが domain name [DNS-TERMS] によって識別される場合、クライアントはターゲットホストを示す代替メカニズムが使用されていない限り、server_name TLS 拡張を送信しなければ MUST です。

TLS 1.3 をネゴシエートする HTTP/2 展開に関する要件は Section 9.2.3 に含まれます。TLS 1.2 の展開は 9.2.1 および 9.2.2 の要件に従います。実装は準拠するデフォルトを提供することが推奨されますが、最終的なコンプライアンスは展開に依存することが認識されています。

9.2.1. TLS 1.2 の機能

本節は HTTP/2 と共に使用できる TLS 1.2 の機能セットに関する制約を記述します。展開上の制限のため、これらの制約が満たされない場合に TLS ネゴシエーションを失敗させることが不可能な場合があります。これらの TLS 要件を満たさない HTTP/2 接続をエンドポイントが即座に終了させてもよい(MAY)ことを示し、その際の接続エラーは Section 5.4.1INADEQUATE_SECURITY 型とします。

TLS 1.2 上の HTTP/2 展開は圧縮を無効にしなければ MUST なりません。TLS 圧縮は本来明らかにならない情報を露出させる可能性があります([RFC3749])。一般的な圧縮は不要であり、HTTP/2 はよりコンテキストに敏感な圧縮機能を提供しているため、性能やセキュリティの観点からそちらがより適切である可能性があります。

TLS 1.2 上の HTTP/2 展開は再ネゴシエーションを無効にしなければ MUST なりません。エンドポイントは TLS の再ネゴシエーションを Section 5.4.1 の種類の接続エラー(PROTOCOL_ERROR)として扱わなければなりません。再ネゴシエーションを無効にすると、基盤となる暗号スイートが暗号化できるメッセージ数の制限により長時間接続が使用不能になる可能性があります。

エンドポイントは、ハンドシェイクで提示されたクライアント資格情報の機密性保護のために再ネゴシエーションを使用することが MAY ありますが、いかなる再ネゴシエーションも接続プレフェースの送信前に行われなければ MUST なりません。サーバーは接続を確立した直後に再ネゴシエーション要求を見た場合、クライアント証明書を要求することを SHOULD します。

これは特定の保護されたリソースに対する再ネゴシエーションの使用を実質的に防ぎます。将来の仕様ではこのユースケースをサポートする方法が提供される可能性があります。あるいは、サーバーは Section 5.4 の種類のエラー、例えば HTTP_1_1_REQUIRED を用いて、クライアントに再ネゴシエーションをサポートするプロトコルの使用を要求することができます。

実装は、DHE(ephemeral finite field Diffie-Hellman)を使用する暗号スイートに対して少なくとも 2048 ビットのエフェメラル鍵交換サイズ、ならびに ECDHE(ephemeral elliptic curve Diffie-Hellman)を使用する暗号スイートに対して 224 ビットをサポートしなければ MUST です。クライアントは DHE サイズとして最大 4096 ビットを受け入れなければ MUST です。エンドポイントは、これらの下限より小さい鍵サイズのネゴシエーションを Section 5.4.1 の種類の接続エラー(INADEQUATE_SECURITY)として扱っても MAY です。

9.2.2. TLS 1.2 暗号スイート

TLS 1.2 上の HTTP/2 展開は、付録 A(Prohibited TLS 1.2 Cipher Suites)に列挙された禁止された暗号スイートのいずれかを使用しては SHOULD NOT です。

エンドポイントは、禁止された暗号スイートのいずれかがネゴシエートされた場合、接続エラー(Section 5.4.1)の INADEQUATE_SECURITY 型を生成することを選択しても MAY ます。禁止された暗号スイートを使用する展開は、その暗号スイートを受け入れる可能性のあるピアの集合が既知でない限り接続エラーを引き起こすリスクがあります。

実装は、禁止されていない暗号スイートのネゴシエーションに反応してこのエラーを生成しては MUST NOT です。したがって、クライアントが禁止されていない暗号スイートを提示した場合、HTTP/2 を用いるにあたりその暗号スイートを使用する準備をしておかなければなりません。

禁止された暗号スイートのリストには TLS 1.2 が必須とする暗号スイートも含まれているため、TLS 1.2 展開は許可される暗号スイートの集合が交差しない可能性があります。この問題を避けるため、TLS 1.2 を使用する HTTP/2 展開は TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 を P-256 楕円曲線と共にサポートしなければ MUST です。

クライアントは、HTTP/2 をサポートしていないサーバーへの接続を許容するために、禁止された暗号スイートのサポートを広告することがあります。これによりサーバーは禁止された暗号スイートを用いて HTTP/1.1 を選択することができます。しかし、アプリケーションプロトコルと暗号スイートが独立して選択される場合、禁止された暗号スイートで HTTP/2 がネゴシエートされてしまう可能性があります。

9.2.3. TLS 1.3 の機能

TLS 1.3 には以前のバージョンでは利用できなかった多くの機能があります。本節ではこれらの機能の使用について議論します。

HTTP/2 サーバーは TLS 1.3 のハンドシェイク後の CertificateRequest メッセージを送信しては MUST NOT です。HTTP/2 クライアントは TLS のハンドシェイク後の CertificateRequest メッセージを受信した場合、それを接続エラー(Section 5.4.1)の PROTOCOL_ERROR として扱わなければ MUST です。

ハンドシェイク後認証に対する禁止は、クライアントが "post_handshake_auth" TLS 拡張を提示していた場合でも適用されます。ハンドシェイク後認証のサポートは ALPN とは独立に広告され得ます。クライアントは他のプロトコルで使用するためにその能力を提示するかもしれませんが、その拡張の包含は HTTP/2 内でのサポートを意味するものではありません。

[TLS13] は NewSessionTicket や KeyUpdate のような他のハンドシェイク後メッセージを定義しており、これらは HTTP/2 と直接的な相互作用を持たないため使用可能です。アプリケーション層プロトコルとの相互作用に依存しない限り、これらの TLS メッセージはハンドシェイク完了後に送信できます。

TLS early data はリクエストを送信するために MAY 使用できますが、その際は [RFC8470] の指針に従う必要があります。クライアントはすべてのサーバ設定に対して初期値を仮定して early data 内でリクエストを送信します。


10. セキュリティ考慮事項

TLS の使用は本プロトコルの多くのセキュリティ特性を提供するために必要です。本節の多くの主張は、Section 9.2 に記載されているように TLS が使用されない限り当てはまりません。

10.1. サーバーの権威

HTTP/2 は、ある応答の提供においてサーバーが権威を持つかどうかを判断するために HTTP の authority の定義に依存します(RFC9110 の Section 4.3 を参照)。これは "http" URI スキームについてはローカルな名前解決に、"https" スキームについては認証されたサーバー識別に依存します。

10.2. クロスプロトコル攻撃

クロスプロトコル攻撃とは、攻撃者がクライアントにあるプロトコルでトランザクションを開始させ、そのトランザクションを別のプロトコルを理解するサーバーに向けさせるものです。攻撃者はトランザクションを第二のプロトコルで有効なものに見せかけることができる可能性があります。ウェブコンテキストの能力と組み合わせると、これはプライベートネットワーク内の保護が不十分なサーバーと相互作用するために利用され得ます。

ALPN 識別子として HTTP/2 を用いた TLS ハンドシェイクを完了することは、クロスプロトコル攻撃に対する十分な保護と見なせます。ALPN はサーバーが HTTP/2 で続行する意思があることを肯定的に示すため、他の TLS ベースのプロトコルへの攻撃を防ぎます。

TLS による暗号化は、攻撃者が明文プロトコルに対するクロスプロトコル攻撃で利用するデータを制御することを困難にします。

HTTP/2 の平文バージョンはクロスプロトコル攻撃に対する保護が最小限です。接続プレフェース(Section 3.4)には HTTP/1.1 サーバーを混乱させるための文字列が含まれていますが、他のプロトコルに対する特別な保護は提供されていません。

10.3. インターミディアリによるカプセル化攻撃

HPACK は他の HTTP バージョンで区切り文字として扱われる可能性のあるフィールド名や値のエンコーディングを許可します。HTTP/2 のリクエストやレスポンスを変換するインターミディアリは、別の HTTP バージョンにメッセージを翻訳する前に Section 8.2 の規則に従ってフィールドを検証しなければ MUST なりません。無効な区切り文字を含むフィールドを翻訳すると、受信者がメッセージを誤って解釈するようになり、攻撃者に悪用される可能性があります。

Section 8.2 は擬似ヘッダーフィールドの検証に関する特定の規則を含んでいません。これらのフィールドの値が使用される場合、追加の検証が必要です。これは特に ":scheme", ":authority", ":path" を結合して単一の URI 文字列を形成する場合に重要です([RFC3986])。類似の問題は、その URI や単に ":path" を ":method" と組み合わせてリクエスト行を構築する際にも発生する可能性があります。単純な連結は、入力値が完全に検証されない限り安全ではありません。

インターミディアリは、無効なフィールド名や値を含むフィールドを他の理由で却下することができます。特に、RFC9110 の Section 5 に基づく HTTP ABNF 文法に準拠しないフィールドが該当します。Section 8.2 の最小限の検証以外を行わないインターミディアリは、無効なフィールド名や値を含むメッセージを転送してしまう可能性があります。

インターミディアリが転送前に削除する必要のあるフィールドを受け取った場合(RFC9110 の Section 7.6.1 を参照)、それらのヘッダーフィールドを削除または置換して転送しなければ MUST です。加えて、インターミディアリは Content-Length フィールドを含むメッセージを転送する際にメッセージが正しく形成されるよう注意を払うべきです(Section 8.1.1)。これにより、メッセージが HTTP/1.1 に翻訳される場合でもフレーミングが正しく保たれます。

10.4. プッシュされたレスポンスのキャッシュ可能性

プッシュされたレスポンスにはクライアントからの明示的なリクエストがありません。リクエストはサーバーが PUSH_PROMISE フレームで提供します。

プッシュされたレスポンスのキャッシュは、オリジンサーバーが Cache-Control ヘッダフィールドで示す指針に基づいて可能です。しかし、単一のサーバーが複数のテナントをホストする場合は問題が生じる可能性があります。例えば、サーバーが複数のユーザーにそれぞれ小さな URI スペースを提供している場合などです。

複数のテナントが同一サーバー上でスペースを共有する場合、そのサーバーはテナントが自分に権限のないリソースの表現をプッシュできないように MUST 確保しなければなりません。これを強制しないと、テナントがキャッシュから提供される表現を上書きする表現を提供できてしまいます。

オリジンサーバーが権威を持たないプッシュされたレスポンス(Section 10.1 を参照)を使用またはキャッシュしては MUST NOT です。

10.5. サービス拒否に関する考慮事項

HTTP/2 接続は HTTP/1.1 接続よりも動作させるためにより多くのリソースのコミットを要求する可能性があります。フィールドセクション圧縮やフロー制御はより多くの状態のコミットに依存します。これらの機能の設定は、これらの機能に対するメモリのコミットを厳密に境界付けることを保証します。

PUSH_PROMISE フレームの数は同様の方法で制約されていません。サーバープッシュを受け入れるクライアントは、"reserved (remote)" 状態にあるストリーム数を制限することが SHOULD です。過剰な数のサーバープッシュストリームは、Section 5.4.2ENHANCE_YOUR_CALM 型のストリームエラーとして扱うことができます。

いくつかの HTTP/2 実装はサービス拒否の脆弱性があることが発見されました([NFLX-2019-002])。以下は実装がサービス拒否攻撃にさらされる可能性のある既知の方法の一覧です:

  • 未送信の送信待ちフレームを非効率的に追跡すると、攻撃者が大量のフレームを送信キューに入れさせることにより過負荷を引き起こす可能性があります。ピアが大量のフレームを生成させるために使用し得るいくつかの手法があります:

    • 小さなフロー制御増分を WINDOW_UPDATE フレームで提供することで、送信者が大量の DATA フレームを生成させられる可能性があります。
    • エンドポイントは PING フレームに応答する必要があります。
    • SETTINGS フレームは確認応答を必要とします。
    • 無効なリクエスト(またはサーバープッシュ)は、ピアに RST_STREAM フレームを生成させる可能性があります。
  • 攻撃者が HTTP/2 レイヤーで大量のフロー制御クレジットを提供しつつ TCP 層でクレジットを抑制すると、フレームの送信が妨げられます。TCP の限界を考慮せずにフレームを構築し記憶するエンドポイントはリソース枯渇にさらされる可能性があります。
  • 大量の小さいまたは空のフレームは、ピアにフレームヘッダの処理時間を浪費させるために悪用され得ます。ここでは注意が必要です。なぜなら、一部の小さなフレームの使用(例えば、ストリームの終端での空の DATACONTINUATION フレームの送信)は完全に正当な用途だからです。
  • SETTINGS フレームは、設定を無意味に変更したり、未定義の設定を多数送信したり、同じ設定を同じフレーム内で何度も変更したりすることでピアに余分な処理時間を費やさせるために悪用され得ます。
  • PRIORITY フレームによる再優先付けの処理は大きな処理時間を要することがあり、多数の PRIORITY フレームが送信されると過負荷を招く可能性があります。
  • フィールドセクション圧縮も攻撃者が処理リソースを浪費させる機会を提供します。詳細は RFC7541 の Section 7 を参照してください。
  • SETTINGS による制限は即座に縮小できないため、エンドポイントはピアの振る舞いに露出する可能性があります。特に接続確立直後、サーバーによって設定された制限はクライアントには知られておらず、明白なプロトコル違反でない限り超過され得ます。

サービス拒否に悪用され得る機能の多く(SETTINGS の変更、小さなフレーム、フィールドセクション圧縮など)は正当な用途があります。これらの機能は不必要または過度に使用されると負担になります。

これらの機能の使用を監視しないエンドポイントはサービス拒否のリスクにさらされます。実装はこれらの機能の使用を追跡し、その使用に上限を設定することを SHOULD です。エンドポイントは疑わしい活動を Section 5.4.1 の種類の接続エラー(ENHANCE_YOUR_CALM)として扱っても MAY です。

10.5.1. フィールドブロックサイズの制限

大きなフィールドブロック(Section 4.3)は実装に大量の状態をコミットさせる可能性があります。ルーティングに重要なフィールド行がフィールドブロックの終わり近くに現れることがあり、これによりフィールドを最終的な宛先にストリーミングできなくなります。この並び順やキャッシュの正確性を確保するなどの理由により、エンドポイントはフィールドブロック全体をバッファリングする必要が生じることがあります。フィールドブロックのサイズには厳密な上限がないため、一部のエンドポイントはフィールドブロックのために大量のメモリをコミットさせられる可能性があります。

エンドポイントは SETTINGS_MAX_HEADER_LIST_SIZE を使用して、非圧縮フィールドブロックのサイズに適用され得る制限をピアに助言することができます。この設定は助言的なものであるため、エンドポイントはこの制限を超えるフィールドブロックを送信することを MAY 選択し、リクエストまたはレスポンスが誤形成として扱われるリスクを負うことができます。この設定は接続固有であるため、任意のリクエストまたはレスポンスがより低い未知の上限を持つホップに遭遇する可能性があります。インターミディアリは異なるピアが提示した値を渡すことでこの問題を回避しようと試みることができますが、そうする義務はありません。

サーバーが処理可能なより大きなフィールドブロックを受信した場合、HTTP 431 (Request Header Fields Too Large) ステータスコードを送信することができます(参考:[RFC6585])。クライアントは処理できないレスポンスを破棄することができます。フィールドブロックは一貫した接続状態を確保するために処理されなければ MUST なく、接続が閉じられる場合を除きます。

10.5.2. CONNECT に関する問題

CONNECT メソッドは、ストリームの作成が TCP 接続の作成および維持と比較して比較的安価であるため、プロキシに対して不均衡な負荷を作り出すのに使用され得ます。プロキシは CONNECT リクエストを運ぶストリームの終了後も一部の TCP 接続リソースを維持する場合があり、これには送信側の TCP 接続が TIME_WAIT 状態に残ることが含まれます。したがって、プロキシは SETTINGS_MAX_CONCURRENT_STREAMS のみで CONNECT リクエストが消費するリソースを制限できるとは限りません。

10.6. 圧縮の使用

圧縮は、機密データが攻撃者制御下のデータと同じコンテキストで圧縮されるときに攻撃者がその秘密を回復できるようにする可能性があります。HTTP/2 はフィールド行の圧縮(Section 4.3)を可能にしますが、以下の懸念は HTTP 圧縮コンテンツ符号化の使用にも適用されます(RFC9110 の Section 8.4.1 を参照)。

Web の特性を悪用する圧縮に関する攻撃が実証されています(例:[BREACH])。攻撃者は異なる平文を含む複数のリクエストを誘導し、それぞれの結果の暗号文の長さを観察します。秘密に対する推測が正しいときに暗号文の長さが短くなることを見つけ出します。

安全なチャネルで通信する実装は、機密データと攻撃者制御のデータの両方を含むコンテンツを、別々の圧縮辞書を使用しない限り圧縮しては MUST NOT です。データのソースを確実に判別できない場合、圧縮は MUST NOT 使用されてはなりません。TLS が提供するような汎用的なストリーム圧縮は、HTTP/2 では使用しては MUST NOT です(Section 9.2 を参照)。

ヘッダーフィールドの圧縮に関する追加の考慮事項は [COMPRESSION] に記載されています。

10.7. パディングの使用

HTTP/2 内のパディングは、TLS(TLS [TLS13])などが提供する一般目的のパディングの代替を意図したものではありません。冗長なパディングは逆効果になることさえあります。正しく適用するには、パディングされるデータに関する具体的な知識が必要な場合があります。

圧縮に依存する攻撃を軽減するために、パディングより圧縮の無効化や制限の方が好ましい場合があります。

パディングはフレーム内容の正確なサイズを覆い隠すために使用でき、攻撃の緩和を目的として提供されています。例えば、攻撃者制御の平文と秘密データの両方を含む圧縮コンテンツに対する攻撃([BREACH])のようなケースです。

パディングの使用は一見したほどの保護をもたらさない場合があります。最良でも、パディングは攻撃者が観測しなければならないフレームの数を増やすことで長さ情報の推測を難しくするにすぎません。不適切に実装されたパディング方式は容易に破られます。特に、予測可能な分布のランダム化パディングはほとんど保護を提供しません。同様に、フレームペイロードを固定サイズにパディングすることは、フレームのペイロードサイズが固定境界を越えると情報を露出するため、攻撃者が平文を制御できる場合には問題を引き起こします。

インターミディアリは DATA フレームのパディングを保持することを SHOULD ますが、HEADERS および PUSH_PROMISE フレームのパディングは省略しても MAY です。インターミディアリがフレームのパディング量を変更する正当な理由としては、パディングが提供する保護を改善するためのものがあります。

10.8. プライバシーに関する考慮事項

HTTP/2 のいくつかの特性は、観測者が単一のクライアントまたはサーバーの行動を時間を通じて相関付ける機会を提供します。これには設定の値、フロー制御ウィンドウの管理方法、ストリームへの優先度割り当ての方法、刺激に対する反応のタイミング、設定で制御される機能の取り扱いなどが含まれます。

これらが挙動の観測可能な違いを生む範囲では、それらは RFC6973 の Section 3.2 に定義されたように特定のクライアントのフィンガープリンティングの基礎として利用され得ます(参照:[PRIVACY])。

HTTP/2 が単一の TCP 接続を使用することを好む点は、サイト上でのユーザーの活動の相関を可能にします。異なるオリジンに対して接続を再利用することは、それらのオリジン間での追跡を許すことになります。

PING および SETTINGS フレームは即時の応答を要求するため、これらはエンドポイントがピアまでのレイテンシを測定するために使用され得ます。特定のシナリオではこれはプライバシーへの影響を持つ可能性があります。

10.9. リモートタイミング攻撃

リモートタイミング攻撃は、サーバーが秘密を使用するリクエストを処理する際の処理時間の変動を観測することで秘密を抽出します。HTTP/2 は同時のリクエスト作成と処理を可能にするため、攻撃者に対していつリクエスト処理が開始されるかについてより良い制御を与える可能性があります。複数の HTTP/2 リクエストが同一の IP パケットや TLS レコードに含まれることがあり得ます。したがって、HTTP/2 はリクエスト配信の可変性を排除してリモートタイミング攻撃を効率化し得ます。残る時間的変動の要因はリクエストの順序とレスポンスの配信だけになります。

処理時間が秘密の値に依存しないようにすることが、あらゆる形態のタイミング攻撃に対する最良の防御です。


11. IANAに関する考慮事項

この改訂版のHTTP/2では、HTTP2-Settings ヘッダーフィールドと、 h2c アップグレードトークン(いずれも [RFC7540] で定義) を廃止済みとしています。

Section 11[RFC7540] において h2 および h2c の ALPN 識別子と PRI HTTP メソッドを登録しました。RFC 7540 はまたフレームタイプ、 設定、およびエラーコードのためのレジストリを確立しました。これらの登録とレジストリは HTTP/2 に適用され、本書では再定義していません。

IANA は次のレジストリにおける RFC 7540 への参照を本書を参照するよう更新しました: "TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs"、"HTTP/2 Frame Type"、 "HTTP/2 Settings"、"HTTP/2 Error Code"、および "HTTP Method Registry"。PRI メソッドの登録は Section 3.4 を参照するよう 更新されました;その他の節番号は変更されていません。

IANA は RFC 7540 で実験的使用のために予約されていた "HTTP/2 Frame Type" および "HTTP/2 Settings" レジストリの当該部分のポリシーを変更しました。これらのレジストリの部分は、 各レジストリの残りと同じポリシーで運用されます。

11.1. HTTP2-Settings ヘッダーフィールド登録

本節では、Section 11.5 によって登録された HTTP2-Settings ヘッダーフィールドを "Hypertext Transfer Protocol (HTTP) Field Name Registry" で廃止済みとして扱うことを記します。この機能は削除されました:参照 Section 3.1。登録は Section 18.4 of [HTTP] が要求する詳細を含むように更新されています:

Field Name:
HTTP2-Settings
Status:
廃止済み
Reference:
Section 3.2.1 of [RFC7540] 
Comments:
廃止済み;本書の Section 11.1 を参照。

11.2. h2c アップグレードトークン

本節は、Section 11.8 によって登録された h2c アップグレードトークンを "Hypertext Transfer Protocol (HTTP) Upgrade Token Registry" で廃止済みとして記録します。この機能は削除されました:参照 Section 3.1。登録は次のように更新されます:

Value:
h2c
Description:
(OBSOLETE) Hypertext Transfer Protocol version 2 (HTTP/2)
Expected Version Tokens:
なし
Reference:
Section 3.1 of this document

12. 参考文献

12.1. ノルマティブ参考文献

[CACHING]
Fielding, R., 編, Nottingham, M., 編, および J. Reschke, 編, “HTTP Caching”, STD 98, RFC 9111, DOI 10.17487/RFC9111, 2022年6月, <https://www.rfc-editor.org/info/rfc9111>。
[COMPRESSION]
Peon, R. および H. Ruellan, “HPACK: Header Compression for HTTP/2”, RFC 7541, DOI 10.17487/RFC7541, 2015年5月, <https://www.rfc-editor.org/info/rfc7541>。
[COOKIE]
Barth, A., “HTTP State Management Mechanism”, RFC 6265, DOI 10.17487/RFC6265, 2011年4月, <https://www.rfc-editor.org/info/rfc6265>。
[HTTP]
Fielding, R., 編, Nottingham, M., 編, および J. Reschke, 編, “HTTP Semantics”, STD 97, RFC 9110, DOI 10.17487/RFC9110, 2022年6月, <https://www.rfc-editor.org/info/rfc9110>。
[QUIC]
Iyengar, J., 編および M. Thomson, 編, “QUIC: A UDP-Based Multiplexed and Secure Transport”, RFC 9000, DOI 10.17487/RFC9000, 2021年5月, <https://www.rfc-editor.org/info/rfc9000>。
[RFC2119]
Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, 1997年3月, <https://www.rfc-editor.org/info/rfc2119>。
[RFC3986]
Berners-Lee, T., Fielding, R., および L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax”, STD 66, RFC 3986, DOI 10.17487/RFC3986, 2005年1月, <https://www.rfc-editor.org/info/rfc3986>。
[RFC8174]
Leiba, B., “Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words”, BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2017年5月, <https://www.rfc-editor.org/info/rfc8174>。
[RFC8422]
Nir, Y., Josefsson, S., および M. Pegourie-Gonnard, “Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier”, RFC 8422, DOI 10.17487/RFC8422, 2018年8月, <https://www.rfc-editor.org/info/rfc8422>。
[RFC8470]
Thomson, M., Nottingham, M., および W. Tarreau, “Using Early Data in HTTP”, RFC 8470, DOI 10.17487/RFC8470, 2018年9月, <https://www.rfc-editor.org/info/rfc8470>。
[TCP]
Postel, J., “Transmission Control Protocol”, STD 7, RFC 793, DOI 10.17487/RFC0793, 1981年9月, <https://www.rfc-editor.org/info/rfc793>。
[TLS-ALPN]
Friedl, S., Popov, A., Langley, A., および E. Stephan, “Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension”, RFC 7301, DOI 10.17487/RFC7301, 2014年7月, <https://www.rfc-editor.org/info/rfc7301>。
[TLS-ECDHE]
Rescorla, E., “TLS Elliptic Curve Cipher Suites with SHA-256/384 and AES Galois Counter Mode (GCM)”, RFC 5289, DOI 10.17487/RFC5289, 2008年8月, <https://www.rfc-editor.org/info/rfc5289>。
[TLS-EXT]
Eastlake 3rd, D., “Transport Layer Security (TLS) Extensions: Extension Definitions”, RFC 6066, DOI 10.17487/RFC6066, 2011年1月, <https://www.rfc-editor.org/info/rfc6066>。
[TLS12]
Dierks, T. および E. Rescorla, “The Transport Layer Security (TLS) Protocol Version 1.2”, RFC 5246, DOI 10.17487/RFC5246, 2008年8月, <https://www.rfc-editor.org/info/rfc5246>。
[TLS13]
Rescorla, E., “The Transport Layer Security (TLS) Protocol Version 1.3”, RFC 8446, DOI 10.17487/RFC8446, 2018年8月, <https://www.rfc-editor.org/info/rfc8446>。
[TLSBCP]
Sheffer, Y., Holz, R., および P. Saint-Andre, “Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)”, BCP 195, RFC 7525, DOI 10.17487/RFC7525, 2015年5月, <https://www.rfc-editor.org/info/rfc7525>。

12.2. 参考資料(情報提供)

[ALT-SVC]
Nottingham, M., McManus, P., および J. Reschke, “HTTP Alternative Services”, RFC 7838, DOI 10.17487/RFC7838, 2016年4月, <https://www.rfc-editor.org/info/rfc7838>。
[BREACH]
Gluck, Y., Harris, N., および A. Prado, “BREACH: Reviving the CRIME Attack”, 2013年7月, <https://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>。
[DNS-TERMS]
Hoffman, P., Sullivan, A., および K. Fujiwara, “DNS Terminology”, BCP 219, RFC 8499, DOI 10.17487/RFC8499, 2019年1月, <https://www.rfc-editor.org/info/rfc8499>。
[HTTP-PRIORITY]
Oku, K. および L. Pardue, “Extensible Prioritization Scheme for HTTP”, RFC 9218, DOI 10.17487/RFC9218, 2022年6月, <https://www.rfc-editor.org/info/rfc9218>。
[HTTP/1.1]
Fielding, R., 編, Nottingham, M., 編, および J. Reschke, 編, “HTTP/1.1”, STD 99, RFC 9112, DOI 10.17487/RFC9112, 2022年6月, <https://www.rfc-editor.org/info/rfc9112>。
[NFLX-2019-002]
Netflix, “HTTP/2 Denial of Service Advisory”, 2019年8月, <https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md>。
[PRIVACY]
Cooper, A., Tschofenig, H., Aboba, B., Peterson, J., Morris, J., Hansen, M., および R. Smith, “Privacy Considerations for Internet Protocols”, RFC 6973, DOI 10.17487/RFC6973, 2013年7月, <https://www.rfc-editor.org/info/rfc6973>。
[RFC1122]
Braden, R., 編, “Requirements for Internet Hosts - Communication Layers”, STD 3, RFC 1122, DOI 10.17487/RFC1122, 1989年10月, <https://www.rfc-editor.org/info/rfc1122>。
[RFC3749]
Hollenbeck, S., “Transport Layer Security Protocol Compression Methods”, RFC 3749, DOI 10.17487/RFC3749, 2004年5月, <https://www.rfc-editor.org/info/rfc3749>。
[RFC6125]
Saint-Andre, P. および J. Hodges, “Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)”, RFC 6125, DOI 10.17487/RFC6125, 2011年3月, <https://www.rfc-editor.org/info/rfc6125>。
[RFC6585]
Nottingham, M. および R. Fielding, “Additional HTTP Status Codes”, RFC 6585, DOI 10.17487/RFC6585, 2012年4月, <https://www.rfc-editor.org/info/rfc6585>。
[RFC7323]
Borman, D., Braden, B., Jacobson, V., および R. Scheffenegger, 編, “TCP Extensions for High Performance”, RFC 7323, DOI 10.17487/RFC7323, 2014年9月, <https://www.rfc-editor.org/info/rfc7323>。
[RFC7540]
Belshe, M., Peon, R., および M. Thomson, 編, “Hypertext Transfer Protocol Version 2 (HTTP/2)”, RFC 7540, DOI 10.17487/RFC7540, 2015年5月, <https://www.rfc-editor.org/info/rfc7540>。
[RFC8441]
McManus, P., “Bootstrapping WebSockets with HTTP/2”, RFC 8441, DOI 10.17487/RFC8441, 2018年9月, <https://www.rfc-editor.org/info/rfc8441>。
[RFC8740]
Benjamin, D., “Using TLS 1.3 with HTTP/2”, RFC 8740, DOI 10.17487/RFC8740, 2020年2月, <https://www.rfc-editor.org/info/rfc8740>。
[TALKING]
Huang, L., Chen, E., Barth, A., Rescorla, E., および C. Jackson, “Talking to Yourself for Fun and Profit”, 2011年, <https://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf>。

付録 A. 禁止された TLS 1.2 暗号スイート

HTTP/2 実装は、次のいずれかの暗号スイートが TLS 1.2 によって交渉された場合を、 接続エラー(Section 5.4.1) タイプ INADEQUATE_SECURITY として扱うことが MAY です:

  • TLS_NULL_WITH_NULL_NULL
  • TLS_RSA_WITH_NULL_MD5
  • TLS_RSA_WITH_NULL_SHA
  • TLS_RSA_EXPORT_WITH_RC4_40_MD5
  • TLS_RSA_WITH_RC4_128_MD5
  • TLS_RSA_WITH_RC4_128_SHA
  • TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
  • TLS_RSA_WITH_IDEA_CBC_SHA
  • TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
  • TLS_RSA_WITH_DES_CBC_SHA
  • TLS_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
  • TLS_DH_DSS_WITH_DES_CBC_SHA
  • TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
  • TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
  • TLS_DH_RSA_WITH_DES_CBC_SHA
  • TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
  • TLS_DHE_DSS_WITH_DES_CBC_SHA
  • TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  • TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
  • TLS_DHE_RSA_WITH_DES_CBC_SHA
  • TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
  • TLS_DH_anon_WITH_RC4_128_MD5
  • TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
  • TLS_DH_anon_WITH_DES_CBC_SHA
  • TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
  • TLS_KRB5_WITH_DES_CBC_SHA
  • TLS_KRB5_WITH_3DES_EDE_CBC_SHA
  • TLS_KRB5_WITH_RC4_128_SHA
  • TLS_KRB5_WITH_IDEA_CBC_SHA
  • TLS_KRB5_WITH_DES_CBC_MD5
  • TLS_KRB5_WITH_3DES_EDE_CBC_MD5
  • TLS_KRB5_WITH_RC4_128_MD5
  • TLS_KRB5_WITH_IDEA_CBC_MD5
  • TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
  • TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA
  • TLS_KRB5_EXPORT_WITH_RC4_40_SHA
  • TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
  • TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5
  • TLS_KRB5_EXPORT_WITH_RC4_40_MD5
  • TLS_PSK_WITH_NULL_SHA
  • TLS_DHE_PSK_WITH_NULL_SHA
  • TLS_RSA_PSK_WITH_NULL_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • TLS_DH_DSS_WITH_AES_128_CBC_SHA
  • TLS_DH_RSA_WITH_AES_128_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_DH_anon_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_DH_DSS_WITH_AES_256_CBC_SHA
  • TLS_DH_RSA_WITH_AES_256_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_DH_anon_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_NULL_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DH_DSS_WITH_AES_128_CBC_SHA256
  • TLS_DH_RSA_WITH_AES_128_CBC_SHA256
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_DH_DSS_WITH_AES_256_CBC_SHA256
  • TLS_DH_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DH_anon_WITH_AES_128_CBC_SHA256
  • TLS_DH_anon_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
  • TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
  • TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
  • TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
  • TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
  • TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
  • TLS_PSK_WITH_RC4_128_SHA
  • TLS_PSK_WITH_3DES_EDE_CBC_SHA
  • TLS_PSK_WITH_AES_128_CBC_SHA
  • TLS_PSK_WITH_AES_256_CBC_SHA
  • TLS_DHE_PSK_WITH_RC4_128_SHA
  • TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
  • TLS_DHE_PSK_WITH_AES_128_CBC_SHA
  • TLS_DHE_PSK_WITH_AES_256_CBC_SHA
  • TLS_RSA_PSK_WITH_RC4_128_SHA
  • TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
  • TLS_RSA_PSK_WITH_AES_128_CBC_SHA
  • TLS_RSA_PSK_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_SEED_CBC_SHA
  • TLS_DH_DSS_WITH_SEED_CBC_SHA
  • TLS_DH_RSA_WITH_SEED_CBC_SHA
  • TLS_DHE_DSS_WITH_SEED_CBC_SHA
  • TLS_DHE_RSA_WITH_SEED_CBC_SHA
  • TLS_DH_anon_WITH_SEED_CBC_SHA
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DH_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DH_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DH_DSS_WITH_AES_128_GCM_SHA256
  • TLS_DH_DSS_WITH_AES_256_GCM_SHA384
  • TLS_DH_anon_WITH_AES_128_GCM_SHA256
  • TLS_DH_anon_WITH_AES_256_GCM_SHA384
  • TLS_PSK_WITH_AES_128_GCM_SHA256
  • TLS_PSK_WITH_AES_256_GCM_SHA384
  • TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
  • TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
  • TLS_PSK_WITH_AES_128_CBC_SHA256
  • TLS_PSK_WITH_AES_256_CBC_SHA384
  • TLS_PSK_WITH_NULL_SHA256
  • TLS_PSK_WITH_NULL_SHA384
  • TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
  • TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
  • TLS_DHE_PSK_WITH_NULL_SHA256
  • TLS_DHE_PSK_WITH_NULL_SHA384
  • TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
  • TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
  • TLS_RSA_PSK_WITH_NULL_SHA256
  • TLS_RSA_PSK_WITH_NULL_SHA384
  • TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
  • TLS_EMPTY_RENEGOTIATION_INFO_SCSV
  • TLS_ECDH_ECDSA_WITH_NULL_SHA
  • TLS_ECDH_ECDSA_WITH_RC4_128_SHA
  • TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_NULL_SHA
  • TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
  • TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDH_RSA_WITH_NULL_SHA
  • TLS_ECDH_RSA_WITH_RC4_128_SHA
  • TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_RSA_WITH_NULL_SHA
  • TLS_ECDHE_RSA_WITH_RC4_128_SHA
  • TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_ECDH_anon_WITH_NULL_SHA
  • TLS_ECDH_anon_WITH_RC4_128_SHA
  • TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDH_anon_WITH_AES_128_CBC_SHA
  • TLS_ECDH_anon_WITH_AES_256_CBC_SHA
  • TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA
  • TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
  • TLS_SRP_SHA_WITH_AES_128_CBC_SHA
  • TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
  • TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA
  • TLS_SRP_SHA_WITH_AES_256_CBC_SHA
  • TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA
  • TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_PSK_WITH_RC4_128_SHA
  • TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_PSK_WITH_NULL_SHA
  • TLS_ECDHE_PSK_WITH_NULL_SHA256
  • TLS_ECDHE_PSK_WITH_NULL_SHA384
  • TLS_RSA_WITH_ARIA_128_CBC_SHA256
  • TLS_RSA_WITH_ARIA_256_CBC_SHA384
  • TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256
  • TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384
  • TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256
  • TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384
  • TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256
  • TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384
  • TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
  • TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
  • TLS_DH_anon_WITH_ARIA_128_CBC_SHA256
  • TLS_DH_anon_WITH_ARIA_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384
  • TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256
  • TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384
  • TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256
  • TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384
  • TLS_RSA_WITH_ARIA_128_GCM_SHA256
  • TLS_RSA_WITH_ARIA_256_GCM_SHA384
  • TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256
  • TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384
  • TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256
  • TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384
  • TLS_DH_anon_WITH_ARIA_128_GCM_SHA256
  • TLS_DH_anon_WITH_ARIA_256_GCM_SHA384
  • TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256
  • TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384
  • TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256
  • TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384
  • TLS_PSK_WITH_ARIA_128_CBC_SHA256
  • TLS_PSK_WITH_ARIA_256_CBC_SHA384
  • TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
  • TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384
  • TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
  • TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384
  • TLS_PSK_WITH_ARIA_128_GCM_SHA256
  • TLS_PSK_WITH_ARIA_256_GCM_SHA384
  • TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256
  • TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384
  • TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256
  • TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
  • TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
  • TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
  • TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
  • TLS_RSA_WITH_AES_128_CCM
  • TLS_RSA_WITH_AES_256_CCM
  • TLS_RSA_WITH_AES_128_CCM_8
  • TLS_RSA_WITH_AES_256_CCM_8
  • TLS_PSK_WITH_AES_128_CCM
  • TLS_PSK_WITH_AES_256_CCM
  • TLS_PSK_WITH_AES_128_CCM_8
  • TLS_PSK_WITH_AES_256_CCM_8

詳細については、Section 9.2.2 を参照してください。


付録 B. RFC 7540 からの変更点

この改訂には、次の実質的な変更が含まれます:

  • TLS 1.3 の使用は [RFC8740] に基づき定義されており、本書はそれを廃止します。
  • RFC 7540 で定義された優先度スキームは廃止予定です。PRIORITY フレームの形式および HEADERS フレーム内の優先度フィールドの定義は保持され、PRIORITY フレームの送受信が許される条件に関する規則も保持されますが、これらのフィールドの意味論は RFC 7540 にのみ記述されています。RFC 7540 の優先度シグナリングスキームは成功しませんでした。より単純なシグナリングである [HTTP-PRIORITY] の使用が推奨されます。
  • HTTP/1.1 の Upgrade 機構は廃止予定であり、本書ではもはや規定されません。これは広く配備されることはなく、プレーンテキストの HTTP/2 利用者は代わりに prior-knowledge 実装を選択しました。
  • フィールド名と値の検証が狭められました。中継者に対して必須となる検証は正確に定義され、リクエストに対するエラー報告は 400 系のステータスコードを送ることを奨励するように修正されました。
  • 実験的使用のために予約されていた設定値およびフレームタイプのコードポイントの範囲は、一般利用可能になりました。
  • 禁止された接続固有のヘッダーフィールドは、より正確かつ包括的に特定されました。
  • Host と ":authority" が異なることはもはや許可されません。
  • settings の変更後に Dynamic Table Size Update 命令を送信するための規則は、Section 4.3.1 で明確化されました。

編集上の変更も含まれます。特に用語と文書構成の変更は、コア HTTP セマンティクス[HTTP])の更新への対応です。これらの文書には、RFC 7540 で最初に定義された概念(421 ステータスコードやコネクションの合流など)が含まれるようになりました。


謝辞

この文書への重要な入力に対するクレジットは、長年にわたり HTTP ワーキンググループに貢献した多数の人々に帰するものです。[RFC7540] には、貢献に対して謝意を表すべきより包括的な人物一覧が含まれています。


貢献者

Mike Belshe と Roberto Peon が本書の元になった文章を作成しました。


著者の連絡先

Martin Thomson (編集者)
Mozilla
Australia
EMail: mt@lowentropy.net
Cory Benfield (編集者)
Apple Inc.
EMail: cbenfield@apple.com