この文書は「RFC7540」の日本語訳です。

原文の最新版 は、この日本語訳が参照した版から更新されている可能性があります。
この日本語訳は参考情報であり、正式な文書ではないことにも注意してください。また、翻訳において生じた誤りが含まれる可能性があるため、必ず原文もあわせて参照することを推奨します。

公開日:
2015-05-17
更新日:
2015-07-22
翻訳者:
Moto Ishizawa <>
翻訳協力:
Shigeki Ohtsu, Kazu Yamamoto

概要

この仕様は、HTTP バージョン2 (HTTP/2) と呼ばれる、最適化された Hypertext Transfer Protocol (HTTP) のセマンティクス表現について説明します。HTTP/2 は、ヘッダーフィールドの圧縮を導入し、同一接続上での複数同時通信の実現により、ネットワークリソースのより効率的な利用とレイテンシの削減を可能にします。また、サーバーからクライアントへ一方的に送るプッシュ表現についても説明します。

この仕様は HTTP/1.1 のメッセージ構文を変更しますが、これを廃止するわけではありません。HTTP の既存のセマンティクスは変更しません。

このメモの状態

これは Internet Standards Track 文書です。

この文書は Internet Engineering Task Force (IETF) の成果物です。これは、IETF コミュニティの合意を表現するものであり、公開の査読を受け、Internet Engineering Steering Group (IESG) により発行が承認されました。Internet Standards に関するさらなる情報は RFC 5741 の2章に記述されています。

この文書の現在の状態やエラッタ、フィードバックの提供方法についての情報は http://www.rfc-editor.org/info/rfc7540 で参照できます。

Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

目次

1. はじめに

Hypertext Transfer Protocol (HTTP) は広く成功したプロトコルです。しかしながら、HTTP/1.1 による下層のトランスポートの使い方 ([RFC7230]、6章) には、今日のアプリケーションのパフォーマンスに悪い影響を与える特性がいくつかあります。

特に、HTTP/1.0 は与えられた TCP 接続に対して、同時に1つのリクエストしか転送できません。HTTP/1.1 ではリクエストパイプラインが追加されましたが、それはリクエストの並列化に部分的に取り組んだだけで、今でも行頭ブロッキングに悩まされています。そのため、多数のリクエストを生成する必要がある HTTP/1.0 や HTTP/1.1 のクライアントは、並行性やレイテンシを減らすためにサーバーに対して複数の接続を使用します。

さらに、HTTP のヘッダーフィールドはしばしば重複し、冗長です。これは、巨大なネットワークパケットを多数生成し、不要なネットワークトラフィックを発生させるだけでなく、TCP [TCP] 輻輳の小さな初期ウインドウはすぐいっぱいになってしまいます。そして結果的に、1つの新しい TCP 接続上で複数のリクエストを発行すると、過度の待ち時間が発生することになります。

HTTP/2 では、基礎となる接続に対して HTTP セマンティクスの最適化マッピングを定義することによって、これらの問題に取り組みます。具体的には、同一接続上においてリクエストとレスポンスメッセージを交互に挟み込んだり、HTTP ヘッダーフィールドに対して効率のよい符号化方式を利用したりします。またリクエストの優先付けも可能にし、より重要なリクエストをより迅速に完了させることで更なる性能向上を実現します。

もたらされたプロトコルは、HTTP/1.x と比較して少ない TCP 接続を利用することになるため、よりネットワークフレンドリーになります。これは他のフローとの競合を減らし、接続寿命が長くなることを意味します。そして結果的に、利用可能なネットワークキャパシティの有効利用につながることになります。

最後に、HTTP/2 では、バイナリメッセージ構造を使用することで、メッセージ処理をより効率的にすることも可能にします。

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

HTTP/2 は HTTP セマンティクスの最適化された転送手段を提供します。HTTP/2 は HTTP/1.1 の主要な機能の全てに対応しますが、いくつかの方法を用いてより効率的なものを目指します。

HTTP/2 におけるプロトコルの基本的な単位はフレーム (4.1節) です。各フレームタイプは異なる目的を果たします。例えば、HEADERS と DATA フレームは HTTP リクエストとレスポンス (8.1節) の基礎を構成します。SETTINGS、WINDOW_UPDATE、PUSH_PROMISE といったその他のフレームタイプは他の HTTP/2 の機能に対応するために使われます。

リクエストの多重化は、各 HTTP リクエスト/レスポンスを単一のストリーム (5章) に割り当てることで実現します。ストリームは他のストリームとは独立しているため、リクエストのブロックや停止が、他のリクエストの進捗を妨げることはありません。

フロー制御や優先度付けは、多重化されたストリームを適切に使用できることを保証します。フロー制御 (5.2節) は、受信者が使用可能なデータのみが送信されることを保証するのに役立ちます。また、優先度付け (5.3節) は限られたリソースが最初の最も重要なリクエストに割り当てられることを保証します。

HTTP/2 では、サーバーがクライアントにレスポンスをプッシュできる、新しい対話モードを追加されます (8.2節)。サーバープッシュは、潜在的なレイテンシの増加に対してある程度のネットワーク使用率と引き換えに、サーバーがクライアントが必要とするデータを予測し、クライアントデータの送信を可能にします。サーバーは、PUSH_PROMISE フレームとしてリクエストを合成して送信し、プッシュをおこないます。その後、サーバーは合成したリクエストのレスポンスを別のストリーム上で送信できます。

コネクションで使用される HTTP ヘッダーフィールドには、多くの冗長なデータが存在する可能性があるため、それらを含むフレームは圧縮されます (4.3節)。これは、多くのリクエストを1つのパケットに圧縮できるため、一般的なリクエストのサイズにおいて特に有益な効果があります。

2.1. この文書の構成

HTTP/2 の仕様は4つのパートで構成されます:

フレームレイヤーやストリームレイヤーの概念の一部は HTTP から分離されていますが、この仕様では完全に汎用的なフレームレイヤーを定義するわけではありません。フレームレイヤーとストリームレイヤーは HTTP プロトコルとサーバープッシュの要件にあわせて作られました。

2.2. 表記と用語

この文書のキーワード "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"MAY"、そして "OPTIONAL" は RFC 2119 [RFC2119] で記述されたとおりに解釈されるべきです。

すべての数値はネットワークバイトオーダーです。特に断りがない限り、値は符号なしとなります。リテラルの値は、必要に応じて10進数または16進数で提供されます。また、16進数リテラルは10進数リテラルと区別するために "0x" ではじまります。

使用される用語は以下のとおりです:

クライアント
HTTP/2 接続を開始するエンドポイント。クライアントは HTTP リクエストを送信し、HTTP レスポンスを受信します。
コネクション
2つのエンドポイント間のトランスポート層での接続。
コネクションエラー
HTTP/2 接続全体に影響するエラー。
エンドポイント
コネクションにおけるクライアントまたはサーバー。
フレーム
ヘッダー、フレームタイプに従って構成される可変長のオクテット列からなる HTTP/2 接続内部での最小の通信単位。
ピア
エンドポイントの1つ。特定のエンドポイントを議論するときに、"ピア" は議論の対象となる主なリモートエンドポイントを示します。
受信者
フレームを受信するエンドポイント。
送信者
フレームを送信するエンドポイント。
サーバー
HTTP/2 接続を受け付けるエンドポイント。サーバーは HTTP リクエストを受信し、HTTP レスポンスを送信します。
ストリーム
HTTP/2 接続内部の仮想チャンネルを通る双方向のフレームの流れ。
ストリームエラー
個々の HTTP/2 ストリームにおけるエラー。

最後に、"ゲートウェイ"、"中継者"、"プロキシ" そして "トンネル" は [RFC7230] の2.3節で定義されています。中継者は状況によりクライアントとサーバーのどちらとしても振舞います。

"ペイロードボディ" は [RFC7230] の3.3節で定義されています。

3. HTTP/2 の開始

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

HTTP/2 は、 HTTP/1.1 で使用されるのと同じ "http" と "https" の URI スキームを使用します。また、HTTP/2 は標準のポート番号も共有します: "http" 用の80番と、"https" 用の443番です。この結果、"http://example.org/foo" や "https://example.com/bar" といった対象リソース URI へのリクエストを処理する実装は、最初にアップストリームサーバー (クライアントがコネクションを確立しようとしているピア) が HTTP/2 に対応するかどうかを認識する必要があります。

これは HTTP/2 への対応を決定する手段が "http" と "https" の URI で異なることを意味します。"http" URI のための認識は3.2節で説明します。また、"https" URI のための認識は3.3節で説明します。

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

この文書で定義されるプロトコルの識別子は2つあります。

"h2" や "h2c" で通信するということは、この文書で説明される伝送方式、セキュリティ、フレーミング、メッセージセマンティクスを使用することを意味します。

3.2. "http" URI での HTTP/2 の開始

次のホップの HTTP/2 への対応に関する事前知識なしに "http:" URI にリクエストをするクライアントは、HTTP アップグレードメカニズムを使用します ([RFC7230]、6.7節)。クライアントは "h2c" トークンを用いて HTTP/2 を指定した Upgrade ヘッダーフィールドを含む HTTP/1.1 リクエストを送信することで、これを実行します。この HTTP/1.1 リクエストには1つの HTTP2-Settings (3.2.1節) ヘッダーフィールドも含まなければなりません (MUST)。

例:

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <HTTP/2 SETTINGS ペイロードの base64url エンコード>

ペイロードボディを含むリクエストは、クライアントが HTTP/2 フレームを送信する前に、完全に送信されなければなりません (MUST)。これは、巨大なリクエストが完全に送信されるまで、そのコネクションの使用を妨げることを意味します。

最初のリクエストとその後に続くリクエストの並行性が重要な場合は、追加のラウンドトリップコストを負担して、HTTP/2 へのアップグレードを行う OPTIONS リクエストが使用できます。

HTTP/2 に対応しないサーバーは、リクエストに対して Upgrade ヘッダーフィールドが存在しなかったかのように応答できます。

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html
...

サーバーは、Upgrade ヘッダーフィールドの "h2" は無視しなければなりません (MUST)。"h2" トークンの存在は TLS 上の HTTP/2 を意味し、3.3節で説明するようにネゴシエートされます。

HTTP/2 に対応するサーバーは 101 (Switching Protocols) レスポンスと共にアップグレードを受け入れます。101 レスポンスの終わりを示す空行の後、サーバーは HTTP/2 フレームの送信を開始できます。これらのフレームは Upgrade を開始したリクエストへのレスポンスを含まなければなりません (MUST)。

例:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 コネクション ...

サーバーにより送信される最初の HTTP/2 フレームは、SETTINGS フレーム (6.5節) で構成されるサーバーコネクションプリフェイス (3.5節) でなければなりません (MUST)。101 レスポンスを受信すると、クライアントは SETTINGS フレームを含むコネクションプリフェイス (3.5節) を送信しなければなりません (MUST)。

アップグレードの前に送信された HTTP/1.1 リクエストには、デフォルト優先度の値 (5.3.5節) と共にストリームID 1 (5.1.1節) が割り当てられます。リクエストが HTTP/1.1 リクエストとして完了しているため、ストリーム 1 はクライアントからサーバーに対して暗黙的に "half-closed" 状態になります (5.1節)。HTTP/2 接続を開始した後、ストリーム 1 はレスポンスのために使用されます。

3.2.1. HTTP2-Settings ヘッダーフィールド

HTTP/1.1 から HTTP/2 にアップグレードするリクエストは、単一の "HTTP2-Settings" ヘッダーフィールドを送信しなければなりません (MUST)。HTTP2-Settings ヘッダーフィールドは、HTTP/2 接続を制御するパラメーターを含む接続固有ヘッダーフィールドです。このフィールドは、サーバーがアップグレードリクエストを受け付けることを見越して送信されます。

HTTP2-Settings = token68

このヘッダーフィールドが存在しなかったり、2つ以上存在するような場合、サーバーは接続を HTTP/ 2 にアップグレードしてはいけません (MUST NOT)。また、サーバーはこのヘッダーフィールドを送信してはいけません (MUST NOT)。

HTTP2-Settings ヘッダーフィールドの内容は、SETTINGS フレーム (6.5節) のペイロードであり、base64url (これは、最後の '=' を省略した [RFC4648] の5章で説明されている URL セーフかつファイル名セーフの Base64 エンコードです) 文字列としてエンコードされます。"token68" の ABNF [RFC5234] プロダクションは、[RFC7235] の2.1節に定義されています。

アップグレードは直接接続に対して適用することのみを意図しているため、HTTP2-Settings ヘッダーフィールド を送信するクライアントは、転送を防ぐために Connection ヘッダーフィールドの接続オプションとして "HTTP2-Settings" を送信しなければなりません (MUST) ([RFC7230]、6.1節)。

サーバーは他の SETTINGS フレームと同じように、これらの値をデコードし、解釈します。101 レスポンスは、暗黙的な応答としての役割を果たすため、明示的な SETTINGS パラメーターの応答 (6.5.3節) は不要です。このような値をアップグレードリクエストで提供することで、クライアントがサーバーからフレームを受信するよりも前に、パラメーターを送信できる機会を持てるようになります。

3.3. "https" URI での HTTP/2 の開始

>"https" URI へのリクエストをするクライアントは、TLS [TLS12] と application-layer protocol negotiation (ALPN) extension [TLS-ALPN] を利用します。

TLS 上の HTTP/2 は "h2" プロトコル識別子を使用します。"h2c" プロトコル識別子はクライアントから送信されたり、サーバーにより選択されてはいけません (MUST NOT)。"h2c" プロトコル識別子は TLS を使用しないプロトコルを示します。

TLS ネゴシエーションが完了すると、クライアントとサーバーはコネクションプリフェイス (3.5節) を送信しなければなりません (MUST)。

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

クライアントは、他の方法で特定のサーバーが HTTP/2 に対応していることを知ることができます。例えば、[ALT-SVC] では対応状況を通知するメカニズムを説明しています。

そのようなサーバーに対し、クライアントはコネクションプリフェイス (3.5節) を送信しなければなりません (MUST)。また、続いて直ちに HTTP/2 フレームを送信してもよいものとします (MAY)。サーバーはコネクションプリフェイスの存在により、このような接続を識別できます。これは平文 TCP 上の HTTP/2 接続の確立にのみ影響し、TLS 上の HTTP/2 に対応する実装は、TLS のプロトコルネゴシエーション [[TLS-ALPN]] を使用しなければなりません (MUST)。

同様に、サーバーもコネクションプリフェイス (3.5節) を送信しなければなりません (MUST)。

追加情報がない、事前知識による HTTP/2 接続は、今後のコネクションに対しても指定されたサーバーが HTTP/2 に対応するという強いシグナルではありません。例えば、サーバーの設定の変更や、クラスター化されたサーバーインスタンス間で異なる設定をする、ネットワーク状況を変更するといったことは可能です。

3.5. 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)。101 (Switching Protocols) レスポンス (アップグレードの完了を示します) を受信した直後、もしくは TLS 接続の最初のアプリケーションデータのオクテットとして、クライアントはただちにクライアントコネクションプリフェイスを送信します。サーバーが対応するプロトコルを事前に知っていることによって HTTP/2 接続を開始する場合は、クライアントはコネクションを確立した直後にコネクションプリフェイスを送信します。

注: 多数の HTTP/1.1 や HTTP/1.0 のサーバー、中継システムがさらにフレームを処理しないよう、このクライアントコネクションプリフェイスが選ばれました。これは、[TALKING] で提起された懸念には対応しないことに注意してください。

サーバーコネクションプリフェイスは空の可能性がある SETTINGS フレーム (6.5節) だけで構成され、HTTP/2 接続においてサーバーが送信する最初のフレームでなければなりません (MUST)。

ピアからコネクションプリフェイスの一部として受信した SETTINGS フレームは、コネクションプリフェイスの送信後にその適用を通知 (6.5.3節) しなけければなりません (MUST)。

不要なレイテンシを防ぐために、クライアントはクライアントコネクションプリフェイスの送信後、サーバーコネクションプリフェイスの受信を待たずに、すぐに追加のフレームをサーバーに送信することが認められています。しかしながら、サーバーコネクションプリフェイスの SETTINGS フレームが、クライアントがサーバーとどのように通信するかを変更するパラメーターを含む可能性があることに注意しないといけません。クライアントは、SETTINGS フレームを受信後に直ちにすべてのパラメーターに従うことが求められます。一部の構成においては、サーバーはこの問題を回避する機会を提供するため、クライアントが追加のフレームを送信するよりも前に SETTINGS を送信することが可能です。

クライアントとサーバーは、不正なコネクションプリフェイスを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。ピアが HTTP/2 を使用していないことを不正なプリフェイスが示している場合は GOAWAY フレーム (6.8節) を省略してもよいものとします (MAY)。

4. HTTP フレーム

HTTP/2 接続が確立されると、クライアントとサーバーはフレームの送信を開始できます。

4.1. フレームフォーマット

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

+-----------------------------------------------+
|                 Length (24)                   |
+---------------+---------------+---------------+
|   Type (8)    |   Flags (8)   |
+-+-+-----------+---------------+-------------------------------+
|R|                 Stream Identifier (31)                      |
+=+=============================================================+
|                   Frame Payload (0...)                      ...
+---------------------------------------------------------------+

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

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

Length
符号なし24ビット整数で表現されるフレームペイロードの長さです。2^14 (16,384) よりも大きい値は、受信者が SETTINGS_MAX_FRAME_SIZE により大きな値を設定することなく、送信されてはいけません (MUST NOT)。
フレームヘッダーの9オクテットはこの値には含まれません。
Type
8ビットのフレームタイプです。フレームタイプはフレームのフォーマットとセマンティクスを決定します。実装は不明なタイプを持つフレームを無視して破棄しなければなりません (MUST)。
Flags
フレームタイプ固有の真偽値フラグのために予約された8ビットのフィールドです。
フラグは、指定されたフレームタイプに固有のセマンティクスが割り当てられます。特定のフレームタイプにセマンティクスが定義されていないフラグは無視されなければならず (MUST)、送信時には未設定 (0x0) のままにしなければなりません (MUST)。
R
予約済みの1ビットのフィールドです。このビットのセマンティクスは定義されていません。送信する時は未設定 (0x0) のままにしなければならず (MUST)、受信時には無視されなければなりません (MUST)。
Stream Identifier
ストリームID (5.1.1節) は31ビットの符号なし整数で表現されます。0x0の値は、個々のストリームではなく、コネクションそのものに関連するフレームのために予約されます。

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

4.2. フレームサイズ

フレームペイロードのサイズは、SETTINGS_MAX_FRAME_SIZE 設定で受信者が通知した最大サイズにより制限されます。この設定は 2^14 (16,384) から 2^24-1 (16,777,215) までのオクテットの値を持つことができます。

全ての実装は、2^14オクテットまでの長さのフレームと9オクテットのフレームヘッダー (4.1節) を受信し、最低限処理できなければなりません (MUST)。フレームサイズを記述する場合は、フレームヘッダーのサイズは含まれません。

注: PING (6.7節) のような特定のフレームタイプでは、ペイロードデータの量について追加の制限があります。

フレームが、SETTINGS_MAX_FRAME_SIZE で定義されたサイズやフレームタイプで定義された制限を超えていたり、必須となるフレームデータを含むには小さすぎるような場合、エンドポイントは FRAME_SIZE_ERROR のエラーコードを送信しなければなりません (MUST)。接続の状態を変更可能なフレームにおけるフレームサイズエラーは、コネクションエラー (5.4.1節) として扱われなければなりません (MUST)。これらの対象には、ヘッダーブロック (4.3節) を転送するフレーム (つまり HEADERS や PUSH_PROMISE、CONTINUATION) や SETTINGS、ストリームID が 0 の全てのフレームが含まれます。

エンドポイントには、フレームの全ての利用可能な領域を使用する義務はありません。許可された最大サイズよりも小さいフレームを使用することで、応答性を改善できます。巨大なフレームの送信は (RST_STREAM、WINDOW_UPDATE、PRIORITY といった) 時間に敏感なフレームの送信遅延を引き起こし、巨大なフレームの送信によりそれらのフレームがブロックされた場合、パフォーマンスに影響を与えます。

4.3. ヘッダーの圧縮と伸張

HTTP/1 と変わらず、HTTP/2 におけるヘッダーフィールドは1つ以上の値が設定された名前です。ヘッダーフィールドは、HTTP リクエストとレスポンスのメッセージおよび、サーバープッシュ処理に使用されます (8.2節)。

ヘッダーリストは、0個以上のヘッダーフィールドからなる集合です。コネクションを通じて転送されるとき、ヘッダーリストは HTTP ヘッダー圧縮 [COMPRESSION] を使用してヘッダーブロックにシリアライズされます。シリアライズされたヘッダーブロックは、ヘッダーブロックフラグメントと呼ばれる1つ以上のオクテット列に分割され、HEADERS (6.2節)、 PUSH_PROMISE (6.6節)、または CONTINUATION (6.10節) フレームのペイロードとして転送されます。

Cookie ヘッダーフィールド [COOKIE] は HTTP マッピングにより特別に処理されます (8.1.2.5節)。

受信側エンドポイントはフラグメントを結合することでヘッダーブロックを再構築し、ヘッダーリストを復元するために伸張します。

完全なヘッダーブロックは以下のどちらかで構成されます:

ヘッダー圧縮は状態を持ちます。1つの圧縮コンテキストと1つの伸長コンテキストがコネクション全体で使用されます。ヘッダーブロックのデコードエラーは COMPRESSION_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

各ヘッダーブロックは別々の単位として処理されます。ヘッダーブロックは、他の種類のフレームや他のストリームのフレームの間に挟み込まれずに、連続した一連のフレームとして送信されなければなりません (MUST)。一連の HEADERS や CONTINUATION フレームの最後のフレームには、END_HEADERS フラグが設定されます。また、一連の PUSH_PROMISE や CONTINUATION フレームの最後のフレームにも、END_HEADERS フラグが設定されます。これにより、ヘッダーブロックを論理的に単一のフレームと同等にできます。

ヘッダーブロックフラグメントは HEADERS、PUSH_PROMISE、CONTINUATION フレームのペイロードでのみ送信できます。これらのフレームは、受信者が保持する圧縮コンテキストを変更するデータを転送するためです。HEADERS、PUSH_PROMISE、CONTINUATION フレームを受信したエンドポイントは、フレームの破棄が発生したような場合であっても、ヘッダーブロックを再構築し、伸張する必要があります。ヘッダーブロックを伸張できない場合、受信者は COMPRESSION_ERROR コネクションエラー (5.4.1節) と共にコネクションを終了しなければなりません (MUST)。

5. ストリームと多重化

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

5.1. ストリームの状態

ストリームのライフサイクルは、図1に示したようになります。

                        +--------+
                send PP |        | recv PP
               ,--------|  idle  |--------.
              /         |        |         \
             v          +--------+          v
      +----------+          |           +----------+
      |          |          | send H/   |          |
,-----| reserved |          | recv H    | reserved |-----.
|     | (local)  |          |           | (remote) |     |
|     +----------+          v           +----------+     |
|         |             +--------+             |         |
|         |     recv ES |        | send ES     |         |
|  send H |     ,-------|  open  |-------.     | recv H  |
|         |    /        |        |        \    |         |
|         v   v         +--------+         v   v         |
|     +----------+          |           +----------+     |
|     |   half   |          |           |   half   |     |
|     |  closed  |          | send R/   |  closed  |     |
|     | (remote) |          | recv R    | (local)  |     |
|     +----------+          |           +----------+     |
|          |                |                 |          |
|          | send ES/       |        recv ES/ |          |
|          | send R/        v         send R/ |          |
|          | recv R     +--------+    recv R  |          |
| send R/  `----------->|        |<-----------'  send R/ |
| recv R                | closed |               recv R  |
`---------------------->|        |<----------------------'
                        +--------+

  send: エンドポイントがこのフレームを送信
  recv: エンドポイントがこのフレームを受信

  H:  HEADERS フレーム (CONTINUATION が続く可能性がある)
  PP: PUSH_PROMISE フレーム (CONTINUATION が続く可能性がある)
  ES: END_STREAM フラグ
  R:  RST_STREAM フレーム

                 図2: ストリームの状態

このダイアグラムはストリームの状態遷移と、これらの遷移に影響するフレームとフラグのみを表していることに注意してください。なお、CONTINUATION フレームについては状態遷移をもたらさず、実質的に HEADERS や PUSH_PROMISE の一部になります。この状態遷移の目的のために、END_STREAM フラグはそれが設定されたフレームに対して別々のイベントとして処理され、END_STREAM フラグが設定された HEADERS フレームは2つの状態遷移を引き起こす可能性があります。

両方のエンドポイントは、それぞれの立場に応じたストリーム状態図を持ち、フレーム転送中では両者は異なるでしょう。エンドポイントはストリームの作成について互いに連携しません。ストリームはどちらかのエンドポイントにより一方的に作成されます。状態の不一致に伴う悪い影響は、RST_STREAM を送信した後の "closed" 状態に限定されます。その場合クローズ後にしばらくフレームを受信するかもしれません。

ストリームは次のような状態を持ちます:

idle

全てのストリームは "idle" 状態からはじまります。

この状態では、次のような遷移が有効です:

  • HEADER フレームの送信や受信は、ストリームを "open" 状態にします。5.1.1節で説明されるようにストリームIDが選択されます。 同一の HEADERS フレームはストリームをすぐに "half-closed" にする可能性があります。
  • 異なるストリームにおける PUSH_PROMISE フレームの送信は、今後使用する idle ストリームを予約します。予約済みストリームの状態は "reserved (local)" に遷移します。
  • 異なるストリームにおける PUSH_PROMISE フレームの受信は、今後使用する idle ストリームを予約します。予約済みストリームの状態は "reserved (remote)" に遷移します。
  • PUSH_PROMISE フレームは idle ストリームには送信されませんが、Promised Stream ID フィールドの新しい予約ストリームとして参照されることに注意してください。

この状態のストリームでの HEADERS や PRIORITY 以外のフレームの受信は、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

reserved (local)

"reserved (local)" 状態のストリームは、PUSH_PROMISE を送信して予約した状態です。PUSH_PROMISE フレームは、idle ストリームとリモートピアから始めた open ストリームを関連付けることによって、その idle ストリームを予約します (8.2節)。

この状態では、次のような遷移のみ可能です:

  • エンドポイントは HEADERS フレームを送信できます。これは、ストリームを "half-closed (remote)" 状態でオープンします。
  • いずれかのエンドポイントは、ストリームを "closed" にするために RST_STREAM を送信できます。これはストリームの予約を解除します。

この状態において、エンドポイントは HEADERS や RST_STREAM、PRIORITY 以外のいかなる種類のフレームも送信してはいけません。(MUST NOT)。

PRIORITY または WINDOW_UPDATE フレームはこの状態で受信してもよいものとします (MAY)。この状態のストリームでの RST_STREAM や PRIORITY、WINDOW_UPDATE フレーム以外の受信については、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

reserved (remote)

"reserved (remote)" 状態のストリームは、リモートピアにより予約されています。

この状態では、次のような遷移のみ可能です:

  • HEADERS フレームを受信すると、ストリームは "half-closed (local)" に遷移します。
  • いずれかのエンドポイントは、ストリームを "closed" にするために RST_STREAM を送信できます。これはストリームの予約を解除します。

エンドポイントは、予約済みストリームの優先度を変更するために、この状態で PRIORITY フレームを送信してもよいものとします (MAY)。また、エンドポイントはこの状態において、RST_STREAM や WINDOW_UPDATE、PRIORITY フレーム以外の種類のフレームを送信してはいけません (MUST NOT)。

この状態のストリームでの HEADERS や RST_STREAM、PRIORITY フレーム以外の受信については、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

open

"open" 状態のストリームは、両方のピアがいかなる種類のフレームを送信するために使用できます。この状態では、送信側のピアはストリームレベルのフロー制御 (5.2節) に従います。

この状態から、どちらのエンドポイントも END_STREAM フラグを設定したフレームを送信できます。それによって、ストリームは "half-closed" 状態に遷移します。すなわちエンドポイントが END_STREAM フラグを送信すると、ストリームの状態は "half-closed (local)" となり、エンドポイントが END_STREAM フラグを受信した場合は、ストリームの状態が "half-closed (remote)" になります。

この状態では、どちらのエンドポイントも直ちに "closed" に遷移させる RST_STREAM フレームを送信できます。

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 以外の追加のフレームを受信した場合は、STREAM_CLOSED のストリームエラー (5.4.2節) を返さなければなりません (MUST)。

"half-closed (remote)" のストリームは、エンドポイントが任意の種類のフレームの送信に使用できます。この状態では、エンドポイントは通知されたストリームレベルのフロー制御の制限 (5.2節) を守り続けます。

ストリームは、END_STREAM フラグを含むフレームを送信するか、いずれかのピアが RST_STREAM フレームを送信することで、この状態から "closed" 状態に遷移できます。

closed

"closed" 状態は最終的な状態です。

エンドポイントは closed ストリームに PRIORITY 以外のフレームを送信してはいけません (MUST NOT)。RST_STREAM フレームを受信した後に、PRIORITY 以外のフレームを受信したエンドポイントは、STREAM_CLOSED のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。同様に、END_STREAM フラグが設定されたフレームを受信した後に、さらにフレームを受信したエンドポイントは、以下の説明にあるような許可されたフレームでない限り、STREAM_CLOSED のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

END_STREAM フラグが含まれる DATA フレームや HEADERS フレームが送信された後の少しの間、WINDOW_UPDATE や RST_STREAM フレームをこの状態で受信できます。リモートピアが、RST_STREAM または END_STREAM フラグが設定されたフレームを受信し、処理するまでは、リモートピアがこれらのタイプのフレームを送信するかもしれません。エンドポイントは、この状態で受信した WINDOW_UPDATE や RST_STREAM フレームを無視しなければなりません (MUST)。しかしながら、エンドポイントは END_STREAM を送信した後かなり時間が経ってから到着したフレームを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱うことを選択してもよいものとします (MAY)。

PRIORITY フレームは、依存するストリームの優先度付けのために closed ストリームに送信できます。エンドポイントは PRIORITY フレームを処理すべきです (SHOULD)。ただし、そのストリームが依存関係ツリー (5.3.4節) から削除された場合は無視できます。

もし RST_STREAM フレームを送信した結果としてこの状態に至った場合、RST_STREAM を受信したピアは、このストリームに対してフレームを既に送信していたり送信キューに入れていたりして、取りやめることができないかもしれません。エンドポイントは、RST_STREAM フレームを送信した後、closed ストリームで受信したフレームを無視しなければなりません (MUST)。エンドポイントは、この時点以降に到着したフレームを無視するか、エラーとして扱うかの期限を制限するかを選択してもよいものとします (MAY)。

RST_STREAM の送信後に受信したフロー制御下のフレーム (例: DATA) は、コネクションフロー制御のウインドウとして計算されます。これらのフレームは無視されるかもしれませんが、送信者が RST_STREAM を受信する前にフレームが送信されているため、送信者はコネクションフロー制御ウインドウを計算するようにこれらのフレームを考慮します。

エンドポイントは、RST_STREAM を送信した後に PUSH_PROMISE や CONTINUATION を受信するかもしれません。PUSH_PROMISE は関連付けられたストリームが終了されているかにかかわらず、ストリームを "reserved" に遷移させます。したがって、不要な予約済みストリームを終了するには RST_STREAM が必要になります。

この文書の他の場所でより具体的な指針が明記されていない場合、実装は、状態の説明において明示的に許可されていないフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱うべきです (SHOULD)。なお、PRIORITY は全てのストリームの状態において送信や受信がされる可能性があることに注意してください。不明な種類のフレームは無視されます。

HTTP リクエスト/レスポンスの交換における状態遷移の例は、8.1節で確認できます。サーバープッシュの状態遷移の例は、8.2.1節8.2.2節で確認できます。

5.1.1. ストリームID

ストリームは、符合なし31ビットの整数で識別されます。クライアントが開始したストリームは奇数のストリームIDを使わなければなりません (MUST)。また、サーバーが開始したストリームは偶数のストリームIDを使わなければなりません (MUST)。ストリームID 0 (0x0) は、コネクション制御メッセージに使用されます。ストリームID 0 は新しいストリームの確立には使用できません。

HTTP/2 にアップグレードする HTTP/1.1 リクエスト (3.2節) には、ストリームID 1 (0x1) で応答されます。アップグレードの完了後、ストリーム 0x1 はクライアントに対して "half-closed (local)" になります。したがって、HTTP/1.1 からアップグレードするクライアントが、ストリーム 0x1 を新しいストリームIDとして選択することはできません。

新しく確立されるストリームIDは、エンドポイントがすでに開始または予約した全てのストリームよりも大きい数値でなければなりません (MUST)。この影響を受けるのは、HEADERS フレームを使用して開始されたストリームと、PUSH_PROMISE を使用して予約されたストリームです。予期せぬストリームIDを受信したエンドポイントは、PROTOCOL_ERROR タイプのコネクションエラー (5.4.1節) を返さなければなりません (MUST)。

新しいストリームIDを利用すると、それより小さいストリームIDで "idle" 状態のストリームを全て暗黙的に終了します。例えば、クライアントがストリームID 5 のフレームを送信することなくストリームID 7 の HEADERS フレームを送信した場合、ストリームID 7 のフレームを最初に送受信した時点で、ID 5 のストリームは "closed" 状態に遷移します。

ストリームIDは再利用できません。長時間のコネクションでは、エンドポイントがストリームIDの利用可能な範囲を越えてしまう可能性があります。新しいストリームIDを生成できないクライアントは、新しいストリームのために新たなコネクションを確立できます。新しいストリームIDを確立できないサーバーは、新しいストリームのために新しいコネクションを開始することをクライアントに強制するために、GOAWAY フレームを送信できます。

5.1.2. ストリームの並行処理

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

エンドポイントが開始可能なストリームの最大数は、"open" または2つの "half-closed" 状態のストリームの数で計算されます。これら3つの状態にあるストリームは SETTINGS_MAX_CONCURRENT_STREAMS 設定で指定された制限に数えられます。2つの "reserved" 状態にあるストリームは、このストリーム制限には数えられません。

エンドポイントはお互いのピアが設定した制限を超えてはいけません (MUST NOT)。告知した同時ストリーム制限を超えるような HEADERS フレームを受信したエンドポイントは、それを PROTOCOL_ERROR または REFUSED_STREAM のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。エラーコードの選択は、エンドポイントが自動再試行を有効にするかどうかに影響します。この詳細は8.1.4節を参照してください。

SETTINGS_MAX_CONCURRENT_STREAMS を現在の同時ストリーム数よりも少ない値に設定したいエンドポイントは、新しい値を超えるストリームを終了するか、完了させることができます。

5.2. フロー制御

ストリームの多重化を使用すると、TCP 接続を使用する上で競合が発生し、その結果ストリームのブロックが起こります。フロー制御の仕組みは、同一コネクション上でストリームが互いに破壊的な干渉をしないことを保証します。フロー制御は、個々のストリームとコネクション全体のどちらにも使用されます。

HTTP/2 では、WINDOW_UPDATE フレーム (6.9節) の使用を通じて、フロー制御を提供します。

5.2.1. フロー制御の原則

HTTP/2 のストリームフロー制御は、プロトコルの変更の必要なしに、様々なフロー制御アルゴリズムを適用することを目標にしています。HTTP/2 におけるフロー制御は以下のような特徴があります:

  1. フロー制御は接続固有のものです。2つのフロー制御は単一ホップのエンドポイントの間でおこなわれ、エンド間の全てのパスでおこなわれるものではありません。
  2. フロー制御は WINDOW_UPDATE フレームに基づきます。受信者は、どれぐらいのオクテットをストリームとコネクション全体から受信する準備ができているかを告知します。これは信頼に基づいた仕組みです。
  3. フロー制御は方向性を持ち、受信者によって全体的な制御がおこなわれます。受信者は、それぞれのストリームとコネクション全体に対して好ましいウインドウサイズを選択し、設定してもよいものとします (MAY)。送信者は、受信者が設定したフロー制御を尊重しなければなりません (MUST)。クライアント、サーバーそして中継者は、すべて独立して、受信者としてフロー制御ウインドウを告知し、送信する際はピアによって設定されたフロー制御制限に従います。
  4. 新しいストリームとコネクション全体のフロー制御ウインドウの初期値は、どちらも65,535オクテットです。
  5. フロー制御をフレームに適応するかどうかはフレームタイプによって決定されます。この文書で述べられるフレームのうち、DATA フレームのみがフロー制御の対象となります。他の全てのフレームタイプは、通知されたフロー制御ウインドウの容量を消費しません。これは、重要なコントロールフレームがフロー制御によりブロックされないことを保証します。
  6. フロー制御を無効化することはできません。
  7. HTTP/2 は WINDOW_UPDATE フレーム (6.9節) のフォーマットとセマンティクスのみを定義します。この文書は、受信者がこのフレームを送信するタイミングや送信する値を決定する方法については規定しません。また、送信者がパケットの送信を選択する方法についても規定しません。実装は、自身のニーズにあった任意のアルゴリズムを選択できます。

実装には、優先度に基づいてリクエストやレスポンスを送信する方法の管理や、リクエストの行頭ブロッキングを防ぐ方法の選択、新しいストリームの作成の管理などをする責任があります。これらのアルゴリズムの選択肢は、フロー制御アルゴリズムと相互に影響します。

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

フロー制御は、リソース制限下で動作しているエンドポイントを保護するために定義されています。例えばプロキシは、多くのコネクションの間でメモリーを共有する必要があり、そこには低速なアップストリームや高速なダウンストリームを含む可能性があるでしょう。フロー制御は、受信者があるストリームのデータの処理ができない状況であっても、同一コネクション上の他のストリームの処理を継続したい場合に対応します。

この機能を必要としない構成では、最大サイズ (2^31-1) のフロー制御ウインドウを通知し、データの受信時に WINDOW_UPDATE フレームを送信することで、このウインドウを維持できます。これは受信者におけるフロー制御を実質的に無効化します。反対に、送信者は常に受信者により通知されたフロー制御ウインドウの影響を受けます。

リソース (例えばメモリーなど) が制限された構成では、ピアが使用するメモリーの量を制限するために、フロー制御を使用できます。しかしながら、帯域幅遅延積 ([RFC7323]) についての知識なしにフロー制御を有効化した場合、利用可能なネットワークリソースを適切に利用できない可能性があることに注意してください。

最新の帯域幅遅延積についての十分な知識があるとしても、フロー制御の実装は困難である可能性があります。フロー制御を使用する時、受信者は TCP の受信バッファを直ちに読み込まなければなりません (MUST)。読み込みに失敗すると、WINDOW_UPDATE などの重要なフレームの読み込みと処理ができず、デッドロックを引き起こす可能性があります。

5.3. ストリームの優先度

クライアントは、ストリームを開始する HEADERS フレーム (6.2節) に優先度情報を含めることで、新しいストリームの優先度を指定できます。PRIORITY フレーム (6.3節) を使用すれば、いつでもストリームの優先度を変更できます。

優先度の目的は、エンドポイントが同時ストリームを管理する際に、そのピアに対してリソースの割り当て方法を明示できるようにすることです。最も重要なのは、送信キャパシティが限られている時に、フレームを転送するストリームを選択するために優先度が使用できることです。

ストリームは、他のストリームの完了 (5.3.1節) に依存する関係を作ることで、優先度を設定できます。各依存関係には、相対的な重みが割り当てられ、その値は、同じストリームに依存するストリームに割り当てられた利用可能なリソースの、相対的な比率を決定するために使用されます。

ストリームの優先度を明示的に設定することは、優先度付け処理への入力になります。これは他のストリームに相対するストリームに対して、特別な処理や転送順序を保証するものではありません。エンドポイントは優先度を使用して、ピアに特定の順序による同時ストリームの処理を強制できません。優先度を明示することは、あくまで提案でしかありません。

優先度情報はメッセージから省略できます。明示的な値が提供されるまではデフォルトの値が使用されます (5.3.5節)。

5.3.1. ストリームの依存関係

各ストリームは他のストリームに明示的な依存関係を与えることができます。依存関係を含めることで、依存ストリームよりも指定されたストリームへのリソースの割り当てが優先されることを表現します。

他のストリームに依存しないストリームには 0x0 のストリーム依存関係が与えられます。言い換えれば、存在しないストリーム 0 はツリーのルートを構成します。

他のストリームの依存するストリームは依存ストリームです。ストリームが依存する先のストリームは、親ストリームとなります。"idle" 状態にあるストリームなど、現在ツリーにないストリームへの依存は、そのストリームにデフォルト優先度が与えられることになります。

ストリームを他のストリームの依存関係に割り当てるとき、そのストリームは、親ストリームの新しい依存関係として追加されます。同じ親を共有する依存ストリームは、その順序をお互いに考慮しません。例えば、ストリームBとCがストリームAに依存する時、ストリームAを依存先とするストリームDが生成された場合、Aの依存関係は任意の順序でB、C、Dが続きます。

  A                 A
 / \      ==>      /|\
B   C             B D C

図3: デフォルト依存関係の生成例

排他フラグは依存関係に新しい階層を挿入できます。排他フラグは、親ストリームの依存関係を自身の依存関係となるようにし、さらに自身を親ストリームの唯一の依存関係となるようにします。先ほどの例において、ストリームAに対して排他依存関係と共にストリームDを生成した場合、DはBとCの親の依存関係になります。

                    A
  A                 |
 / \      ==>       D
B   C              / \
                  B   C

  図4: 排他依存の生成例

依存ツリーの内部では、全ての依存先のストリーム (0x0までの親ストリームのつながり) が終了したり、ストリームの続行が不可能であった場合でも、依存ストリームにはリソースのみが割り当てられるべきです (SHOULD)。

ストリームは自身に依存できません。エンドポイントはこれを PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

5.3.2. 依存関係の重み付け

全ての依存ストリームには、1から256までの整数の重みが割り当てられます。

同じ依存関係にあるストリームは、それらの重みに比例してリソースが割り当てられるべきです (SHOULD)。例えば、ストリームAに依存するストリームBの重みが4であり、同じストリームAに依存するストリームCの重みが12であった場合、Aに何も進展がなければ、ストリームBにはストリームCに割り当てられたリソースの3分の1が割り当てられます。

5.3.3. 再優先度付け

ストリームの優先度は PRIORITY フレームの使用により変更されます。依存関係を設定すると、ストリームを指定した親ストリームに依存させます。

親ストリームが再優先度付けされた場合、依存ストリームは親ストリームと共に移動します。再優先度付けされたストリームに排他フラグを伴う依存関係を設定すると、新しい親ストリームの全ての依存関係を、自身の依存関係となるようにします。

ストリームが自身に依存するストリームの1つに依存関係を生成する場合、以前の依存ストリームは最初に再優先度付けされるストリームの前の親の依存関係になるように移動します。移動する依存ストリームはその重みを維持します。

例えば、BとCがAに、DとEがCに、FがDに依存する依存ツリーを考えます。AがDに依存関係を生成する場合、DはAの位置に移動します。Fを除く他の全ての依存関係はとどまり、再優先度付けが排他である場合は、全てがAに依存するようになります。

  x                x                x                 x
  |               / \               |                 |
  A              D   A              D                 D
 / \            /   / \            / \                |
B   C     ==>  F   B   C   ==>    F   A       OR      A
   / \                 |             / \             /|\
  D   E                E            B   C           B C F
  |                                     |             |
  F                                     E             E
               (中間状態)       (非排他的状態)      (排他的状態)

                図5: 依存関係の並び替えの例

5.3.4. 優先度付けの状態管理

ストリームが依存ツリーから削除された際、その依存関係は終了したストリームの親ストリームに移動できます。新しい依存関係における重みは、自身の重みに基づき、終了したストリームの依存関係の重みに比例して再計算されます。

依存ツリーから削除されたストリームは、一部の優先度情報が失われる可能性があります。リソースは、同じ親ストリームを持つストリーム間で共有されます。これは、そのセット内のストリームが終了するか、ブロックされた状態になった場合、ストリームに割り当てられた予備のリソースはすぐ隣同士のストリームに分散されることを意味します。しかしながら、共有の依存関係がツリーから削除された場合、それらのストリームは、次の上位レベルのストリームとリソースを共有します。

例えば、まずストリームAとBが親を共有しており、ストリームCとDの両方がストリームAに依存していると仮定します。ストリームAとDの処理が続行できない場合は、ストリームAを削除する前に、ストリームCがAのためのリソースの全てを受け取ります。もしストリームAがツリーから削除された場合、ストリームAの重みはストリームCとDに均等に分割されます。ストリームDがまだ処理を続行できない場合、結果としてストリームCは少なくなったリソース比率を受け取ることになります。ストリームCは利用可能なリソースの半分ではなく、3分の1を受け取ります。

ストリームの依存関係を生成する優先度情報が転送中でも、そのストリームを終了することは可能です。依存関係に指定されたストリームが関連する優先度情報を持っていない場合、その依存ストリームには代わりにデフォルト優先度 (5.3.5節) が割り当てられます。ストリームには意図したよりも異なる優先度が与えられるため、最適でない優先度が設定される可能性があります。

これらの問題を防ぐために、エンドポイントは、ストリームが終了した後しばらくの間、ストリームの優先度状態を保持すべきです (SHOULD)。長く状態が保持されると、低確率でストリームが不正に割り当てられたり、デフォルトの優先度が割り当てられたりしてしまいます。

同様に、"idle" 状態にあるストリームは優先度が割り当てられたり、他のストリームの親になることができます。これにより、依存ツリー内に優先度をより柔軟に表現できるグルーピングノードを作成できます。idle ストリームはデフォルト優先度 (5.3.5節) で始まります。

SETTINGS_MAX_CONCURRENT_STREAMS により設定される制限に計算されないストリームの優先度情報の保持は、エンドポイントに大きな状態負荷を生む可能性があります。従って、保持される優先度状態の量を制限してもよいものとします (MAY)。

エンドポイントが優先度のために管理する追加の状態量は、負荷に依存する可能性があります。高負荷時では、リソースのコミットメントを制限するために優先度の状態を破棄できます。極端なケースでは、エンドポイントは有効なストリームや予約済みストリームの優先度も破棄できます。固定の上限が適用された場合、エンドポイントは少なくとも SETTINGS_MAX_CONCURRENT_STREAMS で許可されたストリームよりも多くの状態を保持すべきです (SHOULD)。実装は、優先度ツリーにおいて活発に使用されるストリームの状態の保持を試みるべきです (SHOULD)。

終了したストリームの優先度を変更する PRIORITY フレームを受信したエンドポイントは、十分な状態を保持しているのであれば、そのストリームに依存するストリームの重みを変更すべきです (SHOULD)。

5.3.5. デフォルト優先度

全てのストリームにはストリーム 0x0 への非排他的依存が最初に割り当てられます。プッシュストリーム (8.2節) は関連付けられたストリームに依存します。どちらの場合も、ストリームにはデフォルトの重み 16 が割り当てられます。

5.4. エラー処理

HTTP/2 の枠組みにおいては、2種類のエラーを認めています:

エラーコードのリストは7章にあります。

5.4.1. コネクションエラー処理

コネクションエラーとは、フレームレイヤーの処理の妨げとなるエラーや、接続状態を破壊するエラーです。

コネクションエラーが発生したエンドポイントは、ピアから受信に成功した最後のストリームIDと共に GOAWAY フレーム (6.8節) を最初に送信するべきです (SHOULD)。GOAWAY フレームにはコネクションが終了した理由を示すエラーコードが含まれます。エラー状態での GOAWAY フレームの送信後は、エンドポイントは TCP 接続を終了しなければなりません (MUST)。

GOAWAY は受信側エンドポイントで期待通りに受信されない可能性があります ([RFC7230]、6.6節では、なぜコネクションの即時の切断がデータの損失につながるのかを説明しています)。コネクションエラーが発生した場合、GOAWAY はコネクションが終了した理由をベストエフォートでピアに対して伝えるだけです。

エンドポイントはいつでもコネクションを終了することができます。特にエンドポイントは、ストリームエラーをコネクションエラーとして扱えます (MAY)。状況が許す限り、エンドポイントはコネクションを終了するときに GOAWAY フレームを送信するべきです (SHOULD)。

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

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

ストリームエラーを検知したエンドポイントは、エラーが発生したストリームのストリームIDを含む RST_STREAM フレーム (6.4節) を送信します。また、RST_STREAM フレームはエラーの種類を示すエラーコードも含みます。

RST_STREAM は、エンドポイントがそのストリーム上で送信できる最後のフレームです。RST_STREAM を送信するピアは、リモートピアによってすでに送信されたフレーム、または送信のためにキューに入れられたどんなフレームも受信する準備をしなければなりません (MUST)。これらのフレームは、接続状態を変更する (ヘッダー圧縮 (4.3節) やフロー制御の維持に必要な) フレームを除いて、無視できます。

通常、エンドポイントは任意のストリームに対して複数の RST_STREAM フレームを送信するべきではありません (SHOULD NOT)。しかしながら、ラウンドトリップ時間が経過した後に終了したストリームに対してフレームを受信した場合には、追加の RST_STREAM フレームを送信してもよいものとします (MAY)。この振る舞いは、不正な実装に対処するために認められます。

ループを防ぐために、エンドポイントは RST_STREAM フレームの応答に RST_STREAM フレームを送信してはいけません (MUST NOT)。

5.4.3. コネクションの終了

ストリームが "open" または "half-closed" 状態の間に TCP 接続が終了または初期化された場合、その影響を受けたストリームを自動的に再試行することはできません (8.1.4節)。

5.5. HTTP/2 の拡張

HTTP/2 はプロトコルの拡張を認めています。この節で説明する制限の範囲内であれば、プロトコル拡張を追加のサービスの提供やプロトコルの様々な面を変更するために使用できます。拡張は単一の HTTP/2 コネクションの範囲に影響します。

これは、この文書で定義されるプロトコルの要素に適用されます。また、新しいメソッドの定義やステータスコード、ヘッダーフィールドといった HTTP を拡張するための既存のオプションには影響しません。

拡張では、新しいフレームタイプ (4.1節)、新しい設定 (6.5.2節)、新しいエラーコード (7章) の使用が認められています。レジストリはこれらの拡張ポイントを管理するために、フレームタイプ (11.2節)、設定 (11.3節)、エラーコード (11.4節) でそれぞれ制定されています。

実装は、全てのプロトコルの拡張要素における不明また未対応の値を無視しなければなりません (MUST)。実装は不明または未対応のタイプのフレームを破棄しなければなりません (MUST)。これはどの拡張ポイントも、事前の合意やネゴシエートなしに拡張によって安全に使用できることを意味します。しかしながら、ヘッダーブロック (4.3節) の間に現れる拡張フレームは許可されません。これらは PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱われなければなりません (MUST)。

既存のプロトコル構成要素のセマンティクスを変更する拡張は、使用される前にネゴシエートされなければなりません (MUST)。例えば、HEADERS フレームの配置を変更する拡張は、ピアからこれを受け入れる肯定的な通知があるまで使用することはできません。このような場合、レイアウトの変更が有効になった時に調整を必要とする可能性があります。DATA フレーム以外のフレームをフロー制御の対象として扱う場合は、そのようにセマンティクスを変更し、ネゴシエーションを通じてのみ完了できることに注意してください。

この文書では、拡張の使用をネゴシエートする具体的な方法を強制しません。しかし、設定 (6.5.2節) がこのような目的で使用されることに注意してください。もし両方のピアが拡張を使用する意図を示す値を設定した場合は、その拡張は使用されます。拡張のネゴシエーションに設定が使用される場合、その初期値はその拡張が無効になるように定義されなければなりません (MUST)。

6. フレーム定義

この仕様では、一意な8ビットのタイプコードで識別される、いくつかのフレームタイプを定義します。各フレームタイプは、全体的なコネクションや個々のストリームの確立と管理について、それぞれ異なる目的を果たします。

特定のフレームタイプの送信は、コネクションの状態を変更できます。エンドポイントの両方が接続状態を同期し続けることに失敗した場合、そのコネクションにおいてこれ以上正常な通信をすることはできません。したがって、エンドポイントは特定のフレームを使用することで、状態にどのような影響を与えるかの共通理解を持つことが重要です。

6.1. DATA

DATA フレーム (type=0x0) は、ストリームに関連する任意の可変長オクテット列を転送します。HTTP リクエストまたはレスポンスのペイロードを伝えるために、1つ以上の DATA フレームが使用されます。

DATA フレームは任意のパディングを含んでもよいものとします (MAY)。パディングは DATA フレームのメッセージサイズを隠すために追加できます。パディングはセキュリティのための機能です。詳細は10.7節を参照してください。

+---------------+
|Pad Length? (8)|
+---------------+-----------------------------------------------+
|                            Data (*)                         ...
+---------------------------------------------------------------+
|                           Padding (*)                       ...
+---------------------------------------------------------------+

                    図6: DATA フレームペイロード

DATA フレームは以下のフィールドを含みます:

Pad Length
オクテット単位のフレームパディングの長さを含む8ビットのフィールドです。このフィールドは (図中で "?" と示されているように) 条件付きであり、PADDED フラグが設定された場合にのみ存在します。
Data
アプリケーションデータ。フレームペイロードから、存在する他のフィールドの長さを引いた後の残りがデータの量になります。
Padding
アプリケーションにとって意味のある値を含まないパディングオクテットです。パディングオクテットは送信時には0を設定しなければなりません (MUST)。受信者にはパディングの検証は義務付けられません。ただし、0でないパディングを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱ってもよいものとします (MAY)。

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

END_STREAM (0x1)
ビット0は、エンドポイントが特定のストリームに送信する最後のフレームであることを示します。このフラグを設定することで、ストリームはいずれかの "half-closed" 状態または "closed" 状態 (5.1節) に遷移します。
PADDED (0x8)
ビット3は、Pad Length フィールドとパディングが設定されていることを示します。

DATA フレームはストリームに関連付けられなければなりません (MUST)。Stream Identifier フィールドが 0x0 の DATA フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) で応答しなければなりません (MUST)。

DATA フレームはフロー制御の対象となり、ストリームが "open" または "half-closed (remote)" 状態の問にのみ送信できます。Pad Length や Padding フィールドが存在する場合は、それらを含む DATA フレームのペイロードの全てが、フロー制御に含まれます。"open" または "half-closed (local)" 状態にないストリームから DATA フレームを受信した場合は、受信者は STREAM_CLOSED のストリームエラー (5.4.2節) で応答しなければなりません (MUST)。

パディングオクテットの合計は、Pad Length フィールドの値により決定されます。パディングの長さが、フレームペイロードの長さと同じかそれよりも大きい場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

注: 値が0の Pad Length フィールドを含めることで、フレームを1オクテット大きくできます。

6.2. HEADERS

HEADERS フレーム (type=0x1) は名前-値のペアを転送します。これはストリームの開始 (5.1節) に使用されます。HEADERS フレームは "idle"、"reserved (local)"、"open" または "half-closed (remote)" 状態のストリームに送信できます。

+---------------+
|Pad Length? (8)|
+-+-------------+-----------------------------------------------+
|E|                 Stream Dependency? (31)                     |
+-+-------------+-----------------------------------------------+
|  Weight? (8)  |
+-+-------------+-----------------------------------------------+
|                   Header Block Fragment (*)                 ...
+---------------------------------------------------------------+
|                           Padding (*)                       ...
+---------------------------------------------------------------+

                  図7: HEADERS フレームペイロード

HEADERS フレームのペイロードは以下のフィールドを含みます:

Pad Length
オクテット単位のフレームパディングの長さを含む8ビットのフィールドです。このフィールドは PADDED フラグが設定された場合にのみ存在します。
E
ストリームの依存関係の排他を示す1ビットのフラグです (5.3節)。このフィールドは PRIORITY フラグが設定された場合にのみ存在します。
Stream Dependency
31ビットの依存先ストリームのストリームIDです (5.3節)。このフィールドは PRIORITY フラグが設定された場合にのみ存在します。
Weight
ストリーム優先度の重みを示す8ビットの符号なし整数です。5.3節を参照してください。この値に1を加えた値が1から256までの重みとなります。このフィールドは PRIORITY フラグが設定された場合にのみ存在します。
Header Block Fragment
ヘッダーブロックフラグメント (4.3節)。
Padding
パディングオクテット。

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

END_STREAM (0x1)
ビット0が設定されると、エンドポイントが特定のストリームに送信する最後のヘッダーブロック (4.3節) であることを示します。
HEADERS フレームは、ストリームの終了を通知する END_STREAM フラグを転送します。しかしながら、END_STREAM フラグが設定された HEADERS フレームの後には、同一ストリーム上に CONTINUATION フレームが続く可能性があります。論理的には、CONTINUATION フレームは HEADERS フレームの一部です。
END_HEADERS (0x4)
ビット2は、このフレームの後には CONTINUATION フレームが続かず、このフレームに完全なヘッダーブロック (4.3節) が含まれていることを示します。
END_HEADERS フラグが設定されていない HEADERS フレームの後には、同一ストリームに CONTINUATION フレームが続かなければなりません (MUST)。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
PADDED (0x8)
ビット3は、Pad Length フィールドとパディングが設定されていることを示します。
PRIORITY (0x20)
ビット5は Exclusive Flag (E)、Stream Dependency、Weight フィールドが設定されていることを示します。5.3節を参照してください。

HEADERS フレームのペイロードは、ヘッダーブロックフラグメント (4.3節) を含みます。HEADERS フレームに収まらないヘッダーブロックは CONTINUATION フレーム (6.10節) に分割されなければなりません。

HEADERS フレームはストリームに関連付けられなければなりません (MUST)。受信した HEADERS フレームの Stream Identifier フィールドが 0x0 であった場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

HEADERS フレームは、4.3節で定義されたように接続状態を変更します。

HEADERS フレームにはパディングを含められます。Padding フィールドと関連するフラグは DATA フレーム (6.1節) における定義と全く同じです。パディングの長さが、残りのヘッダーブロックフラグメントの長さよりも大きい場合、受信者は PROTOCOL_ERROR として扱わなければなりません (MUST)。

HEADERS フレームの優先度情報は、PRIORITY フレームで送信されるものと論理的には同じですが、HEADERS に含めることで新しいストリームが作られた際にストリームの優先度が混乱するのを防止できます。HEADERS フレーム内の優先度フィールドは、そのストリームの最初の再優先度付け (5.3.3節) に続くものです。

6.3. PRIORITY

PRIORITY フレーム (type=0x2) は、送信者からのストリーム優先度 (5.3節) を指定します。このフレームは、アイドル中のストリームや終了したストリームを含む、全てのストリームの状態で送信できます。

+-+-------------------------------------------------------------+
|E|                  Stream Dependency (31)                     |
+-+-------------+-----------------------------------------------+
|   Weight (8)  |
+-+-------------+

                  図8: PRIORITY フレームペイロード

PRIORITY フレームのペイロードは、以下のフィールドを含みます:

E
ストリームの依存関係の排他を示す1ビットのフラグです (5.3節)。
Stream Dependency
31ビットの依存先ストリームのストリームIDです (5.3節)。
Weight
ストリーム優先度の重みを示す8ビットの符号なし整数です (5.3節)。この値に1を加えた値が1から256までの重みとなります。

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

PRIORITY フレームは常にストリームに関連付けられます。ストリームIDが 0x0 の PRIORITY フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

PRIORITY フレームは、全ての状態のストリームに送信できます。ただし、1つのヘッダーブロック (4.3節)を構成する連続したフレームの間での送信はできません。このフレームは、処理の完了後やフレーム送信後に受信されることもあり、そのため関連付けられたストリームには何も影響を与えない可能性があることに注意してください。"half-closed (remote)" や "closed" 状態にあるストリームでは、このフレームは関連付けられたストリームとそれに依存するストリームの処理にのみ影響し、他のストリームの送信には影響を与えません。

PRIORITY フレームは "idle" または "closed" 状態にあるストリームに送信できます。これは、未使用または終了済みの親ストリームの優先度を変更することで、依存ストリームのグループの再優先度付けを可能にします。

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

6.4. RST_STREAM

RST_STREAM フレーム (type=0x3) はストリームの即時終了を可能にします。RST_STREAM はストリームのキャンセルの要求やエラーの状態にあることを示すために送信されます。

+---------------------------------------------------------------+
|                        Error Code (32)                        |
+---------------------------------------------------------------+

                 図9: RST_STREAM フレームペイロード

RST_STREAM フレームはエラーコード (7章) を明確にする符号なし32ビット整数を1つ含みます。このエラーコードは、ストリームが終了した理由を示します。

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

RST_STREAM フレームは関連するストリームを完全に終了し、"closed" 状態に遷移させます。RST_STREAM をストリーム上で受信した後に、受信者はそのストリームに対して PRIORITY 以外の追加のフレームを送信してはいけません (MUST NOT)。しかしながら、RST_STREAM を送信した後でも、送信側エンドポイントは、RST_STREAM が到着する前にピアが 送信したかもしれない追加のフレームを受信し、処理する準備をしなければなりません (MUST)。

RST_STREAM フレームはストリームに関連付けられなければなりません (MUST)。受信した RST_STREAM フレームの Stream Identifier フィールドが 0x0 であった場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

RST_STREAM フレームは "idle" 状態のストリームに送信してはいけません (MUST NOT)。"idle" 状態のストリームに関連する RST_STREAM フレームを受信した場合は、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

長さが 4 オクテットでない RST_STREAM フレームは、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として扱われなければなりません (MUST)。

6.5. SETTINGS

SETTINGS frame (type=0x4) は、ピアの振る舞いに関する初期設定や制約といった、エンドポイントの通信方法に影響を与える設定パラメーターを転送します。SETTINGS フレームはそのようなパラメータの受信確認にも使用されます。SETTINGS パラメーターはそれぞれが「設定」としても呼ばれます。

SETTINGS パラメーターはネゴシエートされません。これらは送信側ピアが特性を記述し、受信側ピアによって使用されます。また、それぞれのピアから、同一のパラメーターに対して異なる値が通知されます。例えば、クライアントは高い初期フロー制御ウインドウを設定するかもしれませんが、サーバーはリソースを節約するために低い値を設定するかもしれません。

SETTINGS フレームは、コネクション開始時に両方のエンドポイントから送信されなければなりません (MUST)。また、接続中はいかなる時でもいずれかのエンドポイントから送信してもよいものとします (MAY)。実装は、この仕様に定義されている全てのパラメーターに対応しなければなりません (MUST)。

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

SETTINGS パラメーターは受信したピアにより確認されます。これを有効にするため、SETTINGS フレームは以下のフラグを定義します:

ACK (0x1)
ビット0が設定されると、フレームの受信を確認し、ピアの SETTINGS フレームを適用したことを示します。このビットが設定された時、SETTINGS フレームのペイロードは空でなければなりません (MUST)。ACK フラグが設定され、Length フィールドの値が 0 以外になっている SETTINGS フレームの受信は、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。より詳しい情報は、6.5.3節 (設定の同期) を参照してください。

SETTINGS フレームは、1つのストリームではなく、コネクションに対して常に適用されます。SETTINGS フレームのストリームIDは 0 (0x0) でなければなりません (MUST)。Stream Identifier フィールドに 0x0 以外の値が設定された SETTINGS フレームを受信した場合、エンドポイントは PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

SETTINGS フレームは接続状態に影響します。不正な形式や不完全な SETTINGS フレームは、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱われなければなりません (MUST)。

長さが6オクテットの倍数でない SETTINGS フレームは、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として扱われなければなりません (MUST)。

6.5.1. SETTINGS フォーマット

SETTINGS フレームのペイロードは0個以上のパラメーターからなります。各パラメーターは、16ビットの設定識別子と符号なし32ビットの設定値からなります。

+-------------------------------+
|       Identifier (16)         |
+-------------------------------+-------------------------------+
|                        Value (32)                             |
+---------------------------------------------------------------+

                       図10: 設定フォーマット

6.5.2. 定義済みの SETTINGS パラメーター

定義済みの設定は以下の通りです:

SETTINGS_HEADER_TABLE_SIZE (0x1)
リモートエンドポイントがヘッダーブロックのデコードに使用する、ヘッダー圧縮テーブルのオクテット単位での最大サイズを、送信者が通知可能にします。エンコーダーは、ヘッダーブロック内のヘッダー圧縮フォーマットにおいて特定の値を使用することで、この値以下の任意のサイズを選択できます ([COMPRESSION])。初期値は 4,096 オクテットです。
SETTINGS_ENABLE_PUSH (0x2)
この設定はサーバープッシュ (8.2節) を無効化するために使用できます。この値が 0 になっているパラメーターを受信した場合、エンドポイントは PUSH_PROMISE フレームを送信してはいけません (MUST NOT)。このパラメーターに 0 を設定し、その応答が受けたエンドポイントは、PUSH_PROMISE フレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません(MUST)。
初期値は 1 であり、これはサーバープッシュが許可されていることを示します。0 または 1 ではない値は全て、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません。
SETTINGS_MAX_CONCURRENT_STREAMS (0x3)
送信者が許可する同時ストリームの最大数を示します。この制限は方向性を持ち、送信者が受信者に作成を許可するストリームの数に適用されます。初期状態ではこの値は無制限になっています。並列性の不要な制限をしないために、この値は 100 以下にしないことをおすすめします。
値が0の SETTINGS_MAX_CONCURRENT_STREAMS を、エンドポイントは特別な値として扱うべきではありません (SHOULD NOT)。0 の値は新しいストリームの生成を防ぎます。しかしながらこのような状況は、どんな制限をしていても、アクティブストリームによる枯渇によって発生する可能性があります。サーバーは短期間の間にのみ 0 の値を設定すべきです (SHOULD)。サーバーがリクエストを受け付けたくないような場合には、接続を終了するほうがより適切です。
SETTINGS_INITIAL_WINDOW_SIZE (0x4)
ストリームレベルのフロー制御のための、送信者の初期ウインドウサイズ (オクテット) を示します。初期値は 2^16-1 (65,535) です。
この設定は、全てのストリームのウインドウサイズに影響します (6.9.2節)。
フロー制御ウインドウサイズの最大値である 2^31-1 を超える値は FLOW_CONTROL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません。
SETTINGS_MAX_FRAME_SIZE (0x5)
送信者が受信できるフレームペイロードのオクテット単位の最大サイズを示します。
初期値は 2^14 (16,384) オクテットです。エンドポイントにより通知される値は、初期値と最大のフレームサイズ (2^24-1 オクテットまたは 16,777,215 オクテット) の間でなければなりません (MUST)。この範囲外の値は、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
SETTINGS_MAX_HEADER_LIST_SIZE (0x6)
このアドバイザリ設定は、送信者が受け入れるように準備されたヘッダーリストのオクテット単位の最大サイズをピアに通知します。この値は、各ヘッダーフィールドの名前や値の長さのオクテットに 32 オクテットのオーバーヘッドを加えた、ヘッダーフィールドの未圧縮サイズです。
任意のリクエストに対して、通知された値よりも低い制限を強制されてもよいものとします (MAY)。この設定の初期値は無制限です。

不明や未対応の識別子を含む SETTINGS フレームを受信したエンドポイントは、その設定を無視しなければなりません (MUST)。

6.5.3. 設定の同期

ほとんどの SETTINGS 値にとって、いつピアが変更するパラメーター値を受信し、その値を適用したかを知ることはメリットになり、そうなることが求められます。このような同期点を提供するために、ACK フラグが設定されていない SETTINGS フレームの受信者は、受信後に更新されたパラメーターを可能な限り早く適用しなければなりません (MUST)。

SETTINGS フレームの値は、その間に他のフレームを処理することなく、出現した順序で処理されなければなりません (MUST)。未対応のパラメーターは無視されなければなりません (MUST)。全ての値を処理後、受信者は ACK フラグを設定した SETTINGS フレームをすぐに送信しなければなりません (MUST)。ACK フラグが設定された SETTINGS フレームを受信すると、パラメーターを変更した送信者は適用された設定に依存できます。

SETTINGS フレームの送信者が妥当な時間に応答を受信しなかった場合、SETTINGS_TIMEOUT のコネクションエラー (5.4.1節) として応答してもよいものとします (MAY)。

6.6. PUSH_PROMISE

PUSH_PROMISE フレーム (type=0x5) は、送信者が開始する予定のストリームを事前にピアエンドポイントに通知するために使用します。PUSH_PROMISE フレームは、エンドポイントがストリームに追加のコンテキストを提供するヘッダーセットと共に、作成する予定のストリームの符号なし31ビット識別子を含みます。PUSH_PROMISE フレームの使用についての完全な説明は、8.2節に記述されています。

+---------------+
|Pad Length? (8)|
+-+-------------+-----------------------------------------------+
|R|                  Promised Stream ID (31)                    |
+-+-----------------------------+-------------------------------+
|                   Header Block Fragment (*)                 ...
+---------------------------------------------------------------+
|                           Padding (*)                       ...
+---------------------------------------------------------------+

               図11: PUSH_PROMISE ペイロードフォーマット

PUSH_PROMISE フレームのペイロードは、以下のフィールドを含みます:

Pad Length
オクテット単位のフレームパディングの長さを含む8ビットのフィールドです。このフィールドは PADDED フラグが設定された場合にのみ存在します。
R
予約済みビットです。
Promised Stream ID
PUSH_PROMISE により予約されたストリームを識別するための符号なし31ビット整数です。予約済みストリームIDは、送信者が次に送信するストリームとして有効なものでなければなりません (MUST) (5.1.1節の "新しいストリームID" を参照してください)。
Header Block Fragment
リクエストヘッダーフィールドを含むヘッダーブロックフラグメント (4.3節) です。
Padding
パディングオクテット。

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

END_HEADERS (0x4)
ビット2は、このフレームの後には CONTINUATION フレームが続かず、このフレームに完全なヘッダーブロック (4.3節) が含まれていることを示します。
END_HEADERS フラグが設定されていない PUSH_PROMISE フレームの後には、同一ストリームに CONTINUATION フレームが続かなければなりません (MUST)。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
PADDED (0x8)
ビット3は、Pad Length フィールドとパディングが設定されていることを示します。

PUSH_PROMISE フレームは、"open" または "half-closed (remote)" 状態の、ピアにより開始されたストリームでのみ送信されなければなりません (MUST)。PUSH_PROMISE フレームのストリームIDは、そのストリームが関連付けられたものであることを示します。ストリームIDフィールドに 0x0 を指定した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

予約済みストリームは、それらが予約された順番で使用される必要はありません。PUSH_PROMISE は今後使用するストリームIDのみを予約します。

ピアエンドポイントの SETTINGS_ENABLE_PUSH 設定に0が設定された場合は、PUSH_PROMISE は送信されてはいけません (MUST NOT)。SETTINGS_ENABLE_PUSH 設定を0に設定し、その応答を受信したエンドポイントは、PUSH_PROMISE フレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

PUSH_PROMISE フレームの受信者は、PUSH_PROMISE の送信者に予約済みストリームIDを参照する RST_STREAM を送信することで、予約済みストリームを拒否できます。

PUSH_PROMISE フレームは2つの方法で接続状態を変更します。ヘッダーブロック (4.3節)を含めることは、ヘッダー圧縮のために保持されている状態を変更する可能性があります。PUSH_PROMISE は、予約済みストリームを "reserved" 状態に遷移させることで、今後使用するストリームを予約します。送信者は、"open" または "half-closed (remote)" のいずれかの状態ではないストリームには PUSH_PROMISE を送信してはいけません (MUST NOT)。また、送信者は予約済みストリームが新しいストリームID (5.1.1節) を正しく選択していることも保証しなければなりません (MUST) (これはつまり、予約済みストリームは "idle" 状態でなければなりません (MUST))。

PUSH_PROMISE はストリームを予約するため、PUSH_PROMISE フレームを無視することは、ストリームの状態を不安定にさせる原因となります。受信者は "open" や "half-closed (local)" でないストリームでの PUSH_PROMISE への応答は、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。しかしながら、関連付けられたストリームで RST_STREAM を送信したエンドポイントは、RST_STREAM フレームが受信または処理される前に生成された可能性のある PUSH_PROMISE フレームを扱わなければなりません (MUST)。

受信者は不正なストリームID (5.1.1節) を予約する PUSH_PROMISE への応答を、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。不正なストリームIDは、現在 "idle" 状態ではないストリームのIDを指すことに注意してください。

PUSH_PROMISE フレームにはパディングを含められます。Padding フィールドと関連するフラグは DATA フレーム (6.1節) における定義と全く同じです。

6.7. PING

PING フレーム (type=0x06) は、アイドル中のコネクションがまだ機能しているかどうかを確認するだけでなく、送信者からの往復遅延時間も計測するための仕組みです。PING フレームはどちらのエンドポイントも送信できます。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                      Opaque Data (64)                         |
|                                                               |
+---------------------------------------------------------------+

                  図12: PING ペイロードフォーマット

PING フレームは、フレームヘッダーに加え、ペイロードに8オクテットの Opaque データを含まなければなりません (MUST)。送信者はペイロードに任意の値を選択して含めることができ、任意の方法でそれらのオクテットを使用できます。

ACK フラグを含まない PING フレームの受信者は、そのレスポンスとして、同じペイロードと共に ACK フラグを設定した PING フレームを送信しなければなりません (MUST)。PING レスポンスは他のフレームよりも高い優先度が設定されるべきです (SHOULD)。

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

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

PING フレームは個別のストリームには関連付けられません。ストリームIDフィールドの値が 0x0 でない PING フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

長さフィールドの値が8になっていない PING フレームの受信者は、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

6.8. GOAWAY

GOAWAY フレーム (type=0x7) はコネクションの終了の開始や、重大なエラー状態の通知に使用されます。GOAWAY はエンドポイントが以前に確立されたストリームの処理を完了している間に、新しいストリームの受け入れを緩やかに停止できるようにします。これにより、サーバーメンテナンスのような管理作業を可能にします。

新しくストリームを開始したエンドポイントと、GOAWAY フレームを送信したリモートの間には、固有の競合状態があります。このような場合に対処するため、GOAWAY は現在のコネクションで送信側エンドポイントが最後に処理した、または処理したと思われる、ピアが開始した最後のストリームIDを含みます。例えば、サーバーが GOAWAY フレームを送信した場合、最後のストリームIDは、クライアントが開始したストリームの最も大きい番号のストリームIDになります。

このフレームが送信されると、送信者は、最終ストリームIDに指定した値よりも大きいストリームIDをもつ、新しいストリームに送信されたフレームを無視します。GOAWAY フレームの受信者は、現在のコネクション上で新しい追加のストリームを開始してはいけません (MUST NOT)。しかし、新しいストリームを生成するために新しくコネクションを確立できます。

GOAWAY の受信者が、GOAWAY フレームで示されたストリームIDよりも大きいIDを持つストリームにデータを送信した場合、それらのストリームは処理されません。GOAWAY フレームの受信者は、そのストリームの全てが生成されなかったものとして扱うことができます。したがって、これらのストリームは、後に新しいコネクション上で再施行できます。

ストリームが部分的に処理されたのかどうかを、リモートピアが知ることができるよう、エンドポイントはコネクションを終了する前に、常に GOAWAY フレームを送信するべきです (SHOULD)。例えば、ある HTTP クライアントが、サーバーがコネクションを終了するのと同時に POST を送信した場合に、サーバーがどのストリームまで処理したかを示す GOAWAY フレームを送信しなければ、クライアントはサーバーが POST リクエストの処理を開始したのかどうかを知ることができません。

不正なピアに対しては、エンドポイントは GOAWAY の送信なしにコネクションを終了することを選ぶかもしれません。

GOAWAY フレームは直ちにコネクションの終了を開始しない可能性があります。コネクションをこれ以上使用しない GOAWAY の受信者であっても、コネクションを終了する前に GOAWAY フレームを送信するべきです (SHOULD)。

+-+-------------------------------------------------------------+
|R|                  Last-Stream-ID (31)                        |
+-+-------------------------------------------------------------+
|                      Error Code (32)                          |
+---------------------------------------------------------------+
|                  Additional Debug Data (*)                    |
+---------------------------------------------------------------+

                  図13: GOAWAY ペイロードフォーマット

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

GOAWAY フレームは特定のストリームではなく、コネクションに対して適用されます。エンドポイントはストリームIDが 0x0 以外の値になっている GOAWAY フレームを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

GOAWAY の最終ストリームIDには、GOAWAY フレームの送信者が何らかの動作をおこなった、あるいはまだ動作をおこなっていないストリームのうち、最も大きい値のストリームIDが含まれます。このストリームIDまでのストリームは全て、すでに何らかの方法で処理された可能性があります。処理されたストリームが存在しない場合は、最終ストリームIDに0が設定される可能性があります。

注: この文脈における "処理された" とはストリームのデータが、何らかの動作をするかもしれない上位レイヤーのソフトウェアに渡された結果を意味します。

GOAWAY フレームの送信なしにコネクションを終了した場合、最終ストリームIDは事実上もっとも大きい値のストリームIDになります。

指定された値と等しいまたはそれ以下のIDを持つストリームのうち、コネクションが終了する前に完全に終了されていないストリームでは、リクエストの再試行やトランザクション、HTTP GET、PUT、DELETE のような冪等な動作を除く、その他のプロトコル処理ができません。指定された値よりも大きいIDのストリームを使用するプロトコル処理は、新しいコネクションを使用して安全に再実行できます。

最終ストリームIDの値と等しいかまたはそれ以下のIDを持つストリームでの処理は、正常に完了する可能性があります。GOAWAY フレームの送信者は、処理中のストリームが全て完了するまで "open" 状態でコネクションを維持し、GOAWAY フレームを送信することで緩やかにコネクションを終了するかもしれません。

状況の変化に応じて、エンドポイントは複数の GOAWAY フレームを送信してもよいものとします (MAY)。例えば、緩やかなシャットダウン中に NO_ERROR と共に GOAWAY を送信したエンドポイントは、その後、接続の即時終了を必要とする状況に陥る可能性があります。受信した最後の GOAWAY フレームの最終ストリームIDは、処理した可能性があるストリームを示します。エンドポイントは、ピアが既に別のコネクション上で未処理リクエストの再施行をしている可能性があるため、自身が送信した最終ストリームIDの値を大きくしてはいけません (MUST NOT)。

リクエストを再施行できないクライアントは、サーバーがコネクションを終了すると、転送中の全てのリクエストを失うことになります。これは、HTTP/2 を使用してクライアントにサービスを提供していない可能性のある中継者にとっては特に起こりえます。コネクションの緩やかなシャットダウンを試みるサーバーは、最終ストリームIDに 2^31-1 を設定し、NO_ERROR コードを設定した最初の GOAWAY フレームを送信すべきです (SHOULD)。これは、シャットダウンが近づいており、さらなるリクエストの開始は禁止されていることをクライアントに通知します。送信中のストリーム生成のための時間 (少なくとも1回分のラウンドトリップ時間) を与えた後、サーバーは更新された最終ストリームIDと共に再度 GOAWAY フレームを送信できます。これにより、リクエストを失うことなく、正しくコネクションが終了されることを確実にします。

GOAWAY フレームの送信後、送信者は受信者により送信された最終ストリームに指定したIDよりも大きいIDを持つストリームのフレームを破棄することができます。しかしながら、接続状態を変更するフレームは完全には無視されません。例えば、HEADERS、PUSH_PROMISE、CONTINUATION フレームは、矛盾のないヘッダー圧縮の状態 (4.3節) を保証するために、最低限処理されなければなりません (MUST)。同様に、DATA フレームはコネクションフロー制御ウインドウに対して計算されなければなりません (MUST)。これらのフレームの処理に失敗すると、フロー制御やヘッダー圧縮の状態が同期されない可能性があります。

GOAWAY フレームは、コネクションを終了する理由を示す32ビットのエラーコード (7章) も含みます。

エンドポイントは、GOAWAY フレームのペイロードに未定義のデータを追加してもよいものとします (MAY)。デバッグ情報にはセキュリティやプライバシーに関わるデータを含めることができます。記録されていたり、永続的に格納されているデバッグデータは、不正なアクセスを防ぐために適切な保護手段を持たなければなりません (MUST)。

6.9. WINDOW_UPDATE

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

フロー制御は、個々のストリームとコネクション全体の2段階でおこなわれます。

どちらの段階のフロー制御もホップ間、つまり2つのエンドポイントの間でのみおこなわれます。中継者は繋がっているコネクションの間で WINDOW_UPDATE フレームを転送しません。しかしながら受信者がデータ転送をスロットリングすることによって、元の送信者に対してフロー制御情報を間接的に伝搬させることができます。

フロー制御は、フロー制御の対象となる特定のフレームにのみ適用されます。この文書に定義されるフレームの種類のうち、対象となるのは DATA フレームのみです。フロー制御の対象でないフレームは、受信者がフレームを処理するためのリソースの割り当てに失敗しない限り、受け入れ、処理されなければなりません (MUST)。フレームの受け入れに失敗した場合、受信者はストリームエラー (5.4.2節) または FLOW_CONTROL_ERROR のコネクションエラー (5.4.1節) として応答してもよいものとします (MAY)。

+-+-------------------------------------------------------------+
|R|              Window Size Increment (31)                     |
+-+-------------------------------------------------------------+

              図14: WINDOW_UPDATE ペイロードフォーマット

WINDOW_UPDATE フレームのペイロードは、1つの予約ビットと、既存のフロー制御ウインドウに加えて送信者が送信可能なオクテット数を示す、符号なし31ビットの整数からなります。フロー制御ウインドウの増加量として認められる範囲は、1 から 2^31-1 (2,147,483,647) オクテットです。

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

WINDOW_UPDATE フレームは、ストリームやコネクションを特定できます。ストリームの場合、フレームのストリームIDが対象のストリームを示し、コネクションの場合は、ストリームID "0" がこのフレームの対象がコネクション全体であることを示します。

受信者は、フロー制御ウインドウの増加量に 0 が指定された WINDOW_UPDATE フレームの受信を、PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。コネクションフロー制御ウインドウでの同様のエラーは、コネクションエラー (5.4.1節) として扱わなければなりません。

WINDOW_UPDATE は、END_STREAM フラグを設定したフレームを送信したピアから送信できます。これは、受信者が "half-closed (remote)" や "closed" 状態のストリームで WINDOW_UPDATE フレームを受信できることを意味します。受信者はこれをエラーとして扱ってはいけません (MUST NOT) (5.1節)。

フロー制御下のフレームを受信した受信者は、受信者がコネクションエラー (5.4.1節)として扱わない限り、常にコネクションフロー制御ウインドウへの影響を考慮しなければなりません (MUST)。この考慮はフレームにエラーがある場合であっても必要です。送信者はフロー制御ウィンドウに対してフレームを計算しているため、受信者がこれをおこなわなければ、送信者と受信者のフロー制御ウインドウに差異が発生する可能性があります。

長さが4オクテットでない WINDOW_UPDATE フレームは、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

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

HTTP/2 におけるフロー制御は、各ストリームの送信者ごとに保持されるウインドウを使用することで実装されます。フロー制御ウインドウは、送信者が送信可能なデータのオクテット数を示す、シンプルな整数値です。このサイズは、受信者のバッファ容量を計測したサイズでもあります。

ストリームフロー制御ウインドウと、コネクションフロー制御ウインドウの2つのフロー制御ウインドウが適用されます。送信者は、受信者から告知されたいずれかのフロー制御ウインドウで、使用可能な容量を超える長さのフロー制御下にあるフレームを送信してはいけません (MUST NOT)。いずれかのフロー制御ウインドウに使用可能な容量がない場合は、END_STREAM フラグが設定された長さが 0 のフレーム (つまり、空の DATA フレーム) を送信してもよいものとします (MAY)。

フロー制御の計算対象には、9オクテットのフレームヘッダーは含まれません。

フロー制御下のフレームを送信後、送信者は2つのウインドウの使用可能な容量から、送信したフレームの長さ分を減少させます。

フレームの受信者はデータを処理し、フロー制御ウインドウの容量を開放して、WINDOW_UPDATE フレームを送信します。ストリームレベルとコネクションレベルのフロー制御ウインドウのために、WINDOW_UPDATE フレームは分割されて送信されます。

WINDOW_UPDATE フレームを受信した送信者は、フレームに指定された容量を使用して、関連するウインドウを更新します。

送信者は、2^31-1 オクテットを超えるフロー制御ウインドウを許可してはいけません (MUST NOT)。送信者がこの最大容量を超えるフロー制御ウインドウが指定された WINDOW_UPDATE を受信した場合は、ストリームまたはコネクションのいずれか適切な方を終了しなければなりません (MUST)。ストリームにおいては FLOW_CONTROL_ERROR のエラーコードと共に RST_STREAM を、コネクションにおいては FLOW_CONTROL_ERROR のエラーコードと共に GOAWAY フレームを送信者は送信します。

送信者からのフロー制御下のフレームと、受信者からの WINDOW_UPDATE フレームは、お互いに完全に非同期です。この特性は、ストリームの停止するのを防ぎ、送信者が保持するウインドウサイズを受信者が積極的に更新することを可能にします。

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

HTTP/2 接続が最初に確立された時に、65,535 オクテットの初期フロー制御ウインドウサイズと共に新しいストリームが作成されます。コネクションフロー制御ウインドウも 65,535 オクテットになります。どちらのエンドポイントも、コネクションプリフェイスの一部として、SETTINGS フレームに SETTINGS_INITIAL_WINDOW_SIZE の値を含めることで、新しいストリームのための初期ウインドウサイズを調整できます。コネクションフロー制御ウインドウは WINDOW_UPDATE フレームを使用してのみ変更できます。

SETTINGS_INITIAL_WINDOW_SIZE の値が設定された SETTINGS フレームを受信する前に、フロー制御下のフレームを送信する場合は、エンドポイントはデフォルトの初期ウインドウサイズのみを使用できます。同様に、WINDOW_UPDATE フレームを受信するまでは、コネクションフロー制御ウインドウにはデフォルトの初期ウインドウサイズが設定されます。

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

SETTINGS_INITIAL_WINDOW_SIZE の変更は、フロー制御ウインドウの使用可能な容量を負の値にする可能性があります。送信者は負の値のフロー制御ウインドウに従わなければならず (MUST)、フロー制御ウインドウが正の値になる WINDOW_UPDATE フレームを受信するまで、新しいフロー制御下のフレームを送信してはいけません (MUST NOT)。

例えば、クライアントがコネクション確立と同時に 60KB を送信し、サーバーが初期ウインドウサイズを 16KB に設定した場合、クライアントは SETTINGS フレームの受信時に、使用可能なフロー制御ウインドウを -44KB に再計算します。クライアントは、WINDOW_UPDATE フレームがウインドウを正の値に戻すまで、負の値のフロー制御ウインドウを保持します。ウインドウが正の値に戻った後に、クライアントは送信を再開します。

SETTINGS フレームはコネクションフロー制御ウインドウを変更できません。

エンドポイントは、フロー制御ウインドウが最大サイズを超えるような SETTINGS_INITIAL_WINDOW_SIZE の変更を FLOW_CONTROL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

6.9.3. ストリームウインドウサイズの減少

現在のサイズよりも少ないフロー制御ウインドウの使用を要求する受信者は、新しい SETTINGS フレームを送信できます。しかしながら、送信者は SETTINGS フレームを処理する前に、変更後の制限を超えるデータを送信した可能性があるため、受信者は変更後のウインドウサイズを超えるデータの受信に備えなければなりません (MUST)。

初期フロー制御ウインドウサイズを減少させる SETTINGS フレームの送信後、受信者はフロー制御の制限を超えるストリームの処理を続けてもよいものとします (MAY)。ストリームの続行を可能にすることは、フロー制御ウインドウのために確保された空間を直ちに減らすことを受信者に認めるものではありません。送信者に対して送信再開を許可するために WINDOW_UPDATE フレームが必要になるまで、これらのストリームの処理は停止できます。受信者は影響を受けたストリームに対して、FLOW_CONTROL_ERROR エラーと共に RST_STREAM を代わりに送信してもよいものとします (MAY)。

6.10. CONTINUATION

CONTINUATION フレーム (type=0x9) は連続するヘッダーブロックフラグメントの続きに使用されます (4.3節)。同一ストリームの直前のフレームが END_HEADERS が設定されていない HEADERS、PUSH_PROMISE、または CONTINUATION である限り、任意の数の CONTINUATION フレームを送信できます。

+---------------------------------------------------------------+
|                   Header Block Fragment (*)                 ...
+---------------------------------------------------------------+

                図15: CONTINUATION フレームペイロード

CONTINUATION フレームのペイロードはヘッダーブロックフラグメントを含みます (4.3節)。

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

END_HEADERS (0x4)
ビット2は、ヘッダーブロック (4.3節) がこのフレームで終わることを示します。
END_HEADERS ビットが設定されない場合、このフレームの後には他の CONTINUATION フレームが続かなければなりません。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

CONTINUATION フレームは4.3節で定義されるように接続状態を変更します。

CONTINUATION フレームはストリームに関連付けられなければなりません (MUST)。ストリームIDフィールドの値が 0x0 になっている CONTINUATION フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

CONTINUATION フレームは、END_HEADERS フラグが設定されていない HEADERS、PUSH_PROMISE、または CONTINUATION フレームの後に続いてなければなりません (MUST)。このルールへの違反を検知した受信者は、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

7. エラーコード

エラーコードは、ストリームやコネクションのエラー理由を伝えるために RST_STREAM と GOAWAY フレームで使用される32ビットのフィールドです。

エラーコードは共通のコード領域を共有します。一部のエラーコードは、ストリームまたはコネクション全体のいずれかのみに適用され、それ以外の状況では定義されたセマンティクスを持ちません。

以下のエラーコードが定義されます:

NO_ERROR (0x0)
関連する状態は、エラーの結果ではありません。例えば、GOAWAY はコネクションが緩やかに終了することを示すためにこのコードを含むかもしれません。
PROTOCOL_ERROR (0x1)
エンドポイントが不特定のエラーを検知しました。このエラーは明確なエラーコードが提供されていない時に使用されます。
INTERNAL_ERROR (0x2)
エンドポイントで予期せぬ内部エラーが発生しました。
FLOW_CONTROL_ERROR (0x3)
エンドポイントがピアのフロー制御プロトコル違反を検知しました。
SETTINGS_TIMEOUT (0x4)
エンドポイントが SETTINGS フレームを送信したものの、適切な時間内にそのレスポンスを受信しませんでした。6.5.3節 (設定の同期) を参照してください。
STREAM_CLOSED (0x5)
エンドポイントが half-closed のストリームからフレームを受信しました。
FRAME_SIZE_ERROR (0x6)
エンドポイントが不正なサイズのフレームを受信しました。
REFUSED_STREAM (0x7)
エンドポイントがアプリケーション処理をする前にストリームを拒否しました (8.1.4節)。
CANCEL (0x8)
ストリームが必要がなくなったことを示すために、エンドポイントが使用します。
COMPRESSION_ERROR (0x9)
エンドポイントがコネクションのためのヘッダー圧縮コンテキストの維持に失敗しました。
CONNECT_ERROR (0xa)
CONNECT リクエスト (8.3節) に応じて確立された接続が、リセットまたは不正終了しました。
ENHANCE_YOUR_CALM (0xb)
ピアが過剰な負荷を発生させる可能性がある挙動をしたことをエンドポイントが検出しました。
INADEQUATE_SECURITY (0xc)
下位のトランスポートの機能が最低限のセキュリティ要件 (9.2節) を満たしていません。
HTTP_1_1_REQUIRED (0xd)
エンドポイントは HTTP/2 の代わりに HTTP/1.1 の使用を要求しました。

不明または未対応のエラーコードは、特別な反応を引き起こしてはなりません (MUST NOT)。これらは、実装では INTERNAL_ERROR と等価として扱ってもよいものとします (MAY)。

8. HTTP メッセージの交換

HTTP/2 は現在使用している HTTP に可能な限り互換であることを目指しています。これは、アプリケーションの観点から、プロトコルの特徴が大きく変わらないことを意味します。これを実現するために、全てのアプリケーションのリクエストとレスポンスヘッダーのセマンティクスは維持され、転送される構文のセマンティクスのみが変更されます。

したがって、HTTP/1.1 セマンティクスの仕様や要件、コンテンツ [RFC7231]、条件付きリクエスト [RFC7232]、範囲リクエスト [RFC7233]、キャッシュ [RFC7234] と認証 [RFC7235] は HTTP/2 に適用できます。HTTP や HTTPS URI スキームのような HTTP/1.1 メッセージ構文とルーティング [RFC7230] の一部も HTTP/2 に適用できますが、このプロトコル専用のセマンティクスの表現は、以降の節で定義されます。

8.1. HTTP リクエスト/レスポンスの交換

クライアントは、過去に使用していないストリームID (5.1.1節) を使用して、新しいストリーム上で HTTP リクエストを送信します。サーバーはリクエストと同一のストリーム上で HTTP レスポンスを送信します。

HTTP メッセージ (リクエストやレスポンス) はそれぞれ以下のフレームから成ります:

  1. レスポンスに限り、情報提供 (1xx) HTTP レスポンスのメッセージヘッダー ([RFC7230]、3.2節と [RFC7231]、6.2節) を含む0個以上の HEADERS フレーム (それぞれに続く0個以上の CONTINUATION フレーム)
  2. メッセージヘッダー ([RFC7230]、3.2節) を含む1つの HEADERS フレーム (それに続く0個以上の CONTINUATION フレーム)
  3. ペイロードボディ ([RFC7230]、3.3節) を含む、0個以上の DATA フレーム
  4. 必要に応じて、トレイラー部 ([RFC7230]、4.1.2節) を含む1つの HEADERS フレームと、それに続く0個以上の CONTINUATION フレーム

一連のフレームの最後のフレームは END_STREAM フラグを持ちます。END_STREAM フラグを持つ HEADERS フレームの後には、残りのヘッダーブロックの一部を転送する CONTINUATION フレームが続く可能性があることに注意してください。

(任意のストリームの) その他のフレームは、HEADERS フレームとその後に続く可能性のある CONTINUATION フレームの間に存在してはいけません (MUST NOT)。

HTTP/2 はメッセージペイロードの転送に DATA フレームを使用します。[RFC7230] の4.1節で定義されている "chunked" 転送エンコーディングは HTTP/2 では使用してはいけません (MUST NOT)。

Trailing ヘッダーフィールドはストリームを終了するヘッダーブロックにより転送されます。このようなヘッダーブロックは、END_STREAM フラグを持つ HEADERS フレームで始まり、0個以上の CONTINUATION フレームが続く、一連のフレームです。ストリームを終了しない最初のヘッダーブロックの後のヘッダーブロックは HTTP リクエストやレスポンスの一部ではありません。

HEADERS フレーム (とそれに関連付けられた CONTINUATION フレーム) は、ストリームの最初と最後でのみ送信できます。最終的な (Informational でない) ステータスコードを受信した後に、END_STREAM フラグが設定されていない HEADERS フレームを受信したエンドポイントは、対応するリクエストやレスポンスを不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)。

HTTP リクエスト/レスポンスの交換は1つのストリームを完全に消費します。リクエストは、ストリームを "open" 状態にする HEADERS フレームで開始されます。そのリクエストは、ストリームをクライアントでは "half-closed (local)" 状態に、サーバーでは "half-closed (remote)" 状態にする END_STREAM が設定されたフレームで終了します。レスポンスは HEADERS フレームで開始され、ストリームを "closed" 状態にする END_STREAM が設定されたフレームで終了します。

HTTP レスポンスは、END_STREAM フラグが設定されたフレーム (ヘッダーブロックの完成に必要な CONTINUATION フレームを含む) をサーバーが送信、またはクライアントが受信した時に完了します。レスポンスが未送信または未受信のリクエストの一部に依存しない場合、サーバーは、クライアントがリクエストを完全に送信する前に、完全なレスポンスを送信できます。このような場合、サーバーは、完全なレスポンス (例: END_STREAM フラグが設定されたフレーム) の送信後に NO_ERROR のエラーコードと共に RST_STREAM を送信することで、クライアントにリクエストの送信中止を要求してもよいものとします (MAY)。クライアントは、この他の理由においては常に自身の裁量でレスポンスを破棄できますが、このような RST_STREAM を受信した結果としてのレスポンスは破棄してはいけません (MUST NOT)。

8.1.1. HTTP/2 からのアップグレード

HTTP/2 は 101 (Switching Protocols) 情報提供ステータスコード ([RFC7231]、6.2.2節) の対応を削除します。

101 (Switching Protocols) のセマンティクスは多重化されたプロトコルには適用されません。代替プロトコルは HTTP/2 の使用をネゴシエートするのに使用するものと同じメカニズムを使用できます。

8.1.2. HTTP ヘッダーフィールド

HTTP ヘッダーフィールドは一連のキーと値のペアとして情報を転送します。登録済み HTTP ヘッダーのリストについては、<https://www.iana.org/assignments/message-headers> で整備されている "メッセージヘッダーフィールドレジストリ" を参照してください。

HTTP/1.x のようにヘッダーフィールド名は、大文字小文字を区別しない方法で比較される ASCII の文字列です。しかしながら HTTP/2 では、ヘッダーフィールド名はエンコード前に小文字に変換されなければなりません (MUST)。大文字のヘッダーフィールド名を含むリクエストやレスポンスは不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)。

8.1.2.1. 擬似ヘッダーフィールド

HTTP/1.x では、対象 URI とリクエストのメソッド、そしてレスポンスのステータスコードを転送するためにメッセージ start-line ([RFC7230]、3.1節) を使用していましたが、HTTP/2 では、':' 文字 (ASCII 0x3a) で始まる特殊な擬似ヘッダーフィールドを使用します。

擬似ヘッダーフィールドは HTTP ヘッダーフィールドではありません。エンドポイントはこの文書で定義されたもの以外の擬似ヘッダーフィールドを生成してはいけません (MUST NOT)。

擬似ヘッダーフィールドは、それらが定義されたコンテキストにおいてのみ有効です。リクエストのために定義された擬似ヘッダーフィールドは、レスポンスに使用してはいけません (MUST NOT)。同様に、レスポンスのために定義された擬似ヘッダーフィールドは、リクエストに使用してはいけません (MUST NOT)。擬似ヘッダーフィールドはトレイラーに使用してはいけません (MUST NOT)。エンドポイントは、未定義や無効な擬似ヘッダーフィールドを含むリクエストやレスポンスを不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)。

全ての擬似ヘッダーフィールドは、ヘッダーブロックにおいて通常のヘッダーフィールドよりも前に出現しなければなりません (MUST)。ヘッダーブロックにおいて通常のヘッダーフィールドよりも後に擬似ヘッダーフィールドを含むリクエストやレスポンスは、不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)

8.1.2.2. 接続固有ヘッダーフィールド

HTTP/2 は接続固有ヘッダーフィールドを示す Connection ヘッダーフィールドを使用しません。このプロトコルでは、接続固有のメタデータは他の方法で転送されます。エンドポイントは接続固有ヘッダーフィールドを含む HTTP/2 メッセージを生成してはいけません (MUST NOT)。接続固有ヘッダーフィールドを含む全てのメッセージは不正な形式 (8.1.2.6節) として扱われなければなりません (MUST)。

これに関する唯一の例外は、TE ヘッダーフィールドです。このフィールドは HTTP/2 リクエストに存在してもよい (MAY) ものとしていますが、"trailers" 以外の値を含んではいけません (MUST NOT)。

このことは、HTTP/1.x メッセージを HTTP/2 に変換する中継者が、Connection ヘッダーフィールドとそこで指定されたヘッダーフィールドを削除する必要があることを意味します。このような中継者は、Connection ヘッダーフィールドで指定されていなくても Keep-Alive、Proxy-Connection、Transfer-Encoding、そして Upgrade といった接続に固有な他のヘッダーフィールドを削除すべきです (SHOULD)。

注: HTTP/2 は他のプロトコルへのアップグレードに意図的に対応しません。3章で説明したハンドシェイク方式は、他のプロトコルの使用をネゴシエートするのに十分と考えられています。

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

以下の擬似ヘッダーフィールドは HTTP/2 リクエストのために定義されます:

全ての HTTP/2 リクエストは、CONNECT リクエスト (8.3節) である場合を除き、":method"、":scheme"、そして ":path" 擬似ヘッダーフィールドに有効な値を1つ含まなければなりません (MUST)。これらの擬似ヘッダーフィールドが省略された HTTP リクエストは不正な形式 (8.1.2.6節) です。

HTTP/2 では、HTTP/1.1 のリクエスト行に含まれるバージョン識別子を伝達する方法を定義しません。

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

":status" 擬似ヘッダーフィールドは、HTTP/2 レスポンスの HTTP ステータスコードフィールド ([RFC7231]、6節) を伝達するために定義されます。この擬似ヘッダーフィールドは全てのレスポンスに含まれなければなりません (MUST) が、これを含まないレスポンスは不正な形式 (8.1.2.6節) です。

HTTP/2 では、HTTP/1.1 のステータス行に含まれるバージョンや理由フレーズを伝達する方法を定義しません。

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

Cookie ヘッダーフィールド [COOKIE] はクッキーペア (もしくは "crumb") の区切りにセミコロン ";" を使用します。このヘッダーフィールドは、HTTP におけるリスト構造のルール ([RFC7230]、3.2.2節) には従っていません。そしてそれは、クッキーペアが異なる名前-値ペアに分割されることを妨げています。 このため個々のクッキーペアが更新されると、圧縮効率が著しく低下します。

圧縮効率を向上させるために、Cookie ヘッダーフィールドは1つ以上のクッキーペアを持つ複数のヘッダーフィールドに分割してもよいものとします (MAY)。ヘッダー圧縮を解凍した後に、複数の Cookie ヘッダーフィールドが存在する場合、HTTP/1.1 コネクションや一般的なサーバーアプリケーションなどの非 HTTP/2 コンテキストに渡す前に、0x3B、0x20 (ASCII 文字の "; ") を2つのオクテットの区切り文字として使用し、それらは1つの文字列に結合されなければなりません (MUST)。

したがって、以下の Cookie ヘッダーフィールドの2つのリストは意味的に等しくなります。

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

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

8.1.2.6. 不正な形式のリクエストやレスポンス

不正な形式のリクエストやレスポンスとは、有効な一連の HTTP/2 フレームである一方で、無関係なフレームや禁止されたヘッダーフィールドが存在したり、必須のヘッダーフィールドが存在しない、大文字のヘッダーフィールド名が含まれているなどの理由で無効になるものです。

ペイロードボディを持つリクエストやレスポンスは content-length ヘッダーフィールドを含むことができます。ボディを構成する DATA フレームペイロードの長さの合計が content-length ヘッダーフィールドの値と等しくない場合、リクエストやレスポンスは不正な形式になります。[RFC7230]、3.3.2節で述べられているような、ペイロードを持たないように定義されたレスポンスは、DATA フレームに内容が含まれていない場合であっても、値が0でない content-length ヘッダーフィールドを持つことができます。

HTTP のリクエストやレスポンスを処理する中継者 (つまり、トンネルとして機能しない全ての中継者) は、不正な形式のリクエストやレスポンスを転送してはいけません (MUST NOT)。不正な形式のリクエストやレスポンスが検出された場合、PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

サーバーは不正な形式のリクエストについて、ストリームを終了したり、リセットをする前に HTTP レスポンスを送信してもよいものとします (MAY)。クライアントは不正な形式のレスポンスを受け入れてはいけません (MUST NOT)。これらの要件は、HTTP に対する一般的な攻撃手法の一部からの保護を意図していることに注意してください。寛容であることは、実装の脆弱性を晒すことにもなるため、用心深く、厳格でなければなりません。

8.1.3. 例

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

リクエストヘッダーフィールドを含み、ペイロードボディがない HTTP GET リクエストは、リクエストヘッダーフィールドのシリアライズされたブロックを含む、HEADERS フレームとそれに続く0個以上の 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
                                   :path = /resource
                                   host = example.org
                                   accept = image/jpeg

同様に、レスポンスヘッダーフィールドを含むレスポンスも、レスポンスヘッダーフィールドのシリアライズされたブロックを含む、HEADERS フレーム (とそれに続く0個以上の 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 ...

リクエストヘッダーフィールドとペイロードデータを含む HTTP POST リクエストは、リクエストヘッダーフィールドを含む 1つの HEADER フレームとその後に続く、0個以上の 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
                                     :path = /resource
{binary data}                        :scheme = https

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

                                 DATA
                                   + END_STREAM
                                 {binary data}

任意のヘッダーフィールドを提供するデータは、ヘッダーブロックフラグメントに分割されることに注意してください。この例における、ヘッダーフィールドのフレームへの割り当ては、単純な説明向のものになっています。

ヘッダーフィールドとペイロードデータを含むレスポンスは、1つ以上の HEADERS フレームとそれに続く、0個以上の 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}

101 以外の 1xx ステータスコードを使用する情報提供レスポンスは HEADERS フレームとそれに続く0個以上の CONTINUATION フレームとして転送されます。

Trailing ヘッダーフィールドは、リクエストやレスポンスヘッダーブロックと、全ての DATA フレームが送信された後に、ヘッダーブロックとして送信されます。トレイラーヘッダーブロックを開始する HEADERS フレームには END_STREAM フラグが設定されます。

以下の例は、Expect ヘッダーフィールドに "100-continue" トークンを含むリクエストに対するレスポンスとして送信される 100 (Continue) ステータスコードと Trailing ヘッダーフィールドの両方を含む例です。

HTTP/1.1 103 BAR                 HEADERS
Extension-Field: bar       ==>     - END_STREAM
                                   + END_HEADERS
                                     :status = 103
                                     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-length = 123
123                                  content-type = image/jpeg
{binary data}                        trailer = Foo
0
Foo: bar                         DATA
                                   - END_STREAM
                                 {binary data}

                                 HEADERS
                                   + END_STREAM
                                   + END_HEADERS
                                     foo: bar

8.1.4. HTTP/2 におけるリクエストの信頼性向上メカニズム

HTTP/1.1 においてエラーが発生した際は、エラーの原因を特定する手段が存在しないため、HTTP クライアントは冪等でないリクエストの再試行をおこなうことができませんでした。もしリクエストが再試行されると、エラーが発生する前に進めたサーバー処理が望ましくない結果になってしまう可能性があるでしょう。

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

処理されなかったリクエストは失敗ではありません。クライアントはそのリクエストが冪等でないメソッドであっても、それらを自動的に再施行してもよいものとします (MAY)。

ストリームが処理されていないという事をサーバーが保証できない限り、サーバーはそのことを示してはいけません (MUST NOT)。ストリーム上にあるフレームがアプリケーションレイヤーに渡された場合、そのストリームに対して REFUSED_STREAM を使用してはいけません (MUST NOT)。そして GOAWAY フレームは、アプリケーションレイヤーに渡されたフレームのストリームID以上の値を含まなければなりません (MUST)。

これらのメカニズムに加え、PING フレームはクライアントがコネクションを簡単にテストする方法を提供します。いくつかのミドルボックス (例として、ネットワークアドレス変換器やロードバランサーなどがあります) が静かにコネクションを破棄するため、アイドルとして残っているコネクションは破壊されることがあります。PING フレームは、クライアントがリクエストを送信することなく、コネクションが有効かどうかを安全にテストすることを可能にします。

8.2. サーバープッシュ

HTTP/2 では、クライアントが事前に開始したリクエストに関連するレスポンスを (対応する "予約" リクエストを加えて)、サーバーがクライアントに先行送信 (または "プッシュ") することを可能にします。最初のリクエストのレスポンスをクライアントが完全に処理するために、関連するレスポンスを用意する必要があることをサーバーが知っている場合にこれは有用です。

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

予約リクエストは、キャッシュ可能 ([RFC7231]、4.2.3節) でなければならず (MUST)、また安全 ([RFC7231]、4.2.1節) でなければなりません (MUST)。また、リクエストボディを含んではいけません (MUST NOT)。キャッシュ可能でなかったり、安全であると知られていない、またはリクエストボディの存在を示す予約リクエストを受信したクライアントは、PROTOCOL_ERROR のストリームエラー (5.4.2節) と共に予約ストリームを初期化しなければなりません (MUST)。クライアントが新しく定義されたメソッドを安全であると認識できない場合、予約ストリームは初期化される可能性があることに注意してください。

キャッシュ可能 ([RFC7234]、3章) なプッシュレスポンスは、HTTP キャッシュを実装しているクライアントにより保存されます。予約済みストリームIDにより識別されるストリームが open 状態の間、プッシュレスポンスは (例えば "no-cache" キャッシュレスポンスディレクティブ ([RFC7234]、5.2.2節) が存在する場合のように) オリジンサーバーにおいて正常に検証されたとみなされます。

キャッシュ可能でないプッシュレスポンスは HTTP キャッシュにより保存されてはいけません (MUST NOT)。それらは、個々にアプリケーションで利用されてもよいものとします (MAY)。

サーバーは、":authority" 擬似ヘッダーフィールドに、サーバーが権限を持つ値 (10.1節) を含めなければなりません (MUST)。クライアントはサーバーが権限を持たない PUSH_PROMISE を、PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

中間機器はサーバーからのプッシュを受信でき、クライアントへそれらを転送するかを選択できます。言い換えれば、プッシュされる情報をどのように使用するかは中間機器次第です。同様に、中間機器はサーバーによる動作なしに、クライアントへの追加のプッシュを生成する可能性があります。

クライアントはプッシュすることはできません。したがって、サーバーは PUSH_PROMISE フレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません。クライアントは、PROTOCOL_ERROR のコネクションエラー (5.4.1節) としてメッセージを扱うことで、SETTINGS_ENABLE_PUSH 設定を 0 以外の値に変更しようとする試みを拒否しなければなりません (MUST)。

8.2.1. プッシュリクエスト

サーバープッシュは、リクエストに対してサーバーがレスポンスを返すことと意味的に等しくなります。この時のリクエストはサーバーにより PUSH_PROMISE フレームとして送信されます。

PUSH_PROMISE フレームは、サーバーがリクエストに予想するリクエストヘッダーフィールドの完全なセットからなるヘッダーブロックを含みます。リクエストボディを含むリクエストのレスポンスをプッシュすることは不可能です。

プッシュリクエストは、常にクライアントからのリクエストに明確に関連付けられます。サーバーから送信される PUSH_PROMISE フレームは、明示的なリクエストのストリーム上に送信されます。PUSH_PROMSE フレームは予約済みストリームIDも含みます。それはサーバーで使用可能なストリームIDから選択されています (5.1.1節)。

PUSH_PROMISE のヘッダーフィールドと、その後に続く CONTINUATION フレームは、正しく完全なリクエストヘッダーフィールドのセット(8.1.2.3節) でなければなりません (MUST)。サーバーは、":method" ヘッダーフィールドに安全でキャッシュ可能なメソッドを含めなければなりません (MUST)。クライアントが、正しく完全なヘッダーフィールドのセットを含んでいない、または ":method" ヘッダーフィールドのメソッドが安全でない PUSH_PROMISE を受信した場合は、PROTOCOL_ERROR のストリームエラー (5.4.2節) として応答しなければなりません (MUST)。

サーバーは、予約済みレスポンスに関連するどんなフレームを送信するよりも前に、PUSH_PROMISE フレーム (6.6節) を送信すべきです (SHOULD)。これは、クライアントが PUSH_PROMISE フレームを受信する前に、リクエストを発行するといった競合を防ぎます。

例えば、サーバーが複数の画像ファイルへのリンクが埋め込まれた文書のリクエストを受信し、サーバーがそれらの画像をクライアントにプッシュすることを選択したとします。このような場合、その画像リンクを含む DATA フレームよりも前に PUSH_PROMISE を送信することで、クライアントがそれらの埋め込みリンクを見つける前にリソースがプッシュされるのを確認できることを保証します。同様に、ヘッダーブロックが参照するリクエスト (例えば、Link ヘッダーフィールドなど) をサーバーがプッシュする場合は、ヘッダーブロックを送信する前に PUSH_PROMISE を送信することで、クライアントがそれらのリソースにリクエストしないことを保証します。

PUSH_PROMISE フレームはクライアントから送信してはいけません (MUST NOT)。

PUSH_PROMISE フレームは、クライアントが開始したストリームへのレスポンスにおいてサーバーから送信されますが、そのストリームはサーバーにおいて "open" または "half-closed (remote)" のいずれかの状態でなければなりません (MUST)。PUSH_PROMISE フレームは、レスポンスを構成するフレームの間に存在しますが、1つのヘッダーブロックを構成する HEADERS と CONTINUATION フレームの間に入れ込むことはできません。

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

8.2.2. プッシュレスポンス

PUSH_PROMISE フレームを送信後、サーバーは予約されたIDのストリーム上でレスポンス (8.1.2.4節) と同じ様にプッシュレスポンスを送信し始めることができます。サーバーは、HTTP レスポンスを送信するためにこのストリームを使用します。それは8.1節で定義された一連のシーケンスを使用しています。このストリームは、初期の HEADERS フレームが送信された後、クライアントに対して "half-closed" 状態 (5.1節) に変わります。

クライアントが PUSH_PROMISE フレームを受信し、プッシュレスポンスを受け入れることを選択すると、クライアントは予約済みストリームが終了するまで、そのレスポンスに対してリクエストを発行すべきではありません (SHOULD NOT)。

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

クライアントは、サーバーから同時にプッシュされるレスポンスの数を制限するために SETTINGS_MAX_CONCURRENT_STREAMS 設定を使用できます。値が0に設定された SETTINGS_MAX_CONCURRENT_STREAMS を告知することで、サーバーが必要とするストリームの生成を防ぎ、サーバープッシュを無効にします。これは、サーバーに PUSH_PROMISE の送信を禁止するわけではありません。その場合、クライアントは必要のない予約済みのストリームをリセットする必要があります。

プッシュレスポンスを受信するクライアントは、サーバーが信頼できるか (10.1節)、プッシュレスポンスを提供したプロキシが対応するリクエストを設定したかを検証しなければなりません (MUST)。例えば、DNS-ID や Common Name が "example.com" の証明書を提供するサーバーが、"https://www.example.org/doc" のレスポンスをプッシュすることは認められていません。

PUSH_PROMISE レスポンスのストリームは HEADERS フレームと共に始まり、直ちにそのストリームをサーバー上では "half-closed (remote)" 状態に、クライアント上では "half-closed (local)" 状態にします。そして、ストリームを "closed" 状態にする END_STREAM が設定したフレームにより終了します。

注: クライアントはサーバープッシュに対して END_STREAM フラグを設定したフレームを送信してはいけません。

8.3. CONNECT メソッド

HTTP/1.x において、擬似メソッド CONNECT ([RFC7231]、4.3.6節) は HTTP 接続をリモートホストへのトンネルに変換するために使用されます。CONNECT は、"https" リソースをやりとりする目的でオリジンサーバーと TLS セッションを確立するために、主に HTTP プロキシと共に使用されます。

HTTP/2 における CONNECT メソッドは、同様にリモートホストへの単一の HTTP/2 ストリーム上にトンネルを確立するために使用されます。HTTP ヘッダーフィールドのマッピングは、8.1.2.3節 ("リクエスト擬似ヘッダーフィールド") に定義されたように動作します。一部のヘッダーについては、具体的には以下のようになります。

これらの制限に適合しない CONNECT リクエストは、不正な形式 (8.1.2.6) になります。

CONNECT に対応するプロキシは、":authority" 擬似ヘッダーフィールドに指定されたサーバーと TCP 接続 [TCP] を確立します。コネクションの確立に成功すると、[RFC7231]、4.3.6節で定義されるように、プロキシは 2xx ステータスコードを含む HEADERS フレームをクライアントに送信します。

両方のピアによる初期 HEADERS フレームの送信後、その後に続く全ての DATA フレームは TCP 接続上に送信されたデータに相当します。クライアントから送信された DATA フレームのペイロードは、プロキシにより TCP サーバーに転送されます。TCP サーバーから受信したデータは、プロキシにより DATA フレームに変換されます。DATA 以外のフレームタイプやストリームの管理フレーム (RST_STREAM や WINDOW_UPDATE、PRIORITY) を接続ストリームには送信してはいけません (MUST NOT)。また、それらのフレームを受信した場合は、ストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

TCP 接続はどちらのピアからも終了できます。DATA フレームの END_STREAM フラグは TCP_FIN ビットに相当するフラグとして扱われます。クライアントには END_STREAM フラグが設定されたフレームの受信後に、END_STREAM フラグを設定した DATA フレームの送信が期待されます。END_STREAM フラグが設定された DATA フレームを受信したプロキシは、最後の TCP セグメントに FIN ビットを設定したデータを送信します。FIN ビットが設定された TCP セグメントを受信したプロキシは、END_STREAM フラグを設定した DATA フレームを送信します。なお、最後の TCP セグメントや DATA フレームは空にすることが可能であることに注意してください。

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

9. 追加の HTTP 要件/配慮

この章では、相互運用性を向上する HTTP プロトコルの属性や、既知のセキュリティ脆弱性に対象する方法、実装差異が起こる可能性を減らす方法などについて説明します。

9.1. コネクション管理

HTTP/2 接続は持続的です。最高のパフォーマンスを得るために、(例えば、ユーザーが特定の Web ページから移動してしまった時など) サーバーとの通信がこれ以上は不要だと判断したり、サーバーがコネクションを終了するまでクライアントはコネクションを終了しないよう期待されます。

クライアントは、URI 由来のホストや、選択された代替サービス [ALT-SVC]、設定されたプロキシなどから与えられたホストとポートのペアに対して同時に2つ以上の HTTP/2 接続を開始すべきではありません (SHOULD NOT)。

クライアントは、利用可能なストリームID空間 (5.1.1節) が少なくなったコネクションの交換や TLS 接続用の鍵情報の更新、エラーが発生したコネクションの交換 (5.4.1節) のために、追加のコネクションを生成できます。

クライアントは、異なる Server Name Indication [TLS-EXT] の値が使われている同一のIPアドレスとTCPポートに対してや、異なる TLS クライアント証明書を提供するために、複数の接続を開始してもよいものとします (MAY)。しかし、同一の設定に対して複数の接続を生成することは避けるべきです (SHOULD)。

サーバーは、オープンしたコネクションを可能な限り長く維持することが推奨されますが、必要に応じてアイドル状態のコネクションを終了することが認められています。いずれかのエンドポイントがトランスポート層の TCP 接続の終了を選択した時、終了側のエンドポイントは最初に GOAWAY (6.8節) フレームを送信すべきです (SHOULD)。その結果、両方のエンドポイントは先に送信したフレームが処理されて緩やかに完了したのか、それとも残りの必要なタスクが中断されたのかを期待通りに確認できます。

9.1.1. コネクションの再利用

オリジンサーバーに対するコネクションは、直接接続や CONNECT メソッド (8.3節) を使用して作成されたトンネルを通じての接続かに関わらず、複数の異なる authority コンポーネントの URI に対するリクエストの送信に再利用されてもよいものとします (MAY)。コネクションはオリジンサーバーが信頼できる (10.1節) 限り、再利用できます。TLS のない TCP 接続では、これは同一のIPアドレスとして解決されるホストに依存します。

"https" リソースでのコネクションの再利用は、さらに URI のホストに対する有効な証明書を持つかどうかに依存します。サーバーから提供された証明書は、その URI のホストに対して新しい TLS 接続を確立する際に、クライアントが行ういかなる検証に対して満足するものでなければなりません (MUST)。

オリジンサーバーは、URI の authority に対して有効となる複数の "subjectAltName" 属性や、ワイルドカードの名前と共に証明書を提示するかもしれません。例えば、"subjectAltName" が "*.example.com" の証明書は、"https://a.example.com/" や "https://b.example.com/" で始まる URI へのリクエストに同じコネクションの使用を認めるかもしれません。

一部のデプロイにおいては、複数のオリジンに対するコネクションの再利用が、誤ったオリジンサーバーへのリクエストの送信につながる可能性があります。例えば TLS の終端が、オリジンサーバーの選択に TLS Server Name Indication (SNI) [TLS-EXT] を使用するミドルボックスによっておこなわれている可能性があります。これは、信頼できないサーバーであるにも関わらず、リクエスト対象として意図していないサーバーに対して、クライアントが機密情報を送信してしまう可能性があることを意味します。

クライアントにおけるコネクションの再利用を望まないサーバーは、リクエストに対して 421 (Misdirected Request) をレスポンスとして返すことで、リクエストの権限がないことを示すことができます。

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

9.1.2. 421 (Misdirected Request) ステータスコード

421 (Misdirected Request) ステータスコードは、レスポンスを生成できないサーバーにリクエストを送信したことを示します。これは、リクエスト URI に含まれる scheme と authority の組み合わせに対するレスポンスを生成するように設定されていないサーバーから送信される可能性があります。

サーバーから 421 (Misdirected Request) レスポンスを受信したクライアントは、リクエストメソッドが冪等であるかどうかに関わらず、異なるコネクションを通じてリクエストを再施行してもよいものとします (MAY)。これは、コネクションが再利用 (9.1.1節) されていたり、代替サービス ([ALT-SVC]) が選択されていたりする場合でも可能です。

このステータスコードは、プロキシから生成されてはいけません (MUST NOT)。

明示的なキャッシュ制御 ([RFC7234]、4.2.2節)や、メソッドの定義により示されない限り、421 レスポンスはデフォルトでキャッシュ可能です。

9.2. TLS の機能の利用

HTTP/2 の実装は、TLS 上の HTTP/2 に対して TLS バージョン1.2 [TLS12] 以上を使用しなければなりません (MUST)。[TLSBCP] にある TLS の一般的な利用ガイダンスに即すべきであり (SHOULD)、加えて HTTP/2 特有の制限もあります。

TLS の実装は、TLS の Server Name Indication (SNI) [TLS-EXT] 拡張に対応しなければなりません (MUST)。HTTP/2 クライアントは、TLS ネゴシエーションの際に対象のドメイン名を指示しなければなりません (MUST)。

TLS 1.3 以上でネゴシエートする HTTP/2 のデプロイメントに求められるのは、SNI 拡張のサポートとその使用のみです。TLS 1.2 のデプロイメントは次の節の要件の対象になります。実装には適合する初期値の提供が推奨されますが、デプロイメントが最終的にこれを遵守する責任があることと認識されます。

9.2.1. TLS 1.2 の機能

この節では、HTTP/2 で使用可能な TLS 1.2 の機能セットの制限について述べます。デプロイメントの制限により、これらの制限が満たされない場合であっても、TLS ネゴシエーションを失敗できないかもしれません。エンドポイントは、これらの TLS 要件が満たされない HTTP/2 コネクションを、INADEQUATE_SECURITY のコネクションエラー (5.4.1節) と共に直ちに終了してもよいものとします (MAY)。

TLS 1.2 上の HTTP/2 のデプロイメントは圧縮を無効にしなければなりません (MUST)。TLS 圧縮は本来はそうなるべきではない情報の漏洩 [RFC3749] につながります。HTTP/2 は圧縮機能を提供しているため、一般的な圧縮は不要です。その圧縮機能は、よりコンテキストに配慮しており、それ故にパフォーマンスや安全性、その他の点から見ても利用が適切であると思われます。

TLS 1.2 上の HTTP/2 のデプロイメントは再ネゴシエーションを無効にしなければなりません (MUST)。エンドポイントは TLS 再ネゴシエーションを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。再ネゴシエーションを無効にすると、使用する暗号スイートに暗号化できるメッセージ数の上限があるため、コネクションを長期に渡って使用できなくなる可能性があることに注意してください。

エンドポイントは、ハンドシェイクにおいて提示するクライアント証明書の機密保護のためには、再ネゴシエーションを使用してもよいものとします (MAY)。しかし、いかなる再ネゴシーエションも、コネクションプリフェイスの送信前におこなわなければなりません (MUST)。サーバーは、コネクションを確立した後すぐに再ネゴシエーション要求がされた場合は、クライアント証明書を要求すべきです (SHOULD)。

これは実質的に、特定の保護されたリソースに対するリクエストのレスポンスにおける再ネゴシエーションの使用を防止します。将来の仕様では、このユースケースのための手法が規定されるかもしれません。また、サーバーは、クライアントに再ネゴシエーションをサポートするプロトコルを使用させるために HTTP_1_1_REQUIRED のエラー (5.4節) を使用するかもしれません。

実装は、一時的な Diffie-Hellman (DHE) [TLS12] の暗号スイートに対しては最低でも2048ビット、一時的な楕円暗号 (ECDHE) [RFC4492] の暗号スイートに対しては最低でも224ビットの、一時的な鍵交換の大きさをサポートしなければなりません (MUST)。クライアントは DHE の大きさとして4096ビットまで受け入れなければなりません (MUST)。エンドポイントは、この制限よりも小さい鍵サイズのネゴシエーションを INADEQUATE_SECURITY のコネクションエラー (5.4.1節) として扱ってもよいものとします (MAY)。

9.2.2. TLS 1.2 の暗号スイート

TLS 1.2 上の HTTP/2 のデプロイメントは、暗号スイートブラックリスト (付録A) に記載された暗号スイートを使用すべきではありません (SHOULD NOT)。

エンドポイントは、ブラックリストの暗号スイートの1つでネゴシエートされた場合は、INADEQUATE_SECURITY のコネクションエラー (5.4.1節) を発生してもよいものとします (MAY)。ブラックリストの暗号スイートの使用を選択するデプロイメントは、潜在的なピアのセットがその暗号スイートを受け入れることが知られていない限り、コネクションエラーを引き起こす危険があります。

実装は、ブラックリストにない暗号スイートのネゴシエーションに反応して、このエラーを生成してはいけません (MUST NOT)。クライアントがブラックリストにない暗号スイートを提示してきた時は、その暗号スイートを HTTP/2 で使用するための準備をしなければなりません。

ブラックリストは TLS 1.2 が実装を必須としている暗号スイートを含みます。これは、TLS 1.2 のデプロイメントが許可された暗号スイートの共通集合を見出せない可能性があることを意味します。TLS ハンドシェイクの失敗を引き起こすこの問題を避けるために、TLS 1.2 を使う HTTP/2 の実装は、楕円曲線 P256 [FIPS186] を使用した TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] に対応しなければなりません (MUST)。

クライアントは、HTTP/2 をサポートしないサーバーへの接続を可能にするために、ブラックリストの暗号スイートのサポートを通知する可能性があることに注意してください。これにより、サーバーは HTTP/2 でブラックリストの暗号スイートと共に HTTP/1.1 を選択できます。しかしながら、これはアプリケーションプロトコルと暗号スイートが独立して選択された場合に、ブラックリストの暗号スイートと共に HTTP/2 がネゴシエートされる結果を生みます。

10. セキュリティへの配慮

10.1. サーバーの権限

HTTP/2 は、サーバーが対象のリソースの提供する権限があるかどうかを判定するために HTTP/1.1 の権限の定義に依存しています ([RFC7230]、9.1節)。"http" URI スキームではローカル名前解決、"https" スキームでは信頼されたサーバー識別子 ([RFC2818]、3章) にそれぞれ依存します。

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

クロスプロトコル攻撃では、攻撃者は異なるプロトコルを解釈するサーバーに対して、クライアントに最初のプロトコルでトランザクションを開始させます。これにより、攻撃者は第二のプロトコルの有効なトランザクションのように見えるトランザクションを開始できるかもしれません。Web コンテキストの機能と組み合わせることで、これはプライベートネットワーク内の不十分な保護下にあるサーバーと通信をするために使用できます。

HTTP/2 の ALPN 識別子と共に TLS ハンドシェイクを完了することは、クロスプロトコル攻撃に対して十分な保護になると考えられます。ALPN は他の TLS ベースのプロトコルへの攻撃を防ぎ、サーバーが HTTP/2 を処理するための前向きな意思表示を提供します。

TLS の暗号化は、攻撃者が平文プロトコル上でクロスプロトコル攻撃に使用するようなデータの制御を難しくします。

平文バージョンの HTTP/2 はクロスプロトコル攻撃に対する最低限の保護しか持ちません。コネクションプリフェイス (3.5節) は HTTP/1.1 サーバーを混乱させるように設計された文字列を含みますが、他のプロトコルに対する特別な保護を提供しません。クライアントコネクションプリフェイスに加えて、Upgrade ヘッダーフィールドを含む HTTP/1.1 リクエストの一部を無視する意思のあるサーバーは、クロスプロトコル攻撃にさらされる可能性があります。

10.3. 中継者カプセル化攻撃

HTTP/2 のヘッダーフィールドエンコードでは、HTTP/1.1 で使用されるインターネットメッセージ構文においては有効でないフィールド名の使用が可能です。不正なヘッダーフィールド名を含むリクエストやレスポンスは不正な形式 (8.1.2.6節) として扱われなければなりません (MUST)。したがって、中継者は不正なフィールド名を含む HTTP/2 リクエストやレスポンスを HTTP/1.1 メッセージに変換できません。

同様に、HTTP/2 は有効でないヘッダーフィールドの値も使用可能です。エンコード可能なほとんどの値では、ヘッダーフィールドの解析を変更しませんが、キャリッジリターン (CR, ASCII 0xd)、ラインフィード (LF, ASCII 0xa)、ヌル文字 (NUL, ASCII 0x0) は、逐語的に変換される場合に攻撃者により悪用される場合があります。ヘッダーフィールドの値に許可されていない文字を含むリクエストやレスポンスは、不正な形式 (8.1.2.6節) として扱われなければなりません (MUST)。有効な文字は [RFC7230]、3.2節の "field-content" ABNF ルールに定義されています。

10.4. プッシュレスポンスのキャッシュ

プッシュレスポンスとはクライアントからの明確なリクエストがないレスポンスです。リクエストは PUSH_PROMISE フレームによりサーバーから提供されます。

プッシュされたレスポンスのキャッシュは可能です。これはオリジンサーバーの Cache-Control ヘッダーフィールドが提供する指示に基づいておこなわれます。しかしながら、1つのサーバーホストが複数のテナントを提供する場合は、問題を引き起こす可能性があります。例えば、サーバーは複数のユーザーにそれぞれ URI 空間の一部を提供するかもしれません。

複数のテナントが同一サーバーの空間を共有する場合、サーバーは、テナントがリソースの権限を超えてキャッシュをプッシュしないことを保証しなければなりません (MUST)。これを強制しなければ、権限のあるテナントが提供する実際のキャッシュを上書きし、本来のキャッシュの外で提供されたキャッシュを、サーバーが提供することが可能になってしまいます。

権限のないオリジンサーバー (10.1節) のプッシュレスポンスを、キャッシュしたり使用してはいけません (MUST NOT)。

10.5. サービス拒否への配慮

HTTP/2 接続は、HTTP/1.1 接続よりも機能のためにより大きなリソースの割り当てを要求します。ヘッダー圧縮およびフロー制御の使用はより多くの状態を保持するため、リソースの割り当てに依存します。これらの機能の設定は、各機能に対するメモリーの割り当てを厳密に制限することを保証します。

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

処理能力については、状態容量ほどより効果的に保護することはできません。

SETTINGS フレームは、ピアに追加の処理時間を発生させるために悪用される可能性があります。これは、無意味な SETTINGS パラメーターの変更や複数の未定義のパラメーターの変更、同一フレームにおいて同じ設定を複数回変更をするなどで起こる可能性があります。同様に、WINDOW_UPDATE や PRIORITY フレームも、無駄なリソースの消費を引き起こすために悪用される可能性があります。

小さな、または空の大量のフレームは、ピアにフレームヘッダーの処理時間を消費させるために悪用される可能性があります。用途によっては、ストリームを終了させるために空の DATA フレームを送信するといった、正しい方法でも使われることに注意してください。

ヘッダー圧縮も、処理リソースを浪費するいくつかの機会を提供します。悪用の可能性についての詳細は [COMPRESSION] の7章を参照してください。

SETTINGS パラメーターの制限では、直ちに処理を軽減させることはできません。エンドポイントは、ピアが新しく設定しようとした制限値を超えられる状況に晒されたままです。特にコネクションが確立した直後は、サーバーによって設定される制限値がクライアントに通知されておらず、その場合明らかにプロトコル違反にならずに制限値を超えることが可能です。

SETTINGS の変更、小さなフレーム、ヘッダー圧縮といった、これらの全ての機能には正当な用途があります。これらの機能は、不必要に利用されたり、過剰に使用されたりした時に限り、負荷になります。

この動作を監視しないエンドポイントは、自分自身をサービス拒否攻撃のリスクに晒すことになります。実装は先に述べたような特徴を追跡し、それらの使用に制限を設定すべきです (SHOULD)。エンドポイントは、不審な挙動を ENHANCE_YOUR_CALM のコネクションエラー (5.4.1節) として扱ってもよいものとします (MAY)。

10.5.1. ヘッダーブロックサイズの制限

巨大なヘッダーブロック (4.3節) は、実装に大量の状態をコミットしてしまう可能性があります。ルーティングにおいて重要なヘッダーフィールドは、最終的な宛先へのヘッダーフィールドのストリーミングを妨げるようにヘッダーブロックの終わりに出現する可能性があります。こういった順序やキャッシュの正しさを保証するといった他の理由のために、エンドポイントはヘッダーブロック全体をバッファする必要があるかもしれないことを意味します。ヘッダーブロックのサイズに強い制限はないため、一部のエンドポイントではヘッダーフィールドに利用可能なメモリーに対して非常に多くのコミットを余儀なくされる可能性があります。

エンドポイントは、ヘッダーブロックのサイズに適用される可能性がある制限をピアに通知する、SETTINGS_MAX_HEADER_LIST_SIZE を使用できます。この設定はアドバイザリーなものであるため、エンドポイントは、そのリクエストやレスポンスが不正な形式として扱われるリスクを負って、制限を超えるヘッダーブロックを送信してもよいものとします (MAY)。この設定は接続固有であり、リクエストやレスポンスはより低い制限や不明な制限のあるホップに遭遇する可能性があります。中継者は、この問題を避けるために異なるピアが与えた値の通知を試みることができますが、そのようにする義務はありません。

許容できない巨大なヘッダーブロックを受信したサーバーは HTTP 431 (Request Header Fields Too Large) ステータスコード [RFC6585] を送信できます。クライアントは処理できないレスポンスを破棄できます。そのコネクションが終了されない限り、ヘッダーブロックは一貫性のあるコネクションの状態を維持するために処理されなければなりません (MUST)。

10.5.2. CONNECT の問題

TCP 接続の生成や維持と比較すると、ストリームの生成は少ないコストで行えるため、CONNECT メソッドは、プロキシに過剰な負荷を生むために使用される可能性があります。プロキシは送信用の TCP 接続が TIME_WAIT 状態のままであれば、CONNECT リクエストを転送するストリームの終了後も、TCP 接続のための一部のリソースを維持する可能性があります。したがって、プロキシは CONNECT リクエストにより消費されるリソースを制限するために、SETTINGS_MAX_CONCURRENT_STREAMS だけに依存するということはできません。

10.6. 圧縮の使用

圧縮は、攻撃者の制御下でかつ同じコンテキストで圧縮された場合に、攻撃者による機密データの復元を可能にします。HTTP/2 はヘッダーフィールド (4.3節) の圧縮を可能にします、以下の懸念は HTTP の compress content-coding ([RFC7231]、3.1.2.1節) の使用にも適用されます。

Web の特性を利用した圧縮に関する攻撃手法 (例: [BREACH]) もあります。攻撃者は様々な平文を含む複数のリクエストを誘発し、得られた各暗号テキストの長さを観測します。推測した機密が正しければ、その長さは短くなります。

保護されたチャンネル上で通信する実装は、各データソースに異なる圧縮辞書を使わない限り、機密と攻撃者が制御するデータの両方を含む内容を圧縮してはいけません (MUST NOT)。データソースが確実に判断できない場合は、圧縮を使用してはいけません (MUST NOT)。TLS で提供されているような汎用的なストリーム圧縮は HTTP/2 で使用してはいけません (MUST NOT) (9.2節)。

10.7. パディングの使用

HTTP/2 におけるパディングは、TLS [TLS12] により提供されるような一般的なパディングの置き換えを意図していません。冗長なパディングは逆効果にもなり得ます。正しいアプリケーションであるかどうかは、パディングされたデータに関する特別な情報を持つことによって決まります。

圧縮を利用した攻撃を軽減するための圧縮機能の無効化や制限は、対抗策としてのパディングよりも適しているかもしれません。

パッディングはフレームの内容の正確なサイズをわかりにくくするために使用でき、HTTP の特定の攻撃を軽減するために提供されます。例えば、攻撃者により制御されたプレーンテキストと機密データを含む圧縮コンテンツにおける攻撃 (例: [BREACH]) があります。

パディングの使用は、一見してわかる防御よりも結果的に弱い防御に終わることがあります。パディングは攻撃者が観察しなければならないフレームの数を増加させることで、長さ情報の推測をより困難にすることしかできません。不適切に実装されたパディングの構造は、簡単に破られる可能性があります。特に予測可能な分布によるランダムなパッディングは、非常にわずかな保護しか提供できません。同様に、パディングペイロードを固定サイズにすることは、ペイロードサイズをその固定サイズの境界を超えるように変更することで、情報を漏洩させます。これは攻撃者がプレーンテキストの制御が可能な場合に起こりえます。

中継者は DATA フレームのパディングを維持すべきです (SHOUD)。しかしながら、HEADERS や PUSH_PROMISE フレームのパディングは削除してもよいものとします (MAY)。中継者がフレームのパディングの量を変更する正当な理由は、パディングが提供する保護を改善することにあります。

10.8. プライバシーへの配慮

HTTP/2 のいくつかの特徴は、時間をかけてサーバーやクライアントの関連する動作を観測する機会を提供します。これには、設定の値やフロー制御ウインドウの管理方法、優先度がストリームに割り当てられる方法、攻撃に対する反応のタイミング、設定により制御される機能の扱いなどを含みます。

観測可能な振る舞いの違いを生み出す限り、[HTML5] の1.8節で定義されているように、特定クライアントのフィンガープリントの取得に使用することができてしまいます。

HTTP/2 が単一の TCP 接続を使用することで、サイト上でのユーザーの行動を相関させることが可能になります。異なるオリジンに対するコネクションの再利用は、それらのオリジンを超えての追跡を可能にします。

PING や SETTINGS フレームへの応答が直ちに求められるのは、これらのフレームがエンドポイントからピアへのレイテンシの計測に使用されるためです。これは、特定のシナリオでプライバシーへの影響があるかもしれません。

11. IANA への配慮

HTTP/2 を識別するための文字列は、[TLS-ALPN] に記載される "Application-Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリに登録されます。

この文書では、フレームタイプ、設定、そしてエラーコードのレジストリを制定します。これらの新しいレジストリは、新しい "Hypertext Transfer Protocol version 2 (HTTP/2) Parameters" の章に記述されます。

この文書では HTTP で使用する HTTP2-Settings ヘッダーフィールドと、421 (Misdirected Request) ステータスコードを登録します。

この文書では、コネクションプリフェイス (3.5節) との衝突を防ぐために HTTP で使用する "PRI" メソッドを登録します。

11.1. HTTP/2 識別文字列の登録

この文書は [TLS-ALPN] に記載される "Application-Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリにおける HTTP/2 識別子の登録 (3.3節) について制定します。

文字列 "h2" は TLS 上で使用される HTTP/2 を識別します。

Protocol
HTTP/2 over TLS
Identification Sequence
0x68 0x32 ("h2")
Specification
この文書

文字列 "h2c" は平文 TCP 上で使用される HTTP/2 を識別します。

Protocol
HTTP/2 over TCP
Identification Sequence
0x68 0x32 0x63 ("h2c")
Specification
この文書

11.2. フレームタイプレジストリ

この文書は HTTP/2 フレームタイプコードのレジストリを制定します。"HTTP/2 Frame Type" レジストリは8ビットの空間を管理します。"HTTP/2 Frame Type" レジストリは "IETF Review" や "IESG Approval" ポリシー [RFC5226] の下で、0x00 から 0xef までの値の範囲で運用されます。なお、0xf0 から 0xff までの値は実験的な利用のために予約されます。

このレジストリの新しいエントリーには、以下の情報が要求されます。

Frame Type
フレームタイプの名前またはラベル。
Code
フレームタイプに割り当てられる8ビットのコード。
Specification
フレームレイアウトや、フラグの値に基づいて条件付きで存在するフレームの任意の部分を含む、そのフレームタイプが使用するセマンティクスとフラグの概要が記述された仕様への参照。

以下のテーブルのエントリはこの文書で登録されます。

+---------------+------+--------------+
| Frame Type    | Code | Section      |
+---------------+------+--------------+
| DATA          | 0x0  | Section 6.1  |
| HEADERS       | 0x1  | Section 6.2  |
| PRIORITY      | 0x2  | Section 6.3  |
| RST_STREAM    | 0x3  | Section 6.4  |
| SETTINGS      | 0x4  | Section 6.5  |
| PUSH_PROMISE  | 0x5  | Section 6.6  |
| PING          | 0x6  | Section 6.7  |
| GOAWAY        | 0x7  | Section 6.8  |
| WINDOW_UPDATE | 0x8  | Section 6.9  |
| CONTINUATION  | 0x9  | Section 6.10 |
+---------------+------+--------------+

11.3. 設定レジストリ

この文書は HTTP/2 設定のレジストリを制定します。"HTTP/2 Settings" レジストリは16ビットの空間を管理します。"HTTP/2 Settings" レジストリは "Expert Review" ポリシー [RFC5226] の下で、0x0000 から 0xefff までの値の範囲で運用されます。なお、0xf000 から 0xffff までの値は実験的な利用のために予約されます。

新しい登録には、以下の情報を提供することが推奨されます。

Name
設定のシンボル名。設定名の指定は任意です。
Code
設定に割り当てられる16ビットのコード。
Initial Value
設定の初期値。
Specification
設定の使用を記載する仕様への任意の参照。

以下のテーブルのエントリはこの文書で登録されます。

+------------------------+------+---------------+---------------+
| Name                   | Code | Initial Value | Specification |
+------------------------+------+---------------+---------------+
| HEADER_TABLE_SIZE      | 0x1  | 4096          | Section 6.5.2 |
| ENABLE_PUSH            | 0x2  | 1             | Section 6.5.2 |
| MAX_CONCURRENT_STREAMS | 0x3  | (infinite)    | Section 6.5.2 |
| INITIAL_WINDOW_SIZE    | 0x4  | 65535         | Section 6.5.2 |
| MAX_FRAME_SIZE         | 0x5  | 16384         | Section 6.5.2 |
| MAX_HEADER_LIST_SIZE   | 0x6  | (infinite)    | Section 6.5.2 |
+------------------------+------+---------------+---------------+

11.4. エラーコードレジストリ

この文書は HTTP/2 エラーコードのレジストリを制定します。"HTTP/2 Error Code" レジストリは32ビットの空間を管理します。 "HTTP/2 Error Code" レジストリは、"Expert Review" ポリシー [RFC5226] に従って運用します。

エラーコードの登録には、そのエラーコードの説明を含める必要があります。専門のレビュアーは新規の登録が既存のエラーコードと重複可能かについて検討することを推奨します。既存の登録の使用は推奨されますが、義務ではありません。

新しい登録は以下の情報の提供が推奨されます。

Name
エラーコードの名前。 エラーコードの名前の指定は任意です。
Error Code
32ビットのエラーコードの値。
Description
エラーコードのセマンティクスの簡潔な説明、詳細な仕様が提供されていない場合はより長い説明。
Specification
エラーコードを定義する仕様への任意の参照。

以下のテーブルのエントリはこの文書で登録されます。

+---------------------+------+----------------------+---------------+
| Name                | Code | Description          | Specification |
+---------------------+------+----------------------+---------------+
| NO_ERROR            | 0x0  | Graceful shutdown    | Section 7     |
| PROTOCOL_ERROR      | 0x1  | Protocol error       | Section 7     |
|                     |      | detected             |               |
| INTERNAL_ERROR      | 0x2  | Implementation fault | Section 7     |
| FLOW_CONTROL_ERROR  | 0x3  | Flow-control limits  | Section 7     |
|                     |      | exceeded             |               |
| SETTINGS_TIMEOUT    | 0x4  | Settings not         | Section 7     |
|                     |      | acknowledged         |               |
| STREAM_CLOSED       | 0x5  | Frame received for   | Section 7     |
|                     |      | closed stream        |               |
| FRAME_SIZE_ERROR    | 0x6  | Frame size incorrect | Section 7     |
| REFUSED_STREAM      | 0x7  | Stream not processed | Section 7     |
| CANCEL              | 0x8  | Stream cancelled     | Section 7     |
| COMPRESSION_ERROR   | 0x9  | Compression state    | Section 7     |
|                     |      | not updated          |               |
| CONNECT_ERROR       | 0xa  | TCP connection error | Section 7     |
|                     |      | for CONNECT method   |               |
| ENHANCE_YOUR_CALM   | 0xb  | Processing capacity  | Section 7     |
|                     |      | exceeded             |               |
| INADEQUATE_SECURITY | 0xc  | Negotiated TLS       | Section 7     |
|                     |      | parameters not       |               |
|                     |      | acceptable           |               |
| HTTP_1_1_REQUIRED   | 0xd  | Use HTTP/1.1 for the | Section 7     |
|                     |      | request              |               |
+---------------------+------+----------------------+---------------+

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

この節は、HTTP2-Settings ヘッダーフィールドを "Permanent Message Header Field Names" レジストリ [BCP90] に登録します。

Header field name
HTTP2-Settings
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
この文書の3.2.1節
Related information
このヘッダーフィールドは、HTTP/2 クライアントの Upgrade に基づくネゴシエーションにのみ使用されます。

11.6. PRI メソッドの登録

この節は、"PRI" メソッドを "HTTP Method Registry" ([RFC7231]、8.1節) に登録します。

Method Name
PRI
Safe
Yes
Idempotent
Yes
Author/Change controller
IETF
Specification document(s)
この文書の3.5節
Related information
このメソッドは実際のクライアントでは使用されません。HTTP/1.1 サーバーや中継者が HTTP/2 コネクションプリフェイスの解析をする際に、このメソッドが使用されているように見えます。

11.7. 421 (Misdirected Request) HTTP ステータスコード

この文書は 421 (Misdirected Request) HTTP ステータスコードを "HTTP Status Codes" レジストリ ([RFC7231]、8.2節) に登録します。

Status Code
421
Short Description
Misdirected Request
Specification
この文書の9.1.2節

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

この文書は "h2c" アップグレードトークンを "HTTP Upgrade Tokens" レジストリ ([RFC7230]、8.6節) に登録します。

Value
h2c
Description
Hypertext Transfer Protocol version 2 (HTTP/2)
Expected Version Tokens
None
Reference
この文書の3.2節

12. 参考文献

12.1. 引用文書

[COMPRESSION]
Peon, R. and H. Ruellan, "HPACK - Header Compression for HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015, >http://www.rfc-editor.org/info/rfc7541<.
Barth, A., "HTTP State Management Mechanism", RFC 6265, April 2011, >http://www.rfc-editor.org/info/rfc6265<.
[FIPS186]
NIST, "Digital Signature Standard (DSS)", FIPS PUB 186-4, July 2013. <http://dx.doi.org/10.6028/NIST.FIPS.186-4>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.
[RFC2818]
Rescorla, E., "HTTP Over TLS", RFC 2818, DOI 10.17487/RFC2818, May 2000, <http://www.rfc-editor.org/info/rfc2818>.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <http://www.rfc-editor.org/info/rfc3986>.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, <http://www.rfc-editor.org/info/rfc4648>.
[RFC5226]
Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, DOI 10.17487/RFC5226, May 2008, <http://www.rfc-editor.org/info/rfc5226>.
[RFC5234]
Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <http://www.rfc-editor.org/info/rfc5234>.
[RFC7230]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, DOI 10.17487/RFC7230, June 2014, <http://www.rfc-editor.org/info/rfc7230>.
[RFC7231]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014, <http://www.rfc-editor.org/info/rfc7231>.
[RFC7232]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", RFC 7232, DOI 10.17487/RFC7232, June 2014, <http://www.rfc-editor.org/info/rfc7232>.
[RFC7233]
Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", RFC 7233, DOI 10.17487/RFC7233, June 2014, <http://www.rfc-editor.org/info/rfc7233>.
[RFC7234]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", RFC 7234, DOI 10.17487/RFC7234, June 2014, >http://www.rfc-editor.org/info/rfc7234<.
[RFC7235]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", DOI 10.17487/RFC7235, June 2014, <http://www.rfc-editor.org/info/rfc7235>.
[TCP]
Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <http://www.rfc-editor.org/info/rfc793>.
[TLS-ALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301, July 2014, <http://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, August 2008, <http://www.rfc-editor.org/info/rfc5289>>.
[TLS-EXT]
Eastlake, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011, <http://www.rfc-editor.org/info/rfc6066>.
[TLS12]
Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008, <http://www.rfc-editor.org/info/rfc5246>.

12.2. 参考文書

[ALT-SVC]
Nottingham, M., McManus, P., and J. Reschke, "HTTP Alternative Services", Work in Progress, draft-ietf-httpbis-alt-svc-06, February 2015.
[BCP90]
Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004, <http://www.rfc-editor.org/info/bcp90>.
[BREACH]
Gluck, Y., Harris, N., and A. Prado, "BREACH: Reviving the CRIME Attack", July 2013, <http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>.
[HTML5]
Hickson, I., Berjon, R., Faulkner, S., Leithead, T., Doyle Navara, E., O'Connor, E., and S. Pfeiffer, "HTML5", W3C Recommendation REC-html5-20141028, October 2014, <http://www.w3.org/TR/2014/REC-html5-20141028/>.
[RFC3749]
Hollenbeck, S., "Transport Layer Security Protocol Compression Methods", RFC 3749, DOI 10.17487/RFC3749, May 2004, <http://www.rfc-editor.org/info/rfc3749>.
[RFC4492]
Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B. Moeller, "Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)", RFC 4492, DOI 10.17487/RFC4492, May 2006, >http://www.rfc-editor.org/info/rfc4492<.
[RFC6585]
Nottingham, M. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, DOI 10.17487/RFC6585, April 2012, <http://www.rfc-editor.org/info/rfc6585>.
[RFC7323]
Borman, D., Braden, B., Jacobson, V., and R. Scheffenegger, Ed., "TCP Extensions for High Performance", RFC 7323, DOI 10.17487/RFC7323, September 2014, <http://www.rfc-editor.org/info/rfc7323>.
[TALKING]
Huang, L., Chen, E., Barth, A., Rescorla, E., and C. Jackson, "Talking to Yourself for Fun and Profit", 2011, <http://w2spconf.com/2011/papers/websocket.pdf>.
[TLSBCP]
Sheffer, Y., Holz, R., and 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, May 2015, <http://www.rfc-editor.org/info/rfc7525>.

付録A. TLS 1.2 暗号スイートブラックリスト

HTTP/2 実装は、TLS 1.2 での以下の暗号スイートによるネゴシエーションを INADEQUATE_SECURITY のコネクションエラー (5.4.1節) として扱ってもよいものとします (MAY):

注: このリストは、執筆時に登録されている TLS 暗号スイートのセットから構成されています。このリストには、一時鍵の交換を提供しない暗号スイートや、TLS null、ストリームまたはブロック暗号 ([TLS12]、6.2.3節で定義) に分類される種類の暗号スイートを含んでいます。これらと同様の性質を持つ追加の暗号スイートは定義可能ですが、それらは明示的に禁止されません。

謝辞

この文書は、以下の個人からの多くの意見を含んでいます:

著者の連絡先

Mike Belshe
BitGo
EMail: mike@belshe.com
Roberto Peon
Google, Inc
EMail: fenix@google.com
Martin Thomson (editor)
Mozilla
331 E Evelyn Street
Mountain View, CA 94041
United States
EMail: martin.thomson@gmail.com