この文書は「Hypertext Transfer Protocol version 2 (draft-ietf-httpbis-http2-13)」の日本語訳です。

原文の最新版 は、この日本語訳が参照した版から更新されている可能性があります。
原文はドラフト版であり、HTTP/2 は現在策定中の仕様であることに十分注意してください。
この日本語訳は参考情報であり、正式な文書ではないことにも注意してください。また、翻訳において生じた誤りが含まれる可能性があるため、必ず原文もあわせて参照することを推奨します。

公開日:
2014-06-24
更新日:
2014-07-24
翻訳者:
Moto Ishizawa <>
翻訳協力:
Shigeki Ohtsu

概要

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

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

編集者ノート (RFC 編集者により今後削除されます)

この草案の議論は [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ヶ月間有効な草案文書であり、いかなる時でも更新や置き換え、他の文書により廃止されることがあります。また、参考資料としてインターネット草案を使用したり、"進行中の作業" としてではなく引用をするのは不適切です。

このインターネット草案は2014年12月19日に期限切れとなります。

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.

目次

1. はじめに

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 接続を利用することになるため、よりネットワークフレンドリーな設計となります。これは他のフローとの競合を減らし、接続寿命が長くなることを意味します。そして結果的に、利用可能なネットワークキャパシティの有効利用につながることになります。

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

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

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 リクエストは非常に冗長なため、圧縮によりリクエストとレスポンスのサイズを著しく削減できます。

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

最後に、"ゲートウェイ"、"中継者"、"プロキシ" そして "トンネル" は [RFC7230] の2.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 で異なることを意味します。"https" URI のための認識は3.2節で説明します。また、"http" URI のための認識は3.3節で説明します。

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

この文書で定義されるプロトコルの識別子は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] メーリングリストで各実験についての調整をすることをお勧めします。

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

HTTP/2 への対応に関する事前知識なしに "http:" URI にリクエストをするクライアントは、HTTP Upgrade メカニズムを使用します ([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) レスポンスと共に Upgrade を受け入れます。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はレスポンスのために使用されます。

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

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 パラメーターのデフォルト値を必要としません。そして、クライアントがサーバーからフレームを受信するよりも前に、他のパラメーターを送信できる機会を持てるようになります。

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

HTTP/2 の対応を事前に知らずに "https" URI へのリクエストをするクライアントは、 TLS [TLS12] と Application layer protocol negotiation extension [TLSALPN] を利用します。

TLS 上の HTTP/2 は "h2" アプリケーショントークンを使用します。"h2c" トークンはクライアントから送信されたり、サーバーにより選択されてはなりません (MUST NOT)。

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

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

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

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

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

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

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

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

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

どちらかのピアが、正しいコネクションプリフェイスを使って通信を開始しない場合は、クライアントとサーバーは TCP 接続を切断しなければなりません (MUST)。そのピアが HTTP/2 を使用していないことが明らかな場合には、GOAWAY フレーム (6.8節) は省略できます。

4. HTTP フレーム

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

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

全てのフレームは、8オクテット固定長のヘッダーから始まり、0から16,383オクテットのペイロードが続きます。

 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 |     Length (14)           |   Type (8)    |   Flags (8)   |
+-+-------------+---------------+-------------------------------+
|R|                 Stream Identifier (31)                      |
+=+=============================================================+
|                   Frame Payload (0...)                      ...
+---------------------------------------------------------------+

                         フレームレイアウト

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

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

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

4.2. フレームサイズ

フレームペイロードの最大サイズはフレームタイプにより異なります。フレームペイロードの絶対的な最大サイズは 2^14-1 (16,383) オクテットです。これはつまり、フレームの最大サイズは 16,391 オクテットであることを意味します。全ての実装は、最大サイズまでのフレームを受信し、最低限の処理が可能でなければなりません (MUST)。

PING (6.7節) のような特定のフレームタイプでは、ペイロードデータのサイズについて追加の制限を加えます。同様に追加のサイズ制限は、特定アプリケーション用途 (9章) により設定できます。

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

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

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

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

HTTP ヘッダー圧縮はヘッダーフィールドの対応する順序を保持しません。複数の値を持つヘッダーフィールドは、特別な区切り文字を使用して単一のヘッダーフィールドにエンコードされます (8.1.3.3節)。なお、このヘッダーフィールドの値の相対的な順序は保持されます。

Cookie ヘッダーフィールド [COOKIE] は HTTP マッピングにより特別に処理されます (8.1.3.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)。

5. ストリームと多重化

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

5.1. ストリームの状態

ストリームのライフサイクルは、図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

全てのストリームは "idle" 状態からはじまります。この状態ではフレームは交換されません。

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

  • HEADER フレームの送信や受信は、ストリームを "open" 状態にします。5.1.1節で説明されるようにストリームIDが選択されます。同一の HEADERS フレームはストリームをすぐに "half closed" にする可能性があります。
  • PUSH_PROMISE フレームの送信は、今後使用される関連ストリームであることを示します。予約済みストリームの状態は "reserved (local)" に遷移します。
  • PUSH_PROMISE フレームを受信は、リモートピアにより予約された関連ストリームであることを示します。このストリームの状態は "reserved (remote)" に遷移します。
reserved (local)

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

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

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

この状態において、エンドポイントは HEADERS または RST_STREAM 以外のフレームを送信してはいけません。(MUST NOT)。

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

reserved (remote)

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

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

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

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

HEADERS や RST_STREAM フレーム以外の受信については、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" に遷移します。

受信者は、END_STREAM フラグが設定されたフレームを送信した後の短時間に到着する可能性がある WINDOW_UPDATE をこの状態では無視できます。

この状態で受信する PRIORITY フレームは、現在のストリームに依存するストリームの再優先度付けに使用されます。

half closed (remote)

"half closed (remote)" 状態のストリームは、もはやピアによるフレームの送信には使用されません。この状態において、エンドポイントがフロー制御している場合でも、受信者のフロー制御ウインドウを保持する必要はありません。

エンドポイントが、この状態にあるストリームから WINDOW_UPDATE や PRIORITY、RST_STREAM フレーム以外の追加のフレームを受信した場合は、STREAM_CLOSED のストリームエラー (5.4.2節) を返さなければなりません (MUST)。

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

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)。

5.1.1. ストリームID

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

HTTP/2 に Upgrade する HTTP/1.1 リクエスト (3.2節) には、ストリームID 1 (0x1) で応答されます。Upgrade の完了後、ストリーム 0x1はクライアントに対して "half closed (local)" になります。したがって、HTTP/1.1 から Upgrade するクライアントが、ストリーム 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 フレームを送信できます。

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 フレームを受信したエンドポイントは、それをストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

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

5.2. フロー制御

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

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

5.2.1. フロー制御の原則

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

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

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

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

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

この機能を必要としない構成では、新しいデータを受信した際に利用可能な容量を増加させるように最大サイズのフロー制御ウインドウを告知できます。これはそのような受信者において実質的にフロー制御を無効化します。反対に、送信者は常に受信者により通知されたフロー制御ウインドウの影響を受けます。

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

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

5.3. ストリームの優先度

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

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

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

[[CREF2: ストリームの依存関係はまだ実際に検証されていないことに注意してください。この理論は十分適切かもしれませんが、これらを送信する実装は現在は存在しません。これらが便利でなかったり、明らかに有害であることが判明した場合、実装はストリームの依存関係を生成しないように要求されます。]]

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

優先度情報は HEADERS フレームを使用して生成するストリームに明示的に指定したり、PRIORITY フレームを使用して変更できます。優先度情報の提供は任意です。特に指示がない場合は、デフォルトの値が使用されます (5.3.5節)。

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

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

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

他のストリームの依存するストリームは依存ストリームです。ストリームが依存する先のストリームは、親ストリームとなります。

ストリームを他のストリームの依存関係に割り当てるとき、そのストリームは、親ストリームの新しい依存関係として追加されます。同じ親を共有する依存ストリームは、その順序をお互いに考慮しません。例えば、ストリーム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)。

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に依存するようになります。

  ?                ?                ?                 ?
  |               / \               |                 |
  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.3.4. 優先度付けの状態管理

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

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

例えば、まずストリーム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)。

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 は受信側エンドポイントで期待通りに受信されない可能性があります。コネクションエラーが発生した場合、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. コネクションの終了

ストリームが開かれている間、または half closed 状態の間に TCP 接続が破壊された場合、エンドポイントはストリームが異常終了し、不完全な状態にあると見なさなければなりません (MUST)。

5.5. HTTP/2 の拡張

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)。

6. フレーム定義

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

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

6.1. DATA

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 フレームは以下のフィールドを含みます:

Pad Length
オクテット単位のフレームパディングの長さを含む8ビットのフィールドです。このフィールドは任意であり、PADDED フラグが設定された場合にのみ存在します。
Data
アプリケーションデータ。フレームペイロードから、存在する他のフィールドの長さを引いた後の残りがデータの量になります。
Padding
アプリケーションにとって意味のある値を含まないパディングオクテットです。パディングオクテットは送信時には0を設定し、受信時には無視しなければなりません (MUST)。

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

END_STREAM (0x1)
ビット1は、エンドポイントが特定のストリームに送信する最後のフレームであることを示します。このフラグを設定することで、ストリームはいずれかの "half closed" 状態または "closed" 状態 (5.1節) に遷移します。
END_SEGMENT (0x2)
ビット2は、フレームが現在のセグメントの最後のフレームであることを示します。中継者はセグメントの境界を超えてフレームを結合してはいけません (MUST NOT)。また、フレームを転送する際にセグメントの境界を維持しなければなりません。
PADDED (0x8)
ビット4は、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オクテット大きくできます。

パディングの使用はセキュリティのための機能です。そのため、使用には注意が必要です。10.7節を参照してください。

6.2. HEADERS

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 フレームのペイロードは以下のフィールドを含みます:

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)
ビット1が設定されると、エンドポイントが特定のストリームに送信する最後のヘッダーブロック (4.3節) であることを示します。このフラグを設定することで、ストリームはいずれかの "half closed" 状態 (5.1節) に遷移します。
CONTINUATION フレームが後に続く HEADERS フレームは、ストリームの終了を知らせる END_STREAM フラグを転送します。CONTINUATION フレームは、ストリームを終了するために使用することはできません。
RESERVED (0x2)
ビット2は将来的な使用のために予約されます。
END_HEADERS (0x4)
ビット3は、このフレームの後には CONTINUATION フレームが続かず、このフレームに完全なヘッダーブロック (4.3節) が含まれていることを示します。
END_HEADERS フラグが設定されていない HEADERS フレームの後には、同一ストリームに CONTINUATION フレームが続かなければなりません (MUST)。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。
PADDED (0x8)
ビット4は、Pad Length フィールドが設定されていることを示します。
PRIORITY (0x20)
ビット6は 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節) における定義と全く同じです。

6.3. PRIORITY

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 フレームのペイロードは、以下のフィールドを含みます:

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 フレームは、"reserved (remote)"、"open"、"half-closed (local)"、"half closed (remote)"、そして "closed" のいずれかの状態のストリームに送信できます。ただし、1つのヘッダーブロック (4.3節)を構成する連続したフレームの間での送信はできません。このフレームは、処理の完了後やフレーム送信後に受信されることもあり、そのため現在のストリームには何も影響を与えない可能性があることに注意してください。"half closed (remote)" や "closed" 状態にあるストリームでは、このフレームは現在のストリームの処理にのみ影響し、ストリームの送信には影響を与えません。

PRIORITY フレームは "closed" 状態にあるストリームに送信できる唯一のフレームです。これは親ストリームの優先度を変更することで、依存ストリームのグループの再優先度付けを可能にします。しかしながら、PRIORITY フレームを終了したストリームに送信しても、ピアがそのストリームの優先度状態の情報を破棄した結果として無視される危険性があります。

6.4. RST_STREAM

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)。

6.5. SETTINGS

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

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

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

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

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

ACK (0x1)
ビット1が設定されると、フレームの受信を確認し、ピアの 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.5.1. SETTINGS フォーマット

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)                             |
+---------------------------------------------------------------+

                        設定フォーマット

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

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

SETTINGS_HEADER_TABLE_SIZE (0x1)
送信者が、リモートエンドポイントがヘッダーブロックのデコードに使用するヘッダー圧縮テーブルの最大サイズを通知することを可能にします。エンコーダーは、ヘッダーブロック内のヘッダー圧縮フォーマットにおいて特定の値を使用することで、この値以下の任意のサイズを選択できます。初期値は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)
ストリームレベルのフロー制御のための、送信者の初期ウインドウサイズ (バイト) を示します。初期値は65,535です。
この設定は、既存のストリームを含む、全てのストリームのウインドウサイズに影響します。6.9.2節を参照してください。
フロー制御ウインドウサイズの最大値である2^31 - 1を超える値は FLOW_CONTROL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません。

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

6.5.3. 設定の同期

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

SETTINGS フレームの値は、出現した順序で適用されなければなりません (MUST)。複数の SETTING 値を適応する間に他のフレームの処理してはいけません。全ての値を適用後、受信者は 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節に記述されています。

 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 フレームのペイロードは、以下のフィールドを含みます:

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

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

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

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節) における定義と全く同じです。

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)                         |
|                                                               |
+---------------------------------------------------------------+

                    PING ペイロードフォーマット

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

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

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

ACK (0x1)
ビット1は、この 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 フレームはクライアントとサーバーのどちらからでも送信できます。このフレームが送信されると、送信者は、最終ストリームIDに指定した値よりも大きいストリームIDをもつ、新しいストリームに送信されたフレームを無視します。GOAWAY フレームの受信者は、現在のコネクション上で新しい追加のストリームを開始してはいけません (MUST NOT)。しかし、新しいストリームを生成するために新しくコネクションを確立できます。

このフレームの目的は、以前確立したストリームの処理を終了している間であっても、エンドポイントが新しいストリームの受け入れを適切に停止できるようにすることです。これによりサーバーメンテナンスのような管理操作を可能にします。

新しくストリームを開始したエンドポイントと、GOAWAY フレームを送信したリモートの間には、固有の競合状態があります。このような場合に対処するため、GOAWAY は現在のコネクションで送信側エンドポイントが最後に処理した、または処理したと思われるストリーム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)。

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)。

 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" がこのフレームの対象がコネクション全体であることを示します。

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

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

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

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 フレームは、お互いに完全に非同期です。この特性は、ストリームの停止するのを防ぎ、送信者が保持するウインドウサイズを受信者が積極的に更新することを可能にします。

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

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)。

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

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

初期フロー制御ウインドウサイズを減少させる SETTINGS フレームの送信後、受信者にはフロー制御の制限を超えたストリームの処理について、2つの選択肢があります:

  1. 受信者は、対象のストリームに対して直ちに FLOW_CONTROL_ERROR エラーと共に RST_STREAM を送信できます。
  2. 受信者は、そのストリームを受け入れ、その結果として生じる行頭ブロッキングを許容し、データを消費した結果として WINDOW_UPDATE フレームを送信できます。

6.10. CONTINUATION

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 フレームは以下のフラグを定義します:

END_HEADERS (0x4)
ビット3は、ヘッダーブロック (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節) を満たしていません。

不明または未対応のエラーコードは、特別な反応を引き起こしてはなりません (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. メッセージヘッダー ([RFC7230]、3.2節) を含む1つの HEADERS フレーム (それに続く0個以上の CONTINUATION フレーム)
  2. メッセージペイロード ([RFC7230]、3.3節) を含む、0個以上の DATA フレーム
  3. 必要に応じて、トレイラー部 ([RFC7230]、4.1.2節) を含む1つの HEADERS フレームと、それに続く0個以上の CONTINUATION フレーム

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

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

他の状態であれば、フレームはストリーム上のこれらのフレームの間に点在してもよいものとします (MAY)。しかし、そのようなフレームは HTTP のセマンティクスを転送しません。特に、この一連のフレームの最初と任意である最後のフレーム以外の HEADERS フレーム (とその後の CONTINUATION フレーム) は HTTP のセマンティクスを転送しません。

他のフレームは、これらのフレームと交互に送受信してもよいものとします (MAY)。しかし、そのようなフレームは HTTP のセマンティクスを転送しません。特に、この一連のフレームの最初と任意な最後のフレーム以外の HEADERS フレーム (とその後の CONTINUATION フレーム) は HTTP のセマンティクスを転送しません。

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

HTTP リクエスト/レスポンスの交換は1つのストリームを完全に消費します。リクエストは、ストリームを "open" 状態にする HEADERS フレームで開始され、クライアントのストリームを "half closed" 状態にする END_STREAM が設定されたフレームで終了します。レスポンスは HEADERS フレームで開始され、ストリームを "closed" 状態にする END_STREAM が設定されたフレームで終了します。また、その後に CONTINUATION フレームが後に続く場合があります。

8.1.1. 情報提供レスポンス

HTTP レスポンスステータスコードの 1xx 系 ([RFC7231]、6.2節) は HTTP/2 ではサポートされません。

1xx の最も一般的なユースケースは、クライアントが最終的なレスポンスステータスコードではない 100 (Continue) を期待することを示す "100-continue" トークン (一般的に "Expect/continue" と呼ばれています) を伴う Except ヘッダーフィールドの使用です。このトークンの受信は、もしリクエストボディの送信が完了していないのであれば、クライアントはその送信を継続しなければならないことを示します。

一般的に Expect/continue は、コネクションを潜在的に使用不可能にするような、巨大なデータを含むリクエストボディの送信を防ぐことを望むクライアントにより使用されます。

HTTP/2 は Expect/continue のメカニズムを有効にしません。すなわち、サーバーが最終的にリクエストを拒否するステータスコードを送信する場合でも、コネクションを使用不可にさせることなくリクエストを続けることができます。

これはリクエストボディを送信する HTTP/2 クライアントが、リクエストが拒否される場合でも、データの送信に少なくとも1ラウンドトリップを浪費してしまうことを意味します。帯域が制限されたクライアントは、最終的なステータスコードを見越して、最初のラウンドトリップのデータ送信量を抑制することでこれを軽減できます。

この他に定義された 1xx ステータスコードも、HTTP/2 には適用されません。例えば、101 (Switching Protocols) のセマンティクスは多重化されたプロトコルに適していません。同様に、HTTP/2 ではコネクションを維持していることの意味がこれまでと異なっているため、コネクションの維持を保証するための 102 (Processing) [RFC2518] はもう必要ありません。進捗の報告のために 102 (Processing) ステータスコードを使用することは、今後推奨されず、維持もされません。

このプロトコルバージョン間の違いによって、それらを変換する中継者は次のような特別な処理を必要とします。

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

HTTP ヘッダーフィールドは一連のキーと値のペアとして情報を転送します。登録済み HTTP ヘッダーのリストについては、[4] で整備されている メッセージヘッダーフィールドレジストリを参照してください。

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

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

HTTP/2 は "ホップ・バイ・ホップ" のヘッダーフィールドを示す Connection ヘッダーフィールドを使用しません。このプロトコルでは、接続に固有なメタデータを他の方法で転送します。そのため、Connection を含む HTTP/2 メッセージは不正な形式 (8.1.2.5節)として扱われなければなりません (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章で説明したハンドシェイク方式は、他のプロトコルの使用をネゴシエートするのに十分と考えられています。

8.1.2.1. リクエストヘッダーフィールド

HTTP/2 はリクエスト対象の情報を転送するコロン ':' 文字で始まるいくつかの擬似ヘッダーフィールドを定義します:

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

コロンで始まるヘッダーフィールド名は、HTTP/2 コンテキストにおいてのみ有効です。これらは HTTP ヘッダーフィールドではありません。実装は、コロンで始まるヘッダーフィールドを生成してはいけません (MUST NOT)。また、コロンで始まる任意のヘッダーフィールドを無視して破棄しなければなりません (MUST)。具体的には、コロンで始まる名前のヘッダーフィールドは HTTP ヘッダーフィールドとして外部に露出してはいけません (MUST NOT)。

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

8.1.2.2. レスポンスヘッダーフィールド

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

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

8.1.2.3. ヘッダーフィールドの順序

HTTP ヘッダー圧縮 [COMPRESSION] はヘッダーフィールドの順序を保持しないため、異なる名前を持つヘッダーフィールドの相対的な順序は重要ではありません。しかしながら、リストを構成するために同一のヘッダーフィールドを繰り返すことができます([RFC7230]、3.2.2節) 。そのような場合では、ヘッダーフィールドの値の相対的な順序は重要です。 この繰り返しは、カンマ区切りリストの値を持つ単一のヘッダーフィールド、値を一つ持つ複数のヘッダーフィールド、またはこの組み合わせのいずれかによって発生します。したがって、後者の場合は、順序付けは圧縮がおこなわれる前に保持される必要があります。

同じ名前のヘッダーフィールドの複数の出現順序を保持するために、順序付けされた値は、ゼロ値オクテット (0x0) を区切り文字に使用して1つの値に結合されます。

ヘッダー圧縮を解凍した後、値に0のオクテット値 (0x0) を含むヘッダーフィールドは、処理される前に複数のヘッダーフィールドに分割されなければなりません (MUST)。

例えば、以下の HTTP/1.x ヘッダーブロックは:

Content-Type: text/html
Cache-Control: max-age=60, private
Cache-Control: must-revalidate

3つの Cache-Control ディレクティブを含んでいます。2つのディレクティブは最初の Cache-Control ヘッダーフィールドに、3つ目のディレクティブは2つ目の Cache-Control フィールドにあります。これらは圧縮の前に以下のように変換される必要があります (0x0 は '\0' として表現しています)。

cache-control = max-age=60, private\0must-revalidate
content-type = text/html

ここでは、Content-Type と Cache-Control の順序は保持されませんが、Cache-Control ディレクティブの相対的な順序は (最初の2つはカンマで区切られ、最後は異なる行にあったように) 保持されることに注意してください。

ヘッダーフィールドの順序に意味が無いことが知られていない限り、複数の値を含むヘッダーフィールドは1つの値として結合されなければなりません (MUST)。

カンマ区切りリストで構成されなくとも複数の値を持つことができる "set-cookie" のような特殊な場合では、順序に依存しません。"set-cookie" ヘッダーフィールドは、複数のヘッダーフィールドの値として、もしくは1つの結合された値としてエンコードされてもよいものとします (MAY)。

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

Cookie ヘッダーフィールド [COOKIE] は冗長なデータを大量に運ぶことがあります。

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

圧縮効率を向上させるために、Cookie ヘッダーフィールドは1つ以上のクッキーペアを持つ複数のヘッダーフィールドに分割してもよいものとします (MAY)。ヘッダー圧縮を解凍した後に、複数の Cookie ヘッダーフィールドが存在した場合、それらは 0x3B、0x20 (ASCII 文字の "; ") を2つのオクテットの区切り文字として使用して1つの文字列に結合されなければなりません (MUST)。

Cookie ヘッダーフィールドは、8.1.2.3節で定義されたように0のオクテット値 (0x0) を使用して分割されてもよものとします (MAY)。デコード時には、0のオクテット値はクッキーの区切り文字 ("; ") に置き換えられなければなりません (MUST)。

したがって、以下の Cookie ヘッダーフィールドのセットは、最終的な形としては圧縮および解凍後に異なる順序になる可能性がありますが、意味的に等しくなります。

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

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

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

8.1.2.5. 不正な形式のメッセージ

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

エンティティボディを持つリクエストやレスポンスは "content-length" ヘッダーフィールドを含むことができます。ボディを構成する DATA フレームペイロードの長さの合計が "content-length" ヘッダーフィールドの値と等しくない場合、リクエストやレスポンスは不正な形式となります。

HTTP のリクエストやレスポンスを処理する中継者 (つまり、トンネルとして機能しない全ての中継者) は、不正な形式のリクエストやレスポンスを転送してはいけません (MUST NOT)。

不正な形式のリクエストやレスポンスを検出する実装は、ストリームが終了したことを保証する必要があります。サーバーは不正な形式のリクエストについて、ストリームを終了したり、リセットをする前に 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}                        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

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 では、単一のリクエストに対するレスポンスにおいて、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)。

8.2.1. プッシュリクエスト

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

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

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

PUSH_PROMISE のヘッダーフィールドと、その後に続く CONTINUATION フレームは、正しく完全なリクエストヘッダーフィールドのセット(8.1.2.1節) でなければなりません (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 フレームの間に入れ込むことはできません。

8.2.2. プッシュレスポンス

PUSH_PROMISE フレームを送信後、サーバーは予約されたIDのストリーム上でレスポンス (8.1.2.2節) と同じ様にプッシュレスポンスを送信し始めることができます。サーバーは、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" のレスポンスをプッシュすることは認められていません。

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.1節)に定義されたように動作します。一部のヘッダーについては、具体的には以下のようになります。

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. コネクションの再利用

クライアントは、サーバーが信頼できる場合に限り、複数の異なる 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 ステータスコード) をレスポンスとして返すことで、リクエストの権限がないことを示すことができます。

9.1.2. 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レスポンスはデフォルトでキャッシュ可能です。

9.2. TLS の機能の利用

HTTP/2 の実装は、TLS 上の HTTP/2 のために TLS 1.2 [TLS12] に対応しなければなりません (MUST)。HTTP/2 固有のいくつかの追加制限と共に、[TLSBCP] の一般的な TLS の利用ガイダンスには従うべきです (SHOULD)。

9.2.1. TLS の機能

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)。

これは実質的に、特定の保護されたリソースに対するリクエストのレスポンスにおける再ネゴシエーションの使用を防止します。将来の仕様では、このユースケースに対応する異なる方法を提供するかもしれません。

9.2.2. TLS 暗号スイート

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) モードは受け入れ可能です。

クライアントは、別コネクションの使用で発生する追加のレイテンシーなしにフォールバックを完了するため、HTTP/2 に対応しないサーバーへの接続を可能にする他の暗号スイートを通知してもよいものとします (MAY)。

実装は、これらの要件を満たす暗号スイートによるネゴシエートをすることなしに、HTTP/2 のための TLS コネクションをネゴシエートすべきではありません (SHOULD NOT)。実装上の制限により TLS ネゴシエーションを失敗できない可能性もあります。エンドポイントは、最小要件を満たしていない HTTP/2 コネクションを INADEQUATE_SECURITY のコネクションエラー (5.4.1節) と共に、速やかに終了しなければなりません (MUST)。

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

10.1. サーバーの権限

クライアントは、リソースに対する権限のあるサーバーからの HTTP/2 レスポンスのみを受け取ることができます。これは、レスポンスを受け取る前にクライアントが PUSH_PROMISE を検証するサーバープッシュ (8.2節) においては特に重要です。

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

信頼できないサーバーが提供するリソースは、クライアントは破棄しなければなりません (MUST)。

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/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)。

10.4. プッシュリソースのキャッシュ

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

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

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

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

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] の8章を参照してください。

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

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

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

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

巨大なヘッダーブロック (4.3節) は、実装に大量の状態をコミットしてしまう可能性があります。サーバーや中継者では、":authority" や ":path"、":scheme" といったルーティングに重要なヘッダーフィールドが、ヘッダーブロックの早い段階で出現することが保証されていません。特に、リファレンスセットにある値は、そのヘッダーブロックの最後まで出現しません。

これは、中継者などからの最終的な宛先に対するヘッダーフィールドのストリーミングを妨げ、エンドポイントにヘッダーブロックの全てをバッファすることを強制します。ヘッダーブロックのサイズに強い制限はないため、エンドポイントは利用可能なメモリを使い果たすことを強いられる可能性があります。

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

10.6. 圧縮の使用

HTTP/2 はヘッダーフィールド (4.3節) とエンティティボディの両方の圧縮のより多く利用します。圧縮は、攻撃者の制御下でかつ同じコンテキストで圧縮された場合に、攻撃者による機密データの復元を可能にします。

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

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

ヘッダーフィールドの圧縮に関するさらなる考察は、[COMPRESSION] で述べられています。

10.7. パディングの使用

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

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

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

パディングの使用は、一見してわかる防御よりも結果的に弱い防御に終わることがあります。パディングは攻撃者が観察しなければならないフレームの数を増加させることで、長さ情報の推測をより困難にすることしかできません。不適切に実装されたパディングの構造は、簡単に破られる可能性があります。

特に予測可能な分布によるランダムなパッディングは、非常にわずかな保護しか提供できません。同様に、パディングペイロードを固定サイズにすることは、ペイロードサイズをその固定サイズの境界を超えるように変更することで、情報を漏洩させます。これは攻撃者がプレーンテキストの制御が可能な場合に起こりえます。

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

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

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

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

11. IANA への配慮

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

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

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

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

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

この文書は [TLSALPN] に記載される "Application Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリにおける 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
設定の使用を記載する仕様への安定した参照。

登録設定の初期セットは、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 |
+------------------------+------+---------------+---------------+

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

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

この文書は HTTP/2.0 エラーコードのレジストリを制定します。"HTTP/2.0 Error Code" レジストリは32ビットの空間を管理します。 "HTTP/2.0 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           |               |
+---------------------+------+----------------------+---------------+

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

この節は、"HTTP2-Settings" ヘッダーフィールドを Permanent Message Header Field Registry [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
No
Idempotent
No
Author/Change controller
IETF
Specification document(s)
この文書の3.5節
Related information
このメソッドは実際のクライアントでは使用されません。HTTP/1.1 サーバーや中継者が HTTP/2 コネクションプリフェイスの解析をする際に、このメソッドが使用されているように見えます。

11.7. 421 Not Authoritative HTTP ステータスコード

この文書は 421 (Not Authoritative) HTTP ステータスコードを Hypertext Transfer Protocol (HTTP) Status Code Registry ([RFC7231]、8.2節) に登録します。

Status Code
421
Short Description
Not Authoritative
Specification
この文書の9.1.2節

12. 謝辞

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

13. 参考文献

13.1. 引用文書

[COMPRESSION]
Ruellan, H. and R. Peon, "HPACK - Header Compression for HTTP/2", draft-ietf-httpbis-header-compression-08 (work in progress), June 2014.
Barth, A., "HTTP State Management Mechanism", RFC 6265, April 2011.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2818]
Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006.
[RFC5226]
Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.
[RFC5234]
Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008.
[RFC7230]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 2014.
[RFC7231]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, June 2014.
[RFC7232]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", RFC 7232, June 2014.
[RFC7233]
Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", RFC 7233, June 2014.
[RFC7234]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", RFC 7234, June 2014.
[RFC7235]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", RFC 7235, June 2014.
[TCP]
Postel, J., "Transmission Control Protocol", STD 7, RFC 793, September 1981.
[TLS-EXT]
Eastlake, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, January 2011.
[TLS12]
Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.
[TLSALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application Layer Protocol Negotiation Extension", draft-ietf-tls-applayerprotoneg-05 (work in progress), March 2014.

13.2. 参考文書

[ALT-SVC]
Nottingham, M., McManus, P., and J. Reschke, "HTTP Alternative Services", draft-ietf-httpbis-alt-svc-01 (work in progress), April 2014.
[BCP90]
Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.
[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]
Berjon, R., Faulkner, S., Leithead, T., Doyle Navara, E., O'Connor, E., and S. Pfeiffer, "HTML5", W3C Candidate Recommendation CR-html5-20140204, Febuary 2014, <http://www.w3.org/TR/2014/CR-html5-20140204/>.
Latest version available at [5].
[RFC1323]
Jacobson, V., Braden, B., and D. Borman, "TCP Extensions for High Performance", RFC 1323, May 1992.
[RFC2518]
Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D. Jensen, "HTTP Extensions for Distributed Authoring -- WEBDAV", RFC 2518, February 1999.
[RFC3749]
Hollenbeck, S., "Transport Layer Security Protocol Compression Methods", RFC 3749, May 2004.
[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, May 2006.
[RFC5288]
Salowey, J., Choudhury, A., and D. McGrew, "AES Galois Counter Mode (GCM) Cipher Suites for TLS", RFC 5288, August 2008.
[RFC6585]
Nottingham, N. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, April 2012.
[TALKING]
Huang, L-S., 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 TLS and DTLS", draft-sheffer-tls-bcp-02 (work in progress), February 2014.

13.3. URI

[1]
https://www.iana.org/assignments/message-headers
[2]
https://groups.google.com/forum/?fromgroups#!topic/spdy-dev/cfUef2gL3iU
[3]
https://tools.ietf.org/html/draft-montenegro-httpbis-http2-fc-principles-01

付録A. 変更点 (公開前に RFC 編集者により削除されます)

A.1. draft-ietf-httpbis-http2-12 からの変更

A.2. draft-ietf-httpbis-http2-11 からの変更

A.3. draft-ietf-httpbis-http2-10 からの変更

A.4. draft-ietf-httpbis-http2-09 からの変更

A.5. draft-ietf-httpbis-http2-08 からの変更

A.6. draft-ietf-httpbis-http2-07 からの変更

A.7. draft-ietf-httpbis-http2-06 からの変更

A.8. draft-ietf-httpbis-http2-05 からの変更

A.9. draft-ietf-httpbis-http2-04 からの変更

A.10. draft-ietf-httpbis-http2-03 からの変更

A.11. draft-ietf-httpbis-http2-02 からの変更

A.12. draft-ietf-httpbis-http2-01 からの変更

A.13. draft-ietf-httpbis-http2-00 からの変更

A.14. draft-mbelshe-httpbis-spdy-00 からの変更

著者の連絡先

Mike Belshe
Twist
EMail: [email protected]
Roberto Peon
Google, Inc
EMail: [email protected]
Martin Thomson (editor)
Mozilla
331 E Evelyn Street
Mountain View, CA 94041
US
EMail: [email protected]