この文書は「Hypertext Transfer Protocol version 2 (draft-ietf-httpbis-http2-14)」の日本語訳です。
原文の最新版 は、この日本語訳が参照した版から更新されている可能性があります。
原文はドラフト版であり、HTTP/2 は現在策定中の仕様であることに十分注意してください。
この日本語訳は参考情報であり、正式な文書ではないことにも注意してください。また、翻訳において生じた誤りが含まれる可能性があるため、必ず原文もあわせて参照することを推奨します。
draft-ietf-httpbis-http2-14
この仕様は、最適化された Hypertext Transfer Protocol (HTTP) の構文表現について説明します。HTTP/2 は、ヘッダーフィールドの圧縮を導入し、同一接続上の複数同時メッセージの実現により、ネットワークリソースのより効率的な利用とレイテンシの削減を可能にします。また、サーバーからクライアントへ一方的に送るプッシュ表現についても説明します。
この仕様は HTTP/1.1 のメッセージ構文を変更しますが、これを廃止するわけではありません。HTTP の既存のセマンティクスは変更しません。
この草案の議論は [1] にアーカイブされる HTTPBIS ワーキンググループのメーリングリスト ([email protected]) でおこなわれます。
ワーキンググループの情報は [2] で、HTTP/2 に関する情報は [3] でそれぞれ見つけることができます。
この草案における変更点は Appendix A に要約されています。
このインターネット草案は BCP 78 と BCP 79 の規定に完全に準拠して提出されます。
インターネット草案は Internet Engineering Task Force (IETF) の作業文書です。他のグループも作業文書をインターネット草案として配布できることに注意してください。最新のインターネット草案のリストは http://datatracker.ietf.org/drafts/current/ にあります。
インターネット草案は、最長6ヶ月間有効な草案文書であり、いかなる時でも更新や置き換え、他の文書により廃止されることがあります。また、参考資料としてインターネット草案を使用したり、"進行中の作業" としてではなく引用をするのは不適切です。
このインターネット草案は2015年1月31日に期限切れとなります。
Copyright (c) 2014 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.
Hypertext Transfer Protocol (HTTP) は広く成功したプロトコルです。しかしながら、HTTP/1.1 メッセージのフォーマット ([RFC7230]、3章) は、モダンな Web アプリケーションのパフォーマンスよりも、1990年代の手近なツールを使用して実装できるように設計されました。そのため、全体的に今日のアプリケーションのパフォーマンスに悪い影響を与える特性をいくつか持っています。
特に、HTTP/1.0 は与えられた接続に対して、同時に1つのリクエストしか転送できません。HTTP/1.1 パイプラインは、リクエストの並列化に部分的に取り組んだだけで行頭ブロッキングに悩まされています。そのため、多数のリクエストを生成する必要があるクライアントは、レイテンシを減らすために一般的にサーバーに対して複数の接続を使用します。
さらに、HTTP/1.1 のヘッダーフィールドはしばしば重複し、冗長です。これよって巨大なネットワークパケットを多数生成することになり、TCP [TCP] 輻輳の小さな初期ウインドウはすぐいっぱいになってしまいます。そして結果的に、1つの新しい TCP 接続上で複数のリクエストを発行すると、過度の待ち時間が発生することになります。
この仕様では、基礎となる接続に対して HTTP セマンティクスの最適化マッピングを定義することによって、これらの問題に取り組みます。具体的には、同一接続上においてリクエストとレスポンスメッセージを交互に挟み込んだり、HTTP ヘッダーフィールドに対して効率のよい符号化方式を利用したりします。またリクエストの優先付けも可能にし、より重要なリクエストをより迅速に完了させることで更なる性能向上を実現します。
もたらされたプロトコルは、HTTP/1.x と比較して少ない TCP 接続を利用することになるため、よりネットワークフレンドリーな設計となります。これは他のフローとの競合を減らし、接続寿命が長くなることを意味します。そして結果的に、利用可能なネットワークキャパシティの有効利用につながることになります。
最後に、こうしたカプセル化は、バイナリメッセージ構造を使用することで、メッセージ処理をより効率的にすることも可能にします。
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節)。HTTP リクエストは非常に冗長なため、圧縮によりリクエストとレスポンスのサイズを著しく削減できます。
HTTP/2 の仕様は4つのパートで構成されます:
フレーミングレイヤーやストリームレイヤーの概念の一部は HTTP から分離されていますが、完全に汎用的なフレーミングレイヤーを定義することを意図してはいません。フレーミングレイヤーとストリームレイヤーは HTTP プロトコルとサーバープッシュの要件にあわせて作られました。
この文書のキーワード "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"MAY"、そして "OPTIONAL" は RFC 2119 [RFC2119] で記述されたとおりに解釈されるべきです。
すべての数値はネットワークバイトオーダーです。特に断りがない限り、値は符号無しとなります。リテラルの値は、必要に応じて10進数または16進数で提供されます。また、16進数リテラルは10進数リテラルと区別するために "0x" ではじまります。
使用される用語は以下のとおりです:
最後に、"ゲートウェイ"、"中継者"、"プロキシ" そして "トンネル" は [RFC7230] の2.3節で定義されています。
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 で異なることを意味します。"https" URI のための認識は3.2節で説明します。また、"http" URI のための認識は3.3節で説明します。
この文書で定義されるプロトコルの識別子は2つあります。
文字列 "h2" は TLS [TLS12] を使用する HTTP/2 プロトコルを識別します。この識別子は TLS Application layer protocol negotiation extension (ALPN) [TLS-APLN] フィールドや、TLS 上の HTTP/2 であることが識別されるいかなる場所において使用されます。
文字列 "h2" は、2つのオクテット 0x68, 0x32 として、ALPN プロトコル識別子にシリアライズされます。
文字列 "h2c" は平文の TCP 上での HTTP/2 プロトコルを識別します。 この識別子は HTTP/1.1 Upgrade ヘッダーフィールドや、TCP 上の HTTP/2 であることが識別されるいかなる場所において使用されます。
"h2" や "h2c" で通信するということは、この文書で説明される伝送方式、セキュリティ、フレーミング、メッセージセマンティクスを使用することを意味します。
[[CREF1: RFC 編集者注: この文書の最終版を公開する前に、この節の残りの部分は削除してください。]]
最終的な実装に限り、公開された RFC は自身を "h2" や "h2c" として識別できます。RFC が公開されるまでは、実装はこれらの文字を使用して自身を識別してはいけません (MUST NOT)。
この文書の文末までの用例や文章では、編集の利便性のために "h2" を使用します。草案版の実装では、この文字列を使用して識別してはいけません (MUST NOT)。
このプロトコルの草案版の実装は、"-" 文字と識別子として対応する草案番号を追加しなければなりません (MUST)。例えば、TLS 上の draft-ietf-httpbis-http2-11 は "h2-11" という文字列を使用して識別されます。
これらの草案版に基づく非互換の試験では、"-" 文字と実験名を識別子に追加しなければなりません (MUST)。例えば、draft-ietf-httpbis-http2-09 に基づく Packet mood-based encoding の実装実験では、"h2-09-emo" として自身を識別することになります。ラベルは [RFC7230] の3.2.6節で定義される "token" 構文に従わなければなりません (MUST)。実験をするにあたっては、[email protected] メーリングリストで各実験についての調整をすることをお勧めします。
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 のアップグレードに利用します。
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節) です。101 レスポンスを受信すると、クライアントは SETTINGS フレームを含むコネクションプリフェイス (3.5節) を送信します。
アップグレードの前に送信された HTTP/1.1 リクエストには、ストリームID 1 が割り当てられ、可能な限りデフォルト優先度の値が割り当てられます。リクエストが HTTP/1.1 リクエストとして完了しているため、ストリーム 1 はクライアントからサーバーに対して暗黙的に half closed 状態になります。HTTP/2 接続を開始した後、ストリーム 1はレスポンスのために使用されます。
HTTP/1.1 から HTTP/2 にアップグレードするリクエストは、1つの "HTTP2-Settings" ヘッダーフィールドを送信しなければなりません (MUST)。"HTTP2-Settings" ヘッダーフィールドは、HTTP/2 接続を制御するパラメーターを含むホップ間で有効なヘッダーフィールドです。このフィールドは、サーバーがアップグレードリクエストを受け付けることを見越して送信されます。
HTTP2-Settings = token68
このヘッダーフィールドが設定されていない場合、サーバーはアップグレードを拒否しなければなりません (MUST)。また、サーバーはこのヘッダーフィールドを送信してはなりません (MUST NOT)。
"HTTP2-Settings" ヘッダーフィールドの内容は、SETTINGS フレーム (6.5節) のペイロードであり、base64url (これは、最後の '=' を省略した [RFC4648] の5章で説明されている URL セーフかつファイル名セーフの Base64 エンコードです) 文字列としてエンコードされます。"token68" の ABNF [RFC5234] プロダクションは、[RFC7235] の2.1節に定義されています。
これはホップ間のヘッダーフィールドであるため、HTTP/2 にアップグレードする時は <Connection< ヘッダーフィールドに <Upgrade< に加えて <HTTP2-Settings< も含まなければなりません (MUST)。
サーバーは他の SETTINGS フレームと同じように、これらの値をデコードし、解釈します。101 レスポンスは、暗黙的な応答としての役割を果たすため、SETTINGS パラメーターの応答 (6.5.3節) は不要です。このような値をアップグレードリクエストで提供することで、プロトコルは上記 SETTINGS パラメーターのデフォルト値を必要としません。そして、クライアントがサーバーからフレームを受信するよりも前に、他のパラメーターを送信できる機会を持てるようになります。
HTTP/2 の対応を事前に知らずに "https" URI へのリクエストをするクライアントは、 TLS [TLS12] と Application layer protocol negotiation extension [TLS-ALPN] を利用します。
TLS 上の HTTP/2 は "h2" アプリケーショントークンを使用します。"h2c" トークンはクライアントから送信されたり、サーバーにより選択されてはなりません (MUST NOT)。
TLS ネゴシエーションが完了すると、クライアントとサーバーはコネクションプリフェイス (3.5節) を送信します。
クライアントは、他の方法で特定のサーバーが HTTP/2 に対応していることを知ることができます。例えば、[ALT-SVC] では対応状況を通知するメカニズムを説明しています。
クライアントは、HTTP/2 に対応していることが分かっているサーバーに対しては、コネクションプリフェイス (3.5節) に続いて直ちに HTTP/2 フレームを送信してもよいものとします (MAY)。サーバーはコネクションプリフェイスにおける "PRI" メソッドの使用により、このような接続を識別できます。これは平文 TCP 上の HTTP/2 接続の確立にのみ影響し、TLS 上の HTTP/2 をサポートする実装は、TLS のプロトコルネゴシエーション [TLS-ALPN] を使用しなければなりません (MUST)。
事前知識による HTTP/2 接続は、今後のコネクションに対しても指定されたサーバーが HTTP/2 に対応するという強いシグナルではありません。サーバーの設定の変更や、クラスター化されたサーバーインスタンス間で異なる設定をする、ネットワーク状況を変更するといったことは可能です。
TCP 接続が確立し、両方のピアが HTTP/2 の使用を決定するにあたり、最終的な確認と HTTP/2 接続の初期 SETTINGS パラメーターの確立のために、各エンドポイントはコネクションプリフェイスを送信しなければなりません (MUST)。
クライアントコネクションプリフェイスは、24オクテットの配列ではじまり、16進数表現は以下のようになります (文字列表現: "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"):
0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
この配列の後には、SETTINGS フレーム (6.5節) が続きます。SETTINGS フレームは空であってもよいものとします (MAY)。101 Switching Protocols レスポンス (アップグレードの完了を示します) を受信した直後、もしくは TLS 接続の最初のアプリケーションデータのオクテットとして、クライアントはただちにクライアントコネクションプリフェイスを送信します。サーバーが対応するプロトコルを事前に知っていることによって HTTP/2 接続を開始する場合は、クライアントはコネクションを確立した直後にコネクションプリフェイスを送信します。
多数の HTTP/1.1 や HTTP/1.0 のサーバー、中継システムがさらにフレームを処理しないよう、このクライアントコネクションプリフェイスが選ばれました。これは、[TALKING] で提起された懸念には対応しないことに注意してください。
サーバーコネクションプリフェイスは空の可能性がある SETTINGS フレーム (6.5節) だけで構成され、HTTP/2 接続においてサーバーが送信する最初のフレームでなければなりません (MUST)。
不要なレイテンシを防ぐために、クライアントはクライアントコネクションプリフェイスの送信後、サーバーコネクションプリフェイスの受信を待たずに、すぐに追加のフレームをサーバーに送信することが認められています。しかしながら、サーバーコネクションプリフェイスの SETTINGS フレームが、クライアントがサーバーとどのように通信するかを変更するパラメーターを含む可能性があることに注意しないといけません。クライアントは、SETTINGS フレームを受信後に直ちにすべてのパラメーターに従うことが求められます。一部の構成においては、サーバーはこの問題を回避する機会を提供するため、クライアントよりも前に SETTINGS を送信することが可能です。
どちらかのピアが、正しいコネクションプリフェイスを使って通信を開始しない場合は、クライアントとサーバーは TCP 接続を切断しなければなりません (MUST)。そのピアが HTTP/2 を使用していないことが明らかな場合には、GOAWAY フレーム (6.8節) は省略できます。
HTTP/2 接続が確立されると、クライアントとサーバーはフレームの送信を開始できます。
全てのフレームは、9オクテット固定長のヘッダーから始まり、可変長のペイロードがその後に続きます。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ フレームレイアウト
フレームヘッダーのフィールドは以下のように定義されます:
フレームペイロードの構造と内容については、フレームタイプに完全に依存します。
フレームペイロードのサイズは、SETTINGS_MAX_FRAME_SIZE 設定で受信者が通知した最大サイズにより制限されます。この設定は 2^14 (16,384) から 2^24-1 (16,777,215) までのオクテットの値を持つことができます。
全ての実装は、2^14オクテットまでの長さのフレームと9オクテットのフレームヘッダー (4.1節) を受信し、最低限処理できなければなりません (MUST)。フレームサイズを記述する場合は、フレームヘッダーのサイズは含まれません。
注: PING (6.7節) のような特定のフレームタイプでは、ペイロードデータの量について追加の制限があります。
フレームサイズが定義された制限を越えていたり、必要なフレームデータを含むには小さすぎるような場合は、エンドポイントは FRAME_SIZE_ERROR エラーを送信しなければなりません (MUST)。接続の状態を変更可能なフレームにおけるフレームサイズエラーは、コネクションエラー (5.4.1節) として扱われなければなりません (MUST)。これらの対象には、ヘッダーブロック (4.3節) を転送するフレーム (つまり HEADERS や PUSH_PROMISE、CONTINUATION) や SETTINGS、ストリームID が0の WINDOW_UPDATE フレームが含まれます。
エンドポイントには、フレームの全ての利用可能な領域を使用する義務はありません。許可された最大サイズよりも小さいフレームを使用することで、応答性を改善できます。巨大なフレームの送信は、RST_STREAM、WINDOW_UPDATE、PRIORITY といったメンテナンスフレームの送信遅延を引き起こし、巨大なフレームの送信によりそれらのフレームがブロックされた場合、パフォーマンスに影響を与えます。
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.4節)。
受信側エンドポイントはフラグメントを結合することでヘッダーブロックを再構築し、ヘッダーリストを復元するために伸張します。
完全なヘッダーブロックは以下のどちらかで構成されます:
ヘッダー圧縮は状態を持ち、コネクション全体で単一の圧縮コンテキストを仕様します。各ヘッダーブロックは別々の単位として処理されます。ヘッダーブロックは、他の種類のフレームや他のストリームのフレームの間に挟み込まれずに、連続した一連のフレームとして送信されなければなりません (MUST)。一連の HEADERS や CONTINUATION フレームの最後のフレームには、END_HEADERS フラグが設定されていなければなりません (MUST)。また、一連の PUSH_PROMISE や CONTINUATION フレームの最後のフレームにも、END_HEADERS フラグが設定されていなければなりません (MUST)。これにより、ヘッダーブロックを論理的に単一のフレームと同等にできます。
ヘッダーブロックフラグメントは HEADERS、PUSH_PROMISE、CONTINUATION フレームのペイロードでのみ送信できます。これらのフレームは、受信者が保持する圧縮コンテキストを変更するデータを転送するためです。HEADERS、PUSH_PROMISE、CONTINUATION フレームを受信したエンドポイントは、フレームの破棄が発生したような場合であっても、ヘッダーブロックを再構築し、伸張しなければなりません (MUST)。ヘッダーブロックを伸張できない場合、受信者は COMPRESSION_ERROR コネクションエラー (5.4.1節) と共にコネクションを終了しなければなりません (MUST)。
"ストリーム" とは、HTTP/2 接続においてクライアントとサーバーとの間で交換されるフレームの独立した双方向シーケンスです。ストリームにはいくつかの重要な特徴があります:
ストリームのライフサイクルは、図1に示したようになります。
+--------+ PP | | PP ,--------| idle |--------. / | | \ v +--------+ v +----------+ | +----------+ | | | H | | ,---| reserved | | | reserved |---. | | (local) | v | (remote) | | | +----------+ +--------+ +----------+ | | | ES | | ES | | | | H ,-------| open |-------. | H | | | / | | \ | | | v v +--------+ v v | | +----------+ | +----------+ | | | half | | | half | | | | closed | | R | closed | | | | (remote) | | | (local) | | | +----------+ | +----------+ | | | v | | | | ES / R +--------+ ES / R | | | `----------->| |<-----------' | | R | closed | R | `-------------------->| |<--------------------' +--------+ H: HEADERS フレーム (CONTINUATION が続く可能性がある) PP: PUSH_PROMISE フレーム (CONTINUATION が続く可能性がある) ES: END_STREAM フラグ R: RST_STREAM フレーム 図1: ストリームの状態
このダイアグラムはストリームの状態遷移と、これらの遷移に影響するフレームのみを表していることに注意してください。なお、CONTINUATION フレームについては状態遷移をもたらさず、実質的に HEADERS や PUSH_PROMISE の一部になります。
両方のエンドポイントは、それぞれの立場に応じたストリーム状態図を持ち、フレーム転送中では両者は異なるでしょう。エンドポイントはストリームの作成について互いに連携しません。ストリームはどちらかのエンドポイントにより一方的に作成されます。状態の不一致に伴う悪い影響は、RST_STREAM を送信した後の "closed" 状態に限定されます。その場合クローズ後にしばらくフレームを受信するかもしれません。
ストリームは次のような状態を持ちます:
全てのストリームは "idle" 状態からはじまります。この状態ではフレームは交換されません。
この状態では、次のような遷移が有効です:
"reserved (local)" 状態のストリームは、PUSH_PROMISE を送信して予約した状態です。PUSH_PROMISE フレームは、idle ストリームとリモートピアから始めた open ストリームを関連付けることによって、その idle ストリームを予約します (8.2節)。
この状態では、次のような遷移のみ可能です:
この状態において、エンドポイントは HEADERS または RST_STREAM 以外のフレームを送信してはいけません。(MUST NOT)。
PRIORITY フレームはこの状態で受信してもよいものとします (MAY)。RST_STREAM や PRIORITY フレーム以外の受信については、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
"reserved (remote)" 状態のストリームは、リモートピアにより予約されています。
この状態では、次のような遷移のみ可能です:
エンドポイントは、予約済みストリームの優先度を変更するために、この状態で PRIORITY フレームを送信してもよいものとします (MAY)。また、エンドポイントは RST_STREAM や PRIORITY フレーム以外の種類のフレームを送信してはいけません (MUST NOT)。
HEADERS や RST_STREAM フレーム以外の受信については、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
"open" 状態のストリームは、両方のピアがいかなる種類のフレームを送信するために使用できます。この状態では、送信側のピアはストリームレベルのフロー制御 (5.2節) に従います。
この状態から、どちらのエンドポイントも END_STREAM フラグを設定したフレームを送信できます。それによって、ストリームは "half closed" 状態に遷移します。すなわちエンドポイントが END_STREAM フラグを送信すると、ストリームの状態は "half closed (local)" となり、エンドポイントが END_STREAM フラグを受信した場合は、ストリームの状態が "half closed (remote)" になります。
この状態では、どちらのエンドポイントも直ちに "closed" に遷移させる RST_STREAM フレームを送信できます。
"half closed (local)" のストリームは、フレームの送信に使用することはできません。この状態では、WINDOW_UPDATE や PRIORITY、RST_STREAM フレームのみを送信できます。
END_STREAM フラグを含むフレームを受信するか、いずれかのピアが RST_STREAM フレームを送信した時、ストリームはこの状態から "closed" に遷移します。
受信者は、END_STREAM フラグが設定されたフレームを送信した後の短時間に到着する可能性がある WINDOW_UPDATE をこの状態では無視できます。
この状態で受信する PRIORITY フレームは、現在のストリームに依存するストリームの再優先度付けに使用されます。
"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 ストリームにフレームを送信してはいけません (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 フレームをこの状態で受信できます。リモートピアが、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)。
HTTP リクエスト/レスポンスの交換における状態遷移の例は、8.1節で確認できます。サーバープッシュの状態遷移の例は、8.2.1節と8.2.2節で確認できます。
ストリームは、符合なし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を確立できないサーバーは、新しいストリームのために新しいコネクションを開始することをクライアントに強制するために、GOAWA フレームを送信できます。
ピアは、SETTINGS フレームの SETTINGS_MAX_CONCURRENT_STREAMS パラメーター (6.5.2節) を使用することで、同時アクティブなストリームの数を制限できます。最大同時ストリーム設定は各エンドポイントに固有であり、その設定を受信したピアにのみ適用されます。つまり、クライアントはサーバーが開始可能な同時ストリームの最大数を指定し、サーバーはクライアントが開始可能な同時ストリームの最大数を指定します。
エンドポイントが開始可能なストリームの最大数は、"open" または2つの "half closed" 状態のストリームの数で計算されます。これら3つの状態にあるストリームは SETTINGS_MAX_CONCURRENT_STREAMS 設定で指定された制限に数えられます。2つの "reserved" 状態にあるストリームは、このストリーム制限には数えられません。
エンドポイントはお互いのピアが設定した制限を超えてはなりません (MUST NOT)。告知した同時ストリーム制限を超えるような HEADERS フレームを受信したエンドポイントは、それをストリームエラー (5.4.2節) として扱わなければなりません (MUST)。SETTINGS_MAX_CONCURRENT_STREAMS を現在の同時ストリーム数よりも少ない値に設定したいエンドポイントは、新しい値を超えるストリームを終了するか、完了させることができます。
ストリームの多重化を使用すると、TCP 接続を使用する上で競合が発生し、その結果ストリームのブロックが起こります。フロー制御の仕組みは、同一コネクション上でストリームが互いに破壊的な干渉をしないことを保証します。フロー制御は、個々のストリームとコネクション全体のどちらにも使用されます。
HTTP/2 では、WINDOW_UPDATE フレーム (6.9節) の使用を通じて、フロー制御を提供します。
HTTP/2 のストリームフロー制御は、プロトコルの変更の必要なしに、フロー制御アルゴリズムを将来的に改善できるようにすることを目標にしています。HTTP/2 におけるフロー制御は以下のような特徴があります:
装には、優先度に基づいてリクエストやレスポンスを送信する方法の管理や、リクエストの行頭ブロッキングを防ぐ方法の選択、新しいストリームの作成の管理などをする責任があります。これらのアルゴリズムの選択肢は、フロー制御アルゴリズムと相互に影響します。
フロー制御は、リソース制限下で動作しているエンドポイントを保護するために定義されています。例えばプロキシは、多くのコネクションの間でメモリーを共有する必要があり、そこには低速なアップストリームや高速なダウンストリームを含む可能性があるでしょう。フロー制御は、受信者があるストリームのデータの処理ができない状況であっても、同一コネクション上の他のストリームの処理を継続したい場合に対応します。
この機能を必要としない構成では、新しいデータを受信した際に利用可能な容量を増加させるように最大サイズのフロー制御ウインドウを告知できます。これはそのような受信者において実質的にフロー制御を無効化します。反対に、送信者は常に受信者により通知されたフロー制御ウインドウの影響を受けます。
リソース (例えばメモリーなど) が制限された構成では、ピアが使用するメモリーの量を制限するために、フロー制御を使用できます。しかしながら、帯域幅遅延積 ([RFC1323]) についての知識なしにフロー制御を有効化した場合、利用可能なネットワークリソースを適切に利用できない可能性があることに注意してください。
最新の帯域幅遅延積についての十分な知識があるとしても、フロー制御の実装は困難である可能性があります。フロー制御を使用する時、受信者は TCP の受信バッファを直ちに読み込まなければなりません (MUST)。読み込みに失敗すると、WINDOW_UPDATE などの重要なフレームの読み込みと処理ができず、デッドロックを引き起こす可能性があります。
クライアントは、ストリームを開始する HEADERS フレーム (6.2節) に優先度情報を含めることで、新しいストリームの優先度を指定できます。既存のストリームでは、PRIORITY フレーム (6.3節) を使用して優先度を変更できます。
優先度の目的は、エンドポイントが同時ストリームを管理する際に、そのピアに対してリソースの割り当て方法を明示できるようにすることです。最も重要なのは、送信キャパシティが限られている時に、フレームを転送するストリームを選択するために優先度が使用できることです。
ストリームは、他のストリームの完了 (5.3.1節) に依存する関係を作ることで、優先度を設定できます。各依存関係には、相対的な重みが割り当てられ、その値は、同じストリームに依存するストリームに割り当てられた利用可能なリソースの、相対的な比率を決定するために使用されます。
ストリームの優先度を明示的に設定することは、優先度付け処理への入力になります。これは他のストリームに相対するストリームに対して、特別な処理や転送順序を保証するものではありません。エンドポイントは優先度を使用して、ピアに特定の順序による同時ストリームの処理を強制できません。優先度を明示することは、あくまで提案でしかありません。
優先度情報は HEADERS フレームを使用して生成するストリームに明示的に指定したり、PRIORITY フレームを使用して変更できます。優先度情報の提供は任意です。特に指示がない場合は、デフォルトの値が使用されます (5.3.5節)。
各ストリームは他のストリームに明示的な依存関係を与えることができます。依存関係を含めることで、依存ストリームよりも指定されたストリームへのリソースの割り当てが優先されることを表現します。
他のストリームに依存しないストリームには 0x0 のストリーム依存関係が与えられます。言い換えれば、存在しないストリーム 0 はツリーのルートを構成します。
他のストリームの依存するストリームは依存ストリームです。ストリームが依存する先のストリームは、親ストリームとなります。"idle" 状態にあるストリームなど、現在ツリーにないストリームへの依存は、そのストリームにデフォルト優先度が与えられることになります。
ストリームを他のストリームの依存関係に割り当てるとき、そのストリームは、親ストリームの新しい依存関係として追加されます。同じ親を共有する依存ストリームは、その順序をお互いに考慮しません。例えば、ストリームBとCがストリームAに依存する時、ストリームAを依存先とするストリームDが生成された場合、Aの依存関係は任意の順序でB、C、Dが続きます。
A A / \ ==> /|\ B C B D C デフォルト依存関係の生成例
排他フラグは依存関係に新しい階層を挿入できます。排他フラグは、親ストリームの依存関係を自身の依存関係となるようにし、さらに自身を親ストリームの唯一の依存関係となるようにします。先ほどの例において、ストリームAに対して排他依存関係と共にストリームDを生成した場合、DはBとCの親の依存関係になります。
A A | / \ ==> D B C / \ B C 排他依存の生成例
依存ツリーの内部では、全ての依存先のストリーム (0x0までの親ストリームのつながり) が終了したり、ストリームの続行が不可能であった場合でも、依存ストリームにはリソースが割り当てられるべきです (SHOULD)。
ストリームは自身に依存できません。エンドポイントはこれを PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。
全ての依存ストリームには、1から256までの整数の重みが割り当てられます。
同じ依存関係にあるストリームは、それらの重みに比例してリソースが割り当てられるべきです (SHOULD)。例えば、ストリームAに依存するストリームBの重みが4であり、同じストリームAに依存するストリームCの重みが12であった場合、Aに何も進展がなければ、ストリームBにはストリームCに割り当てられたリソースの3分の1が割り当てられます。
ストリームの優先度は PRIORITY フレームの使用により変更されます。依存関係を設定すると、ストリームを指定した親ストリームに依存させます。
親ストリームが再優先度付けされた場合、依存ストリームは親ストリームと共に移動します。再優先度付けされたストリームに排他フラグを伴う依存関係を設定すると、新しい親ストリームの全ての依存関係を、自身の依存関係になるように移動します。
ストリームが自身に依存するストリームの1つに依存関係を生成する場合、以前の依存ストリームは最初に再優先度付けされるストリームの前の親の依存関係になるように移動します。移動する依存ストリームはその重みを維持します。
例えば、BとCがAに、DとEがCに、FがDに依存する依存ツリーを考えます。AがDに依存関係を生成する場合、DはAの位置に移動します。Fを除く他の全ての依存関係はとどまり、再優先度付けが排他である場合は、全てがAに依存するようになります。
? ? ? ? | / \ | | 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 (中間状態) (非排他的状態) (排他的状態) 依存関係の並び替えの例
ストリームが依存ツリーから削除された際、その依存関係は終了したストリームの親ストリームに移動できます。新しい依存関係における重みは、自身の重みに基づき、終了したストリームの依存関係の重みに比例して再計算されます。
依存ツリーから削除されたストリームは、一部の優先度情報が失われる可能性があります。リソースは、同じ親ストリームを持つストリーム間で共有されます。これは、そのセット内のストリームが終了するか、ブロックされた状態になった場合、ストリームに割り当てられた予備のリソースはすぐ隣同士のストリームに分散されることを意味します。しかしながら、共有の依存関係がツリーから削除された場合、それらのストリームは、次の上位レベルのストリームとリソースを共有します。
例えば、まずストリームAとBが親を共有しており、ストリームCとDの両方がストリームAに依存していると仮定します。ストリームAとDの処理が続行できない場合は、ストリームAを削除する前に、ストリームCがAのためのリソースの全てを受け取ります。もしストリームAがツリーから削除された場合、ストリームAの重みはストリームCとDに均等に分割されます。ストリームDがまだ処理を続行できない場合、結果としてストリームCは少なくなったリソース比率を受け取ることになります。ストリームCは利用可能なリソースの半分ではなく、3分の1を受け取ります。
ストリームの依存関係を生成する優先度情報が転送中でも、そのストリームを終了することは可能です。依存関係に指定されたストリームが破棄された優先度情報に関連していた場合、その依存ストリームには代わりにデフォルト優先度が割り当てられます。ストリームには意図するよりも高い優先度を与えることができるので、最適でない優先度を設定する可能性があります。
これらの問題を防ぐために、エンドポイントは、ストリームが終了した後しばらくの間、ストリームの優先度状態を保持すべきです (SHOULD)。長く状態が保持されると、低確率でストリームが不正に割り当てられたり、デフォルトの優先度が割り当てられたりしてしまいます。
これはエンドポイントに大規模な状態保持を負わせる可能性があるため、この状態は制限されてもよいものとします (MAY)。エンドポイントは、状態保持を制限を目的として優先度状態を追跡するための終了済みのストリーム数に、固定の上限を設定してもよいものとします (MAY)。エンドポイントが管理する追加の状態量は負荷に依存する可能性があります。高負荷時では、リソースのコミットメントを制限するために優先度の状態を破棄できます。極端なケースでは、エンドポイントは有効なストリームや予約済みストリームの優先度も破棄できます。固定の上限が適用された場合、エンドポイントは少なくとも SETTINGS_MAX_CONCURRENT_STREAMS で許可されたストリームよりも多くの状態を保持すべきです (SHOULD)。
終了したストリームの優先度を変更する PRIORITY フレームを受信したエンドポイントは、十分な状態を保持しているのであれば、そのストリームに依存するストリームの重みを変更すべきです (SHOULD)。
優先度情報の提供は任意です。ストリームにはストリーム 0x0 への非排他的依存がデフォルトで割り当てられます。プッシュストリーム (8.2節) は関連付けられたストリームに依存します。どちらの場合も、ストリームにはデフォルトの重み 16 が割り当てられます。
HTTP/2 の枠組みにおいては、2種類のエラーを認めています:
エラーコードのリストは7章にあります。
コネクションエラーとは、フレーミングレイヤーの処理の妨げとなるエラーや、接続状態を破壊するエラーです。
コネクションエラーが発生したエンドポイントは、ピアから受信に成功した最後のストリームIDと共に GOAWAY フレーム (6.8節) を最初に送信するべきです (SHOULD)。GOAWAY フレームにはコネクションが終了した理由を示すエラーコードが含まれます。GOAWAY フレームの送信後、エンドポイントは TCP 接続を終了しなければなりません (MUST)。
GOAWAY は受信側エンドポイントで期待通りに受信されない可能性があります。コネクションエラーが発生した場合、GOAWAY はコネクションが終了した理由をベストエフォートでピアに対して伝えるだけです。
エンドポイントはいつでもコネクションを終了することができます。特にエンドポイントは、ストリームエラーをコネクションエラーとして扱えます (MAY)。状況が許す限り、エンドポイントはコネクションを終了するときに GOAWAY フレームを送信するべきです (SHOULD)。
ストリームエラーは、他のストリームの処理には影響しない、特定のストリームに関連するエラーです。
ストリームエラーを検知したエンドポイントは、エラーが発生したストリームのストリーム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)。
ストリームが開かれている間、または half closed 状態の間に TCP 接続が破壊された場合、エンドポイントはストリームが異常終了し、不完全な状態にあると見なさなければなりません (MUST)。
HTTP/2 はプロトコルの拡張を認めています。プロトコル拡張はこの節で説明する制限の範囲内で、追加のサービスの提供やプロトコルの様々な面を変更するために使用できます。拡張は単一の HTTP/2 コネクションの範囲に影響します。
拡張では、新しいフレームタイプ (4.1節)、新しい設定 (6.5.2節)、新しいエラーコード (7章) の使用が認められています。レジストリはこれらの拡張ポイントを管理するために、フレームタイプ (11.2節)、設定 (11.3節)、エラーコード (11.4節) でそれぞれ制定されています。
実装は、全てのプロトコルの拡張要素における不明また未対応の値を無視しなければなりません (MUST)。実装は不明または未対応のタイプのフレームを破棄しなければなりません (MUST)。これはどの拡張ポイントも、事前の合意やネゴシエートなしに拡張によって安全に使用できることを意味します。
しかし、既存のプロトコル構成要素のセマンティクスを変更する拡張は、使用される前にネゴシエートされなければなりません (MUST)。例えば、HEADERS フレームの配置を変更する拡張は、ピアからこれを受け入れる肯定的な通知があるまで使用することはできません。このような場合、レイアウトの変更が有効になった時に調整を必要とする可能性があります。DATA フレーム以外のフレームをフロー制御の対象として扱う場合は、そのようにセマンティクスを変更し、ネゴシエーションを通じてのみ完了できることに注意してください。
この文書では、拡張の使用をネゴシエートする具体的な方法を強制しません。しかし、設定 (6.5.2節) がこのような目的で使用されることに注意してください。もし両方のピアが拡張を使用する意図を示す値を設定した場合は、その拡張は使用されます。拡張のネゴシエーションに設定が使用される場合、初期段階ではその拡張が無効化されるように、その初期値を定義しなければなりません (MUST)。
この仕様では、一意な8ビットのタイプコードで識別される、いくつかのフレームタイプを定義します。各フレームタイプは、全体的なコネクションや個々のストリームの確立と管理について、それぞれ異なる目的を果たします。
特定のフレームタイプの送信は、コネクションの状態を変更できます。エンドポイントの両方が接続状態を同期し続けることに失敗した場合、そのコネクションにおいてこれ以上正常な通信をすることはできません。したがって、エンドポイントは特定のフレームを使用することで、状態にどのような影響を与えるかの共通理解を持つことが重要です。
DATA フレーム (type=0x0) は、ストリームに関連する任意の可変長オクテット列を転送します。HTTP リクエストまたはレスポンスのペイロードを伝えるために、1つ以上の DATA フレームが使用されます。
DATA フレームは任意のパディングを含んでもよいものとします (MAY)。パディングは DATA フレームのメッセージサイズを隠すために追加できます。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Pad Length? (8)| +---------------+-----------------------------------------------+ | Data (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ DATA フレームペイロード
DATA フレームは以下のフィールドを含みます:
DATA フレームは以下のフラグを定義します:
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オクテット大きくできます。
パディングの使用はセキュリティのための機能です。そのため、使用には注意が必要です。10.7節を参照してください。
HEADERS フレーム (type=0x1) は名前-値のペアを転送します。これはストリームの開始 (5.1節) に使用されます。HEADERS フレームは "open" または "half closed (remote)" 状態のストリームに送信できます。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ |E| Stream Dependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ HEADERS フレームペイロード
HEADERS フレームのペイロードは以下のフィールドを含みます:
HEADERS フレームは以下のフラグを定義します:
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節) における定義と全く同じです。
PRIORITY フレーム (type=0x2) は、送信者からのストリーム優先度 (5.3節) を指定します。このフレームは、終了したストリームを含む既存のストリームに対していつでも送信でき、既存のストリームの優先付けを可能にします。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |E| Stream Dependency (31) | +-+-------------+-----------------------------------------------+ | Weight (8) | +-+-------------+ PRIORITY フレームペイロード
PRIORITY フレームのペイロードは、以下のフィールドを含みます:
PRIORITY フレームはフラグを定義しません。
PRIORITY フレームは既存のストリームに関連付けられます。ストリームIDが 0x0 の PRIORITY フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。
PRIORITY フレームは、"reserved (remote)"、"open"、"half-closed (local)"、"half closed (remote)"、そして "closed" のいずれかの状態のストリームに送信できます。ただし、1つのヘッダーブロック (4.3節)を構成する連続したフレームの間での送信はできません。このフレームは、処理の完了後やフレーム送信後に受信されることもあり、そのため現在のストリームには何も影響を与えない可能性があることに注意してください。"half closed (remote)" や "closed" 状態にあるストリームでは、このフレームは現在のストリームの処理にのみ影響し、ストリームの送信には影響を与えません。
PRIORITY フレームは "closed" 状態にあるストリームに送信できる唯一のフレームです。これは親ストリームの優先度を変更することで、依存ストリームのグループの再優先度付けを可能にします。しかしながら、PRIORITY フレームを終了したストリームに送信しても、ピアがそのストリームの優先度状態の情報を破棄した結果として無視される危険性があります。
RST_STREAM フレーム (type=0x3) はストリームの異常終了を可能にします。ストリームの作成者がこのフレームを送信した場合は、ストリームのキャンセルを要求しているか、エラー状態にあることを示します。ストリームの受信者が送信した場合は、ストリームのキャンセルを要求しているか、エラー状態にあることにより、受信者がストリームを拒否していることを示します。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code (32) | +---------------------------------------------------------------+ RST_STREAM フレームペイロード
RST_STREAM フレームはエラーコード (7章) を明確にする符号なし32ビット整数を1つ含みます。このエラーコードは、ストリームが終了した理由を示します。
RST_STREAM フレームはフラグを定義しません。
RST_STREAM フレームは関連するストリームを完全に終了し、closed 状態に遷移させます。 RST_STREAM をストリーム上で受信した後に、受信者はそのストリームに対して追加のフレームを送信してはいけません (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)。
SETTINGS frame (type=0x4) は、ピアの振る舞いに関する初期設定や制約といった、エンドポイントの通信方法に影響を与える設定パラメーターを転送します。SETTINGS フレームはそのようなパラメータの受信確認にも使用されます。SETTINGS パラメーターはそれぞれが「設定」としても呼ばれます。
SETTINGS パラメーターはネゴシエートされません。これらは送信側ピアが特性を記述し、受信側ピアによって使用されます。また、それぞれのピアから、同一のパラメーターに対して異なる値が通知されます。例えば、クライアントは高い初期フロー制御ウインドウを設定するかもしれませんが、サーバーはリソースを節約するために低い値を設定するかもしれません。
SETTINGS フレームは、コネクション開始時に両方のエンドポイントから送信されなければなりません (MUST)。また、接続中はいかなる時でもいずれかのエンドポイントから送信してもよいものとします (MAY)。実装は、この仕様に定義されている全てのパラメーターに対応しなければなりません (MUST)。
SETTINGS フレームの各パラメーターは、そのパラメーターの既存の値を置き換えます。パラメーターは登場した順序で処理され、SETTINGS フレームの受信者は現在のパラメーター値以外の状態を維持する必要はありません。したがって SETTINGS パラメーターの値は受信者が最後に処理した値になります。
SETTINGS パラメーターは受信したピアにより確認されます。これを有効にするため、SETTINGS フレームは以下のフラグを定義します:
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)。
SETTINGS フレームのペイロードは0個以上のパラメーターからなります。各パラメーターは、16ビットの設定識別子と符号なし32ビットの設定値からなります。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier (16) | +-------------------------------+-------------------------------+ | Value (32) | +---------------------------------------------------------------+ 設定フォーマット
定義済みの設定は以下の通りです:
不明や未対応の識別子を含む SETTINGS フレームを受信したエンドポイントは、その設定を無視しなければなりません (MUST)。
ほとんどの SETTINGS 値にとって、いつピアが変更するパラメーター値を受信し、その値を適用したかを知ることはメリットになり、そうなることが求められます。このような同期点を提供するために、ACK フラグが設定されていない SETTINGS フレームの受信者は、受信後に更新されたパラメーターを可能な限り早く適用しなければなりません (MUST)。
SETTINGS フレームの値は、その間に他のフレームを処理することなく、出現した順序で処理されなければなりません (MUST)。未対応のパラメーターは無視されなければなりません (MUST)。全ての値を処理後、受信者は ACK フラグを設定した SETTINGS フレームをすぐに送信しなければなりません (MUST)。ACK フラグが設定された SETTINGS フレームを受信すると、パラメーターを変更した送信者は適用された設定に依存できます。
SETTINGS フレームの送信者が妥当な時間に応答を受信しなかった場合、SETTINGS_TIMEOUT のコネクションエラー (5.4.1節) として応答してもよいものとします (MAY)。
PUSH_PROMISE フレーム (type=0x5) は、送信者が開始する予定のストリームを事前にピアエンドポイントに通知するために使用します。PUSH_PROMISE フレームは、エンドポイントがストリームに追加のコンテキストを提供するヘッダーセットと共に、作成する予定のストリームの符号なし31ビット識別子を含みます。PUSH_PROMISE フレームの使用についての完全な説明は、8.2節に記述されています。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ |R| Promised Stream ID (31) | +-+-----------------------------+-------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ PUSH_PROMISE ペイロードフォーマット
PUSH_PROMISE フレームのペイロードは、以下のフィールドを含みます:
PUSH_PROMISE フレームは以下のフラグを定義します:
PUSH_PROMISE フレームは既存のピアが開始したストリームに関連付けられなければなりません (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)。同様に、受信者は不正なストリームID (5.1.1節) (これはつまり、現在 "idle" 状態でないストリームのIDを指します) を予約する PUSH_PROMISE への応答も、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
PUSH_PROMISE フレームは任意のパディングを含みます。Padding フィールドと関連するフラグは DATA フレーム (6.1節) における定義と全く同じです。
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) | | | +---------------------------------------------------------------+ PING ペイロードフォーマット
PING フレームは、フレームヘッダーに加え、ペイロードに8オクテットのデータを含まなければなりません (MUST)。送信者はペイロードに任意の値を選択して含めることができ、任意の方法でそれらのバイトを使用できます。
ACK フラグを含まない PING フレームの受信者は、そのレスポンスとして、同じペイロードと共に ACK フラグを設定した PING フレームを送信しなければなりません (MUST)。PING レスポンスは他のフレームよりも高い優先度が設定されるべきです (SHOULD)。
PING フレームは以下のフラグを定義します:
PING フレームは個別のストリームには関連付けられません。ストリームIDフィールドの値が 0x0 でない PING フレームを受信した場合、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。
長さフィールドの値が 8 になっていない PING フレームの受信者は、FRAME_SIZE_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
GOAWAY フレーム (type=0x7) は、リモートピアがコネクションにおけるストリームの作成を終了することを伝えます。GOAWAY フレームはクライアントとサーバーのどちらからでも送信できます。このフレームが送信されると、送信者は、最終ストリームIDに指定した値よりも大きいストリームIDをもつ、新しいストリームに送信されたフレームを無視します。GOAWAY フレームの受信者は、現在のコネクション上で新しい追加のストリームを開始してはいけません (MUST NOT)。しかし、新しいストリームを生成するために新しくコネクションを確立できます。
このフレームの目的は、以前確立したストリームの処理を終了している間であっても、エンドポイントが新しいストリームの受け入れを適切に停止できるようにすることです。これによりサーバーメンテナンスのような管理操作を可能にします。
新しくストリームを開始したエンドポイントと、GOAWAY フレームを送信したリモートの間には、固有の競合状態があります。このような場合に対処するため、GOAWAY は現在のコネクションで送信側エンドポイントが最後に処理した、または処理したと思われる、ピアが開始した最後のストリームIDを含みます。例えば、サーバーが GOAWAY フレームを送信した場合、最後のストリームIDは、クライアントが開始したストリームの最も大きい番号のストリームIDになります。
GOAWAY の受信者が、GOAWAY フレームで示されたストリームIDよりも大きいIDを持つストリームにデータを送信した場合、それらのストリームは処理されません。GOAWAY フレームの受信者は、そのストリームの全てが生成されなかったものとして扱うことができます。したがって、これらのストリームは、後に新しいコネクション上で再施行できます。
ストリームが部分的に処理されたのかどうかを、リモートが知ることができるよう、エンドポイントはコネクションを終了する前に、常に GOAWAY フレームを送信するべきです (SHOULD)。例えば、ある HTTP クライアントが、サーバーがコネクションを終了するのと同時に POST を送信した場合に、サーバーがどのストリームまで処理したかを示す GOAWAY フレームを送信しなければ、クライアントはサーバーが POST リクエストの処理を開始したのかどうかを知ることができません。
不正なピアに対しては、エンドポイントは GOAWAY の送信なしにコネクションを終了することを選ぶかもしれません。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |R| Last-Stream-ID (31) | +-+-------------------------------------------------------------+ | Error Code (32) | +---------------------------------------------------------------+ | Additional Debug Data (*) | +---------------------------------------------------------------+ 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)。
WINDOW_UPDATE フレーム (type=0x8) フロー制御を実行するために使用されます。概要については5.2節を参照してください。
フロー制御は、個々のストリームとコネクション全体の2段階でおこなわれます。
どちらの段階のフロー制御もホップ間、つまり2つのエンドポイントの間でのみおこなわれます。中継者は繋がっているコネクションの間で WINDOW_UPDATE フレームを転送しません。しかしながら受信者がデータ転送をスロットリングすることによって、元の送信者に対してフロー制御情報を間接的に伝搬させることができます。
フロー制御は、フロー制御の対象となる特定のフレームにのみ適用されます。この文書に定義されるフレームの種類のうち、対象となるのは DATA フレームのみです。フロー制御の対象でないフレームは、受信者がフレームを処理するためのリソースの割り当てに失敗しない限り、受け入れ、処理されなければなりません (MUST)。フレームの受け入れに失敗した場合、受信者はストリームエラー (5.4.2節) または FLOW_CONTROL_ERROR のコネクションエラー (5.4.1節) として応答してもよいものとします (MAY)。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |R| Window Size Increment (31) | +-+-------------------------------------------------------------+ WINDOW_UPDATE ペイロードフォーマット
WINDOW_UPDATE フレームのペイロードは、1つの予約ビットと、既存のフロー制御ウインドウに加えて送信者が送信可能なバイト数を示す、符号なし31ビットの整数からなります。フロー制御ウインドウの増加量として認められる範囲は、1から 2^31-1 (0x7fffffff) バイトです。
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)。この考慮はフレームにエラーがある場合であっても必要です。送信者はフロー制御ウィンドウに対してフレームを計算しているため、受信者がこれをおこなわなければ、送信者と受信者のフロー制御ウインドウに差異が発生する可能性があります。
HTTP/2 におけるフロー制御は、各ストリームの送信者ごとに保持されるウインドウを使用することで実装されます。フロー制御ウインドウは、送信者が送信可能なデータのバイト数を示す、シンプルな整数値です。このサイズは、受信者のバッファ容量を計測したサイズでもあります。
ストリームフロー制御ウインドウと、コネクションフロー制御ウインドウの2つのフロー制御ウインドウが適用されます。送信者は、受信者から告知されたいずれかのフロー制御ウインドウで、使用可能な容量を超える長さのフロー制御下にあるフレームを送信してはいけません (MUST NOT)。いずれかのフロー制御ウインドウに使用可能な容量がない場合は、END_STREAM フラグが設定された長さが 0 のフレーム (つまり、空の DATA フレーム) を送信してもよいものとします (MAY)。
フロー制御の計算対象には、8バイトのフレームヘッダーは含まれません。
フロー制御下のフレームを送信後、送信者は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 フレームは、お互いに完全に非同期です。この特性は、ストリームの停止するのを防ぎ、送信者が保持するウインドウサイズを受信者が積極的に更新することを可能にします。
HTTP/2 接続が最初に確立された時に、65,535バイトの初期フロー制御ウインドウサイズと共に新しいストリームが作成されます。コネクションフロー制御ウインドウは65,535バイトになります。どちらのエンドポイントも、コネクションプリフェイスの一部として、SETTINGS フレームに SETTINGS_INITIAL_WINDOW_SIZE の値を含めることで、新しいストリームのための初期ウインドウサイズを調整できます。コネクションフロー制御ウインドウは WINDOW_UPDATE フレームを使用してのみ変更できます。
SETTINGS_INITIAL_WINDOW_SIZE の値が設定された SETTINGS フレームを受信する前に、フロー制御下のフレームを送信する場合は、エンドポイントはデフォルトの初期ウインドウサイズのみを使用できます。同様に、WINDOW_UPDATE フレームを受信するまでは、コネクションフロー制御ウインドウにはデフォルトの初期ウインドウサイズが設定されます。
SETTINGS フレームは、現在の全てのストリームの初期フロー制御ウインドウサイズを変更できます。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)。
現在のサイズよりも少ないフロー制御ウインドウの使用を要求する受信者は、新しい SETTINGS フレームを送信できます。しかしながら、送信者は SETTINGS フレームを処理する前に、変更後の制限を超えるデータを送信した可能性があるため、受信者は変更後のウインドウサイズを超えるデータの受信に備えなければなりません (MUST)。
初期フロー制御ウインドウサイズを減少させる SETTINGS フレームの送信後、受信者にはフロー制御の制限を超えたストリームの処理について、2つの選択肢があります:
CONTINUATION フレーム (type=0x9) は連続するヘッダーブロックフラグメントの続きに使用されます (4.3節)。同一ストリームの直前のフレームが END_HEADERS が設定されていない HEADERS、PUSH_PROMISE、または CONTINUATION である限り、任意の数の CONTINUATION フレームを既存のストリームに送信できます。
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ CONTINUATION フレームペイロード
CONTINUATION フレームのペイロードはヘッダーブロックフラグメントを含みます (4.3節)。
CONTINUATION フレームは以下のフラグを定義します:
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)。
エラーコードは、ストリームやコネクションのエラー理由を伝えるために RST_STREAM と GOAWAY フレームで使用される32ビットのフィールドです。
エラーコードは共通のコード領域を共有します。一部のエラーコードは、ストリームまたはコネクション全体のいずれかのみに適用され、それ以外の状況では定義されたセマンティクスを持ちません。
以下のエラーコードが定義されます:
不明または未対応のエラーコードは、特別な反応を引き起こしてはなりません (MUST NOT)。これらは、実装では INTERNAL_ERROR と等価として扱ってもよいものとします (MAY)。
HTTP/2 は現在使用している HTTP に可能な限り互換であることを目指しています。これは、アプリケーションの観点から、プロトコルの特徴が大きく変わらないことを意味します。これを実現するために、全てのアプリケーションのリクエストとレスポンスヘッダーのセマンティクスは維持され、転送される構文のセマンティクスのみが変更されます。
したがって、HTTP/1.1 セマンティクスの仕様や要件、コンテンツ [RFC7231]、条件付きリクエスト [RFC7232]、範囲リクエスト [RFC7233]、キャッシュ [RFC7234] と認証 [RFC7235] は HTTP/2 に適用できます。HTTP や HTTPS URI スキームのような HTTP/1.1 メッセージ構文とルーティング [RFC7230] の一部も HTTP/2 に適用できますが、このプロトコル専用のセマンティクスの表現は、以降の節で定義されます。
クライアントは、過去に使用していないストリームID (5.1.1節) を使用して、新しいストリーム上で HTTP リクエストを送信します。サーバーはリクエストと同一のストリーム上で HTTP レスポンスを送信します。
HTTP メッセージ (リクエストやレスポンス) はそれぞれ以下のフレームから成ります:
一連のフレームの最後のフレームは END_STREAM フラグを持ちます。END_STREAM フラグを持つ HEADERS フレームの後には、残りのヘッダーブロックの一部を転送する CONTINUATION フレームが続くことができることに注意してください。
(任意のストリームの) その他のフレームは、HEADERS フレームとその後に続く可能性のある CONTINUATION フレームの間に存在してはいけません (MUST NOT)。
HEADERS フレーム (とそれに関連付けられた CONTINUATION フレーム) は、ストリームの最初と最後でのみ送信できます。END_STREAM フラグが設定されていない2つ目の HEADERS フレームを受信したエンドポイントは、対応するリクエストやレスポンスを不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)。
Trailing ヘッダーフィールドはストリームを終了するヘッダーブロックにより転送されます。すなわち、END_STREAM フラグを持つ HEADERS フレームで始まり、0個以上の CONTINUATION フレームが続く、一連のフレームです。ストリームを終了しない最初のヘッダーブロックの後のヘッダーブロックは HTTP リクエストやレスポンスの一部ではありません。
HTTP リクエスト/レスポンスの交換は1つのストリームを完全に消費します。リクエストは、ストリームを "open" 状態にする HEADERS フレームで開始されます。そのリクエストは、ストリームをクライアントでは "half closed (local)" 状態に、サーバーでは "half closed (remote)" 状態にする END_STREAM が設定されたフレームで終了します。レスポンスは HEADERS フレームで開始され、ストリームを "closed" 状態にする END_STREAM が設定されたフレームで終了します。
HTTP/2 は 101 (Switching Protocols) 情報提供ステータスコード ([RFC7231]、6.2.2節) の対応を削除します。
101 (Switching Protocols) のセマンティクスは多重化されたプロトコルには適用されません。代替プロトコルは HTTP/2 の使用をネゴシエートするのに使用するものと同じメカニズムを使用できます。
HTTP ヘッダーフィールドは一連のキーと値のペアとして情報を転送します。登録済み HTTP ヘッダーのリストについては、[4] で整備されている メッセージヘッダーフィールドレジストリを参照してください。
HTTP/1.x では、対象 URI とリクエストのメソッド、そしてレスポンスのステータスコードを転送するためにメッセージ start-line ([RFC7230]、3.1節) を使用していましたが、HTTP/2 では、':' 文字 (ASCII 0x3a) で始まる特殊な擬似ヘッダーフィールドを使用します。
擬似ヘッダーフィールドは HTTP/2 のコンテキストにおいてのみ有効です。これらは HTTP ヘッダーフィールドではありません。エンドポイントはこの文書で定義されたもの以外の擬似ヘッダーフィールドを生成してはいけません (MUST NOT)。
擬似ヘッダーフィールドは、それらが定義されたコンテキストにおいてのみ有効です。リクエストのために定義された擬似ヘッダーフィールドは、レスポンスに使用してはいけません (MUST NOT)。同様に、レスポンスのために定義された擬似ヘッダーフィールドは、リクエストに使用してはいけません (MUST NOT)。擬似ヘッダーフィールドはトレイラーに使用してはいけません (MUST NOT)。エンドポイントは、未定義や無効な擬似ヘッダーフィールドを含むリクエストやレスポンスを不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)。
HTTP/1.x のようにヘッダーフィールド名は、大文字小文字を区別しない方法で比較される ASCII の文字列です。しかしながら HTTP/2 では、ヘッダーフィールド名はエンコード前に小文字に変換されなければなりません (MUST)。大文字のヘッダーフィールド名を含むリクエストやレスポンスは不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)
全ての擬似ヘッダーフィールドは、ヘッダーブロックにおいて通常のヘッダーフィールドよりも前に出現しなければなりません (MUST)。ヘッダーブロックにおいて通常のヘッダーフィールドよりも後に擬似ヘッダーフィールドを含むリクエストやレスポンスは、不正な形式 (8.1.2.6節) として扱わなければなりません (MUST)
HTTP/2 は "ホップ・バイ・ホップ" のヘッダーフィールドを示す Connection ヘッダーフィールドを使用しません。このプロトコルでは、接続に固有なメタデータを他の方法で転送します。そのため、Connection を含む HTTP/2 メッセージは不正な形式 (8.1.2.6節)として扱われなければなりません (MUST)。
このことは、HTTP/1.x メッセージを HTTP/2 に変換する中継者が、Connection ヘッダーフィールドとそこで指定されたヘッダーフィールドを削除する必要があることを意味します。このような中継者は、Connectionで指定されていなくてもKeep-Alive、Proxy-Connection、Transfer-Encoding、そして Upgrade といった接続に固有な他のヘッダーフィールドを削除すべきです (SHOULD)。
これに関する一つの例外は、TE ヘッダーフィールドです。このフィールドは HTTP/2 リクエストに存在してもよい (MAY) ものとしていますが、"trailers" 以外の値を含んではいけません (MUST NOT)。
注: HTTP/2 は他のプロトコルへのアップグレードに意図的に対応しません。3章で説明したハンドシェイク方式は、他のプロトコルの使用をネゴシエートするのに十分と考えられています。
HTTP/2 はリクエスト対象の情報を転送するコロン ':' 文字で始まるいくつかの擬似ヘッダーフィールドを定義します:
":authority" ヘッダーフィールドは、対象 URI の authority 部 ([RFC3986]、3.2節) を含みます。authority には、非推奨となった "http" や "https" URI のサブコンポーネントの "userinfo" を含めてはいけません (MUST NOT)。
HTTP/1.1 リクエスト行を正確に再現できることを保証するために、origin や asterisk 形式 ([RFC7230]、5.3節) のリクエストターゲットを持つ HTTP/1.1 リクエストから変換するときには、このヘッダーフィールドは省略されなければなりません (MUST)。HTTP/2 リクエストを直接生成するクライアントは、代わりに "Host" ヘッダーフィールドを省略するべきです (SHOULD)。HTTP/2 リクエストを HTTP/1.1 に変換する中継者は、"Host" ヘッダーフィールドが存在しない場合は、":authority" ヘッダーフィールドの値をコピーして "Host" ヘッダーフィールドを生成しなければなりません (MUST)。
":path" ヘッダーフィールドは、対象 URI のパス部とクエリー部 ([RFC3986] の "絶対パス" および、クエリーが後に続く任意の '?' 文字、[RFC3986]、3.3節と[RFC3986]、3.4節) を含みます。asterisk 形式のリクエストは ':path' ヘッダーフィールドに '*' を値として含みます。
このフィールドは、"http" や "https" の URI では空であってはいけません (MUST NOT)。またパスコンポーネントを含まない "http" や "https" の URI では値に '/' を含めなければなりません (MUST)。このルールの例外には、パスコンポーネントを含まない "http" や "https" の URI への OPTIONS リクエストがあります。これらのリクエストは '*' を値に設定 ([RFC7230]、5.3.4節) した ":path" ヘッダーフィールドを含まなければなりません (MUST)。
全ての HTTP/2 リクエストは、CONNECT リクエスト (8.3節) である場合を除き、":method"、":scheme"、そして ":path" ヘッダーフィールドに有効な値を1つ含まなければなりません (MUST)。これらのヘッダーフィールドが省略された HTTP リクエストは不正な形式 (8.1.2.6節) です。
HTTP/2 では、HTTP/1.1 のリクエスト行に含まれるバージョン識別子を伝達する方法を定義しません。
":status" ヘッダーフィールドは、 HTTP ステータスコードフィールド ([RFC7231]、6節) を伝達するために定義されます。このヘッダーフィールドは全てのレスポンスに含まれなければなりません (MUST) が、これを含まないレスポンスは不正な形式 (8.1.2.5節) です。
HTTP/2 では、HTTP/1.1 のステータス行に含まれるバージョンや理由フレーズを伝達する方法を定義しません。
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
不正な形式のリクエストやレスポンスとは、有効な一連の HTTP/2 フレームである一方で、無関係なフレームや禁止されたヘッダーフィールドが存在したり、必須のヘッダーフィールドが存在しない、大文字のヘッダーフィールド名が含まれているなどの理由で無効になるものです。
エンティティボディを持つリクエストやレスポンスは "content-length" ヘッダーフィールドを含むことができます。常に DATA フレームを含まない HEAD リクエストへのレスポンスを除き、ボディを構成する DATA フレームペイロードの長さの合計が "content-length" ヘッダーフィールドの値と等しくない場合、リクエストやレスポンスは不正な形式になります。
HTTP のリクエストやレスポンスを処理する中継者 (つまり、トンネルとして機能しない全ての中継者) は、不正な形式のリクエストやレスポンスを転送してはいけません (MUST NOT)。不正な形式のリクエストやレスポンスが検出された場合、PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。
サーバーは不正な形式のリクエストについて、ストリームを終了したり、リセットをする前に HTTP レスポンスを送信してもよいものとします (MAY)。クライアントは不正な形式のレスポンスを受け入れてはいけません (MUST NOT)。これらの要件は、HTTP に対する一般的な攻撃手法の一部からの保護を意図していることに注意してください。寛容であることは、実装の脆弱性を晒すことにもなるため、用心深く、厳格でなければなりません。
この節では、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} content-type = image/jpeg CONTINUATION + END_HEADERS host = example.org :scheme = https 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}
Trailing ヘッダーフィールドは、リクエストやレスポンスヘッダーブロックと、全ての DATA フレームが送信された後に、ヘッダーブロックとして送信されます。トレイラーヘッダーブロックを開始する HEADERS フレームには END_STREAM フラグが設定されます。
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
101 以外の 1xx ステータスコードを使用する情報提供レスポンスは HEADERS フレームとそれに続く0個以上の CONTINUATION フレームとして転送されます。
HTTP/1.1 103 BAR HEADERS Extension-Field: bar ==> - END_STREAM + END_HEADERS :status = 103 extension-field = bar
HTTP/1.1 においてエラーが発生した際は、エラーの原因を特定する手段が存在しないため、HTTP クライアントは冪等でないリクエストの再試行をおこなうことができませんでした。もしリクエストが再試行されると、エラーが発生する前に進めたサーバー処理が望ましくない結果になってしまう可能性があるでしょう。
HTTP/2 はリクエストが処理されたことをクライアントに保証するために、2つのメカニズムを提供します:
処理されなかったリクエストは失敗ではありません。クライアントはそのリクエストが冪等でないメソッドであっても、それらを自動的に再施行してもよいものとします (MAY)。
ストリームが処理されていないという事をサーバーが保証できない限り、サーバーはそのことを示してはいけません (MUST NOT)。ストリーム上にあるフレームがアプリケーションレイヤーに渡された場合、そのストリームに対して REFUSED_STREAM を使用してはいけません (MUST NOT)。そして GOAWAY フレームは、アプリケーションレイヤーに渡されたフレームのストリームID以上の値を含まなければなりません (MUST)。
これらのメカニズムに加え、PING フレームはクライアントがコネクションを簡単にテストする方法を提供します。いくつかのミドルボックス (例として、ネットワークアドレス変換器やロードバランサーなどがあります) が静かにコネクションを破棄するため、アイドルとして残っているコネクションは破壊されることがあります。PING フレームは、クライアントがリクエストを送信することなく、コネクションが有効かどうかを安全にテストすることを可能にします。
HTTP/2 では、単一のリクエストに対するレスポンスにおいて、1つ以上の関連するレスポンスをサーバーがクライアントに先行送信 (または "プッシュ") することを可能にします。最初のリクエストのレスポンスをクライアントが完全に処理するために、関連するレスポンスを用意する必要があることをサーバーが知っている場合、この機能は特に有益です。
追加レスポンスのプッシュは任意であり、個々のエンドポイントの間でやり取りされます。サーバープッシュが無効であることを示すために、SETTINGS_ENABLE_PUSH 設定には 0 を設定できます。
レスポンスのプッシュはホップ間で有効であり、中継者はサーバーからプッシュされたレスポンスを受信し、クライアントにそれらを転送しないことを選択することができます。言い換えれば、プッシュされたレスポンスをどのように扱うかは、中継者に任されています。中継者は、サーバーによる動作なしに、クライアントに追加のレスポンスをプッシュすることもできます。
クライアントはプッシュすることはできません。したがって、サーバーは PUSH_PROMISE フレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません。クライアントは、PROTOCOL_ERROR のコネクションエラー (5.4.1節) としてメッセージを扱うことで、SETTINGS_ENABLE_PUSH 設定を 0 以外の値に変更しようとする試みを拒否しなければなりません (MUST)。
サーバーはキャッシュ可能 ([RFC7234]、3節) なレスポンスのみをプッシュすることができます。予約リクエストは安全 ([RFC7231]、4.2.1節) でなければならず (MUST)、リクエストボディを含んではいけません (MUST NOT)。
サーバープッシュは、リクエストに対してサーバーがレスポンスを返すことと意味的に等しくなります。この時のリクエストはサーバーにより 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)" 状態にします。
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 の送信を禁止するわけではありません。その場合、クライアントは必要のない予約済みのストリームをリセットする必要があります。
プッシュレスポンスを受信するクライアントは、サーバーがレスポンスを提供することが許可されていることを検証しなければなりません (MUST)。10.1節を参照してください。例えば、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 フラグを設定したフレームを送信してはいけません。
HTTP/1.x において、擬似メソッド CONNECT ([RFC7231]、4.3.6節) は HTTP 接続をリモートホストへのトンネルに変換するために使用されます。CONNECT は、"https" リソースをやりとりする目的でオリジンサーバーと TLS セッションを確立するために、主に HTTP プロキシと共に使用されます。
HTTP/2 における CONNECT メソッドは、同様にリモートホストへの単一の HTTP/2 ストリーム上にトンネルを確立するために使用されます。HTTP ヘッダーフィールドのマッピングは、一部のヘッダーを除きリクエストヘッダーフィールド (8.1.2.3節)に定義されたように動作します。一部のヘッダーについては、具体的には以下のようになります。
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)。
この章では、相互運用性を向上する HTTP プロトコルの属性や、既知のセキュリティ脆弱性に対象する方法、実装差異が起こる可能性を減らす方法などについて説明します。
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)。その結果、両方のエンドポイントは先に送信したフレームが処理されて適切に完了したのか、それとも残りの必要なタスクが中断されたのかを期待通りに確認できます。
クライアントは、サーバーが信頼できる場合に限り、複数の異なる authority コンポーネントの URI に対するリクエストの送信に、単一のサーバーコネクションを使用してもよいものとします (MAY)。"http" リソースについては、同一のIPアドレスとして解決されるホストに依存します。
"https" リソースの場合、コネクションの再利用はさらに、URI におけるホストに対して有効な証明書を持つかどうかに依存します。これはつまり、複数の "subjectAltName" 属性やワイルドカード名を持つサーバー証明書を使用することになります。例えば、"subjectAltName" が "*.example.com" の証明書は、"a.example.com" と "b.example.com" について同一のコネクションの使用を許可するかもしれません。
いくつかのデプロイにおいては、複数のオリジンに対するコネクションの再利用が、誤ったオリジンサーバーへのリクエストの送信につながる可能性があります。例えば TLS の終端が、オリジンサーバーの選択に TLS Server Name Indication (SNI) [TLS-EXT] を使用するミドルボックスによっておこなわれている可能性があります。これは、サーバーが適切な証明書を持っていたとしても、リクエスト対象として意図していないサーバーに対して、クライアントが機密情報を送信してしまう可能性があることを意味します。
クライアントにおけるコネクションの再利用を望まないサーバーは、リクエストに対して 421 (Not Authoritative ステータスコード) をレスポンスとして返すことで、リクエストの権限がないことを示すことができます。
421 (Not Authoritative) ステータスコードは、[RFC7230]、9.1節にあるように、現在のオリジンサーバーが、リクエストされたリソースの権限を持たないことを示します (10.1節もあわせて参照してください)。
サーバーから 421 (Not Authoritative) レスポンスを受信したクライアントは、リクエストメソッドが冪等であるかどうかに関わらず、異なるコネクションを通じてリクエストを再施行してもよいものとします (MAY)。これは、コネクションが再利用 (9.1.1節) されていたり、代替サービス ([ALT-SVC])が選択されていたりする場合でも可能です。
このステータスコードは、プロキシから生成されてはなりません (MUST NOT)。
明示的なキャッシュ制御 ([RFC7234]、4.2.2節)や、メソッドの定義により示されない限り、421 レスポンスはデフォルトでキャッシュ可能です。
HTTP/2 の実装は、TLS 上の HTTP/2 のために TLS 1.2 [TLS12] に対応しなければなりません (MUST)。HTTP/2 固有のいくつかの追加制限と共に、[TLSBCP] の一般的な TLS の利用ガイダンスには従うべきです (SHOULD)。
TLS 上の HTTP/2 の実装は、この節で述べられる機能セットの制限と暗号スイートと共に TLS 1.2 以上を使用しなければなりません (MUST)。実装上の制限により TLS ネゴシエーションを失敗できない可能性もあります。エンドポイントは、最小要件を満たしていない HTTP/2 コネクションを INADEQUATE_SECURITY のコネクションエラー (5.4.1節) と共に、速やかに終了しなければなりません (MUST)。
TLS の実装は、TLS の Server Name Indication (SNI) [TLS-EXT] に対応しなければなりません (MUST)。HTTP/2 クライアントは、TLS ネゴシエーションの際に対象のドメイン名を示さなければなりません (MUST)。
TLS の実装は圧縮を無効化にしなければなりません (MUST)。TLS 圧縮は本来は明らかにされない情報 [RFC3749] の漏洩につながります。HTTP/2 は、コンテキストを意識した圧縮機能を提供しているため一般的な圧縮は必要ありません。それゆえこの圧縮機能は、パフォーマンス、セキュリティ、その他の理由から、より一層利用に適していると言えるでしょう。
TLS の実装は再ネゴシエーションを無効にしなければなりません (MUST)。エンドポイントは TLS 再ネゴシエーションを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。再ネゴシエーションを無効化すると、使用する暗号スイートが暗号化できるメッセージの数の制限により、長時間の接続は使用できなくなる可能性があることに注意してください。
クライアントは、ハンドシェイクにおいて提示するクライアント証明書の機密保護のために再ネゴシエーションを使用してもよいものとします (MAY)。しかし、いかなる再ネゴシーエションも、コネクションプリフェイスの送信前におこなわなければなりません (MUST)。サーバーは、コネクションを確立した後すぐに再ネゴシエーション要求がされた場合は、クライアント証明書を要求すべきです (SHOULD)。
これは実質的に、特定の保護されたリソースに対するリクエストのレスポンスにおける再ネゴシエーションの使用を防止します。将来の仕様では、このユースケースに対応する異なる方法を提供するかもしれません。
HTTP/2 において許可される TLS 暗号スイートのセットは限定的です。HTTP/2 では、ephemeral Diffie-Hellman (DHE) [TLS12] や elliptic curve variant (ECDHE) [RFC4492] などの ephemeral key exchange に対応する暗号スイートのみが使用されなければなりません (MUST)。ephemeral key exchange は、最低でも2048ビットの DHE か、128ビットのセキュリティレベルの ECDH でなければなりません (MUST)。クライアントは 4096 ビットまでのサイズの DHE を受け入れなければなりません (MUST)。HTTP はストリーム暗号またはブロック暗号を使用する暗号スイートを使用してはなりません (MUST NOT)。AES の Galois Counter Model (GCM) モード [RFC5288] のような Authenticated Encryption with Additional Data (AEAD) モードは受け入れ可能です。
TLS 1.2 の実装は、提供する暗号スイートとして HTTP/2 では許可されないセットを持つ可能性があり、TLS 1.2 が必須とした暗号スイートの使用を妨げることになるため、これらの制限に影響します。この問題を避けるため、TLS 1.2 を使用する HTTP/2 の実装は、P256 曲線 [FIPS186] を使用した TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] に対応しなければなりません (MUST)。
クライアントは、HTTP/2 に対応しないサーバーへの接続を想定することを目的として、上記の制限により禁止された暗号スイートへの対応を通知してもよいものとします (MAY)。これは、フォールバックのために別の接続を使用することにより生じる追加のレイテンシなしに、このような制限のないプロトコルへのフォールバックを可能にします。
クライアントは、リソースに対する権限のあるサーバーからの HTTP/2 レスポンスのみを受け取ることができます。これは、レスポンスを受け取る前にクライアントが PUSH_PROMISE を検証するサーバープッシュ (8.2節) においては特に重要です。
HTTP/2 は、サーバーが対象のリソースの提供する権限があるかどうかを判定するために HTTP/1.1 の権限の定義に依存しています。[RFC7230]、9.1節を参照してください。"http" URI スキームではローカル名前解決、"https" スキームでは信頼されたサーバー識別子 ([RFC2818]、3章) にそれぞれ依存します。
信頼できないサーバーが提供するリソースは、クライアントは破棄しなければなりません (MUST)。
クロスプロトコル攻撃では、攻撃者は異なるプロトコルを解釈するサーバーに対して、クライアントに最初のプロトコルでトランザクションを開始させます。これにより、攻撃者は第二のプロトコルの有効なトランザクションのように見えるトランザクションを開始できるかもしれません。Web コンテキストの機能と組み合わせることで、これはプライベートネットワーク内の不十分な保護下にあるサーバーと通信をするために使用できます。
HTTP/2 の ALPN 識別子と共に TLS ハンドシェイクを完了することは、クロスプロトコル攻撃に対して十分な保護になると考えられます。ALPN は他の TLS ベースのプロトコルへの攻撃を防ぎ、サーバーが HTTP/2 を処理するための前向きな意思表示を提供します。
TLS の暗号化は、攻撃者が平文プロトコル上でクロスプロトコル攻撃に使用するようなデータの制御を難しくします。
平文バージョンの HTTP/2 はクロスプロトコル攻撃に対する最低限の保護しか持ちません。コネクションプリフェイス (3.5節) は HTTP/1.1 サーバーを混乱させるように設計された文字列を含みますが、他のプロトコルに対する特別な保護を提供しません。クライアントコネクションプリフェイスに加えて、Upgrade ヘッダーフィールドを含む HTTP/1.1 リクエストの一部を無視する意思のあるサーバーは、クロスプロトコル攻撃にさらされる可能性があります。
HTTP/2 ヘッダーフィールドの名前と値は、長さプレフィクスのあるオクテット列にエンコードされます。これは HTTP/2 が、ヘッダーフィールドの名前や値として、いかなる文字列オクテットの送信も可能にします。HTTP/2 のリクエストやレスポンスを HTTP/1.1 に直接変換する中継者は、不正な HTTP/1.1 メッセージを生成することが可能です。攻撃者は、不正なヘッダーフィールドや追加のヘッダーフィールドを含む HTTP/1.1 メッセージや、完全に改竄された新しいメッセージの生成を中継者が引き起こすよう、この振る舞いを利用するかもしれません。
特に、行頭復帰 (ASCII 0xd) や改行 (ASCII 0xa) などの HTTP/1.1 では認められていない文字を含むヘッダーフィールドの名前や値は、[RFC7230]、3.2.4節で規定されているように、中継者により逐語的に変換されてはいけません (MUST NOT)。
HTTP/1.x から HTTP/2 への変換では、攻撃者に同様の機会を与えません。HTTP/2 に変換する中継者は、ヘッダーフィールドの値からいかなる "obs-fold" な文字を削除しなければなりません (MUST)。
プッシュレスポンスとはクライアントからの明確なリクエストがないレスポンスです。リクエストは PUSH_PROMISE フレームによりサーバーから提供されます。
プッシュされたレスポンスのキャッシュは可能です。これはオリジンサーバーの Cache-Control ヘッダーフィールドが提供する指示に基づいておこなわれます。しかしながら、1つのサーバーホストが複数のテナントを提供する場合は、問題を引き起こす可能性があります。例えば、サーバーは複数のユーザーにそれぞれ URI 空間の一部を提供するかもしれません。
複数のテナントが同一サーバーの空間を共有する場合、サーバーは、テナントがリソースの権限を超えてキャッシュをプッシュしないことを保証しなければなりません (MUST)。これを強制しなければ、権限のあるテナントが提供する実際のキャッシュを上書きし、本来のキャッシュの外で提供されたキャッシュを、サーバーが提供することが可能になってしまいます。
権限のないオリジンサーバー (10.1節) のプッシュレスポンスを、使用したりキャッシュすることはありません。
HTTP/2 接続は、HTTP/1.1 接続よりも機能のためにより大きなリソースの割り当てを要求します。ヘッダー圧縮およびフロー制御の使用はより多くの状態を保持するため、リソースの割り当てに依存します。これらの機能の設定は、各機能に対するメモリーの割り当てを厳密に制限することを保証します。
PUSH_PROMISE フレームの数は、同様の方法では制限できません。サーバープッシュを受け入れるクライアントは、"reserved (remote)" 状態にできるストリームの数を制限すべきです (SHOULD)。極端な数のサーバープッシュストリームは、ENHANCE_YOUR_CALM のストリームエラー (5.4.2節) として扱うことができます。
処理能力については、状態容量ほどより効果的に保護することはできません。
SETTINGS フレームは、ピアに追加の処理時間を発生させるために悪用される可能性があります。これは、無意味な SETTINGS パラメーターの変更や複数の未定義のパラメーターの変更、同一フレームにおいて同じ設定を複数回変更をするなどで起こる可能性があります。同様に、WINDOW_UPDATE や PRIORITY フレームも、無駄なリソースの消費を引き起こすために悪用される可能性があります。
小さな、または空の大量のフレームは、ピアにフレームヘッダーの処理時間を消費させるために悪用される可能性があります。用途によっては、ストリームを終了させるために空の DATA フレームを送信するといった、正しい方法でも使われることに注意してください。
ヘッダー圧縮も、処理リソースを浪費するいくつかの機会を提供します。悪用の可能性についての詳細は [COMPRESSION] の8章を参照してください。
SETTINGS パラメーターの制限では、直ちに処理を軽減させることはできません。エンドポイントは、ピアが新しく設定しようとした制限値を超えられる状況に晒されたままです。特にコネクションが確立した直後は、サーバーによって設定される制限値がクライアントに通知されておらず、その場合明らかにプロトコル違反にならずに制限値を超えることが可能です。
SETTINGS の変更、小さなフレーム、ヘッダー圧縮といった、これらの全ての機能には正当な用途があります。これらの機能は、不必要に利用されたり、過剰に使用されたりした時に限り、負荷になります。
この動作を監視しないエンドポイントは、自分自身をサービス拒否攻撃のリスクに晒すことになります。実装は先に述べたような特徴を追跡し、それらの使用に制限を設定すべきです (SHOULD)。エンドポイントは、不審な挙動を ENHANCE_YOUR_CALM のコネクションエラー (5.4.1節) として扱ってもよいものとします (MAY)。
巨大なヘッダーブロック (4.3節) は、実装に大量の状態をコミットしてしまう可能性があります。サーバーや中継者では、":authority" や ":path"、":scheme" といったルーティングに重要なヘッダーフィールドが、ヘッダーブロックの早い段階で出現することが保証されていません。特に、リファレンスセットにある値は、そのヘッダーブロックの最後まで出現しません。
これは、中継者などからの最終的な宛先に対するヘッダーフィールドのストリーミングを妨げ、エンドポイントにヘッダーブロックの全てをバッファすることを強制します。ヘッダーブロックのサイズに強い制限はないため、エンドポイントは利用可能なメモリを使い果たすことを強いられる可能性があります。
エンドポイントは、ヘッダーブロックのサイズに適用される可能性がある制限をピアに通知する、SETTINGS_MAX_HEADER_LIST_SIZE を使用できます。この設定はアドバイザリーなものであるため、エンドポイントは、そのリクエストやレスポンスが不正な形式として扱われるリスクを負って、制限を超えるヘッダーブロックを送信してもよいものとします (MAY)。この設定はホップ間で通知されるため、リクエストやレスポンスはより低い制限や不明な制限のあるホップに遭遇する可能性があります。中継者は、この問題を避けるために異なるピアが与えた値の通知を試みることができますが、そのようにする義務はありません。
許容できない巨大なヘッダーブロックを受信したサーバーは HTTP 431 (Request Header Fields Too Large) ステータスコード [RFC6585] を送信できます。クライアントは処理できないレスポンスを破棄できます。そのコネクションが終了されない限り、ヘッダーブロックは一貫性のあるコネクションの状態を維持するために処理されなければなりません (MUST)。
HTTP/2 はヘッダーフィールド (4.3節) とエンティティボディの両方の圧縮のより多く利用します。圧縮は、攻撃者の制御下でかつ同じコンテキストで圧縮された場合に、攻撃者による機密データの復元を可能にします。
Web の特性を利用した圧縮に関する攻撃手法 (例: [BREACH]) もあります。攻撃者は様々な平文を含む複数のリクエストを誘発し、得られた各暗号テキストの長さを観測します。推測した機密が正しければ、その長さは短くなります。
保護されたチャンネル上で通信する実装は、各データソースに異なる圧縮辞書を使わない限り、機密と攻撃者が制御するデータの両方を含む内容を圧縮してはいけません (MUST NOT)。データソースが確実に判断できない場合は、圧縮を使用してはいけません (MUST NOT)。
ヘッダーフィールドの圧縮に関するさらなる考察は、[COMPRESSION] で述べられています。
HTTP/2 におけるパディングは、TLS [TLS12] により提供されるような一般的なパディングの置き換えを意図していません。冗長なパディングは逆効果にもなり得ます。正しいアプリケーションであるかどうかは、パディングされたデータに関する特別な情報を持つことによって決まります。
圧縮を利用した攻撃を軽減するための圧縮機能の無効化や制限は、対抗策としてのパディングよりも適しているかもしれません。
パッディングはフレームの内容の正確なサイズをわかりにくくするために使用でき、HTTP の特定の攻撃を軽減するために提供されます。例えば、攻撃者により制御されたプレーンテキストと機密データを含む圧縮コンテンツにおける攻撃 ([BREACH] の例を参照してください) があります。
パディングの使用は、一見してわかる防御よりも結果的に弱い防御に終わることがあります。パディングは攻撃者が観察しなければならないフレームの数を増加させることで、長さ情報の推測をより困難にすることしかできません。不適切に実装されたパディングの構造は、簡単に破られる可能性があります。
特に予測可能な分布によるランダムなパッディングは、非常にわずかな保護しか提供できません。同様に、パディングペイロードを固定サイズにすることは、ペイロードサイズをその固定サイズの境界を超えるように変更することで、情報を漏洩させます。これは攻撃者がプレーンテキストの制御が可能な場合に起こりえます。
中継者は DATA フレームのパディングを維持すべきです (SHOUD)。しかしながら、HEADERS や PUSH_PROMISE フレームのパディングは削除してもよいものとします (MAY)。中継者がフレームのパディングの量を変更する正当な理由は、パディングが提供する保護を改善することにあります。
HTTP/2 のいくつかの特徴は、時間をかけてサーバーやクライアントの関連する動作を観測する機会を提供します。これには、設定の値やフロー制御ウインドウの管理方法、優先度がストリームに割り当てられる方法、攻撃に対する反応のタイミング、任意の機能の扱いなどを含みます。
観測可能な振る舞いの違いを生み出す限り、[HTML5] の1.8節で定義されているように、特定クライアントのフィンガープリントの取得に使用することができてしまいます。
HTTP/2 を識別するための文字列は、[TLS-ALPN] に記載される "Application Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリに登録されます。
この文書では、フレームタイプ、設定、そしてエラーコードのレジストリを制定します。これらの新しいレジストリは、新しい "Hypertext Transfer Protocol (HTTP) 2 Parameters" の章に追加されます。
この文書では HTTP で使用する "HTTP2-Settings" ヘッダーフィールドと、421 (Not Authoritative) ステータスコードを登録します。
この文書では、コネクションプリフェイス (3.5節) との衝突を防ぐために HTTP で使用する "PRI" メソッドを登録します。
この文書は [TLS-ALPN] に記載される "Application Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリにおける HTTP/2 識別子の登録について制定します。
文字列 "h2" は TLS 上で使用される HTTP/2 を識別します。
文字列 "h2c" は平文 TCP 上で使用される HTTP/2 を識別します。
この文書は HTTP/2 フレームタイプコードのレジストリを制定します。"HTTP/2 Frame Type" レジストリは8ビットの空間を管理します。"HTTP/2 Frame Type" レジストリは "IETF Review" や "IESG Approval" ポリシー [RFC5226] の下で、0x00 から 0xef までの値の範囲で運用されます。なお、0xf0 から 0xff までの値は実験的な利用のために予約されます。
このレジストリの新しいエントリーには、以下の情報が要求されます。
以下のテーブルのエントリはこの文書で登録されます。
+---------------+------+--------------+ | 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 | +---------------+------+--------------+
この文書は HTTP/2 設定のレジストリを制定します。"HTTP/2 Settings" レジストリは16ビットの空間を管理します。"HTTP/2 Settings" レジストリは "Expert Review" ポリシー [RFC5226] の下で、0x0000 から 0xefff までの値の範囲で運用されます。なお、0xf000 から 0xffff までの値は実験的な利用のために予約されます。
新しい登録には、以下の情報を提供することが推奨されます。
登録設定の初期セットは、6.5.2節に記載されています。
+------------------------+------+---------------+---------------+ | 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 | 65536 | Section 6.5.2 | | MAX_HEADER_LIST_SIZE | 0x6 | (infinite) | Section 6.5.2 | +------------------------+------+---------------+---------------+
この文書は HTTP/2 エラーコードのレジストリを制定します。"HTTP/2 Error Code" レジストリは32ビットの空間を管理します。 "HTTP/2 Error Code" レジストリは、"Expert Review" ポリシー [RFC5226] に従って運用します。
エラーコードの登録には、そのエラーコードの説明を含める必要があります。専門のレビュアーは新規の登録が既存のエラーコードと重複可能かについて検討することを推奨します。既存の登録の使用は推奨されますが、義務ではありません。
新しい登録は以下の情報の提供が推奨されます。
以下のテーブルのエントリはこの文書で登録されます。
+---------------------+------+----------------------+---------------+ | 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 | | +---------------------+------+----------------------+---------------+
この節は、"HTTP2-Settings" ヘッダーフィールドを Permanent Message Header Field Registry [BCP90] に登録します。
この節は、"PRI" メソッドを HTTP Method Registry ([RFC7231]、8.1節) に登録します。
この文書は 421 (Not Authoritative) HTTP ステータスコードを Hypertext Transfer Protocol (HTTP) Status Code Registry ([RFC7231]、8.2節) に登録します。
この文書は、以下の個人からの多くの意見を含んでいます:
この章は公開前に RFC 編集者により削除されます。