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

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

公開日:
2013-08-20
更新日:
2013-09-01
翻訳者:
Moto Ishizawa <>

概要

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

この文書は HTTP/1.1 のメッセージフォーマットやプロトコルに変わるものですが、これを廃止するものではありません。HTTP の既存のセマンティクスを変更することもありません。

このドラフトは、実装に向けたバージョンとして位置づけられます。相互運用性テストは、2013年8月5日からドイツのハンブルグでおこなわれる HTTP/2.0 interim でおこないます。

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

このドラフトの議論は http://lists.w3.org/Archives/Public/ietf-http-wg/ にアーカイブされる HTTPBIS ワーキンググループのメーリングリスト ([email protected]) でおこなわれます。

ワーキンググループの情報や関連文書は http://tools.ietf.org/wg/httpbis/ (Wiki) と https://github.com/http2/http2-spec (ソースコードや課題トラッキング) で見つけることができます。

このドラフトにおける変更点は Appendix A.1 に要約されています。

このメモの状態

このインターネットドラフトは BCP 78 と BCP 79 の規定に完全に準拠して提出されます。

インターネットドラフトは Internet Engineering Task Force (IETF) の作業文書です。他のグループも作業文書をインターネットドラフトとして配布することができることに注意してください。最新のインターネットドラフトのリストは http://datatracker.ietf.org/drafts/current/ にあります。

インターネットドラフトは、最長6ヶ月間有効なドラフト文書であり、いかなる時でも更新や置き換え、他の文書により廃止されることがあります。また、参考資料としてインターネットドラフトを使用したり、"進行中の作業" としてではない引用をすることは不適切です。このインターネットドラフトは2014年1月10日に期限切れとなります。

Copyright (c) 2013 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. はじめに

The Hypertext Transfer Protocol (HTTP) は広く成功したプロトコルです。しかしながら、HTTP/1.1 メッセージのフォーマット ([HTTP-p1]、3章) は、アプリケーションのパフォーマンスではなく、実装の容易さとアクセシビリティに最適化されています。そのため、アプリケーションのパフォーマンスにおいて全体的に悪い影響を与えるいくつかの特性を持っています。

特に、HTTP/1.0 は与えられた接続に対して、同時に1つのリクエストを転送することしかできません。HTTP/1.1 パイプラインはリクエストの並列化に部分的に取り組みましたが、広くは使われていません。そのため、(Web においては一般的な) 多くのリクエストを発生する必要があるクライアントは、ユーザーが感じる待ち時間を減らすために一般的にサーバーに対して複数の接続を使用します。

さらに、HTTP/1.1 のヘッダーフィールドはしばしば重複し冗長であり、より多くの、より巨大なネットワークパケットを生成することで、初期の小さな TCP 輻輳ウインドウをすぐにいっぱいにしてしまいます。これは単一の新しい TCP 接続上で複数のリクエストを発行した時に、過度の待ち時間を発生させることになります。

この文書では、基本となる接続に対して、最適化された HTTP セマンティクスのマッピングを定義することで、このような問題に取り組みます。具体的には、同一接続上においてリクエストとレスポンスメッセージをインターリーブしたり、HTTP ヘッダーフィールドに対して効率のよい符号化方式を使用します。また、リクエストの優先付けを可能にし、重要なリクエストをより迅速に完了することで、よりいっそう体感速度を向上させます。

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

最後に、このカプセル化は、バイナリメッセージ構造を使用することで、メッセージ処理をよりスケーラブルにすることも可能にします。

1.1. この文書の構成

HTTP/2.0 の仕様は3つのパートに分割されます: HTTP/2.0 接続がどのように開始されるのかをまとめた HTTP/2.0 のはじまり (3章)、様々な種類の独立したフレームにより単一の TCP 接続を多重化する構造化レイヤー (4章)、そして、構造化レイヤーを使用し HTTP のやりとりを表現するための仕組みをまとめた HTTP レイヤー (8章) です。構造化レイヤーの概念の一部は、HTTP から分離されていますが、汎用的な構造化レイヤーを作ることは目標としていません。構造化レイヤーは HTTP プロトコルとサーバープッシュの要件にあわせて作られたものです。

1.2. 表記と用語

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

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

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

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

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

HTTP/2.0 は HTTP セマンティクスに最適化された転送手段を提供します。

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

この文書では、構造化、ストリーム、アプリケーションマッピングの3つのパーツで構成される論理構造を使用して、 HTTP/2.0 プロトコルについて説明します。この構造は、主に仕様を補うために提供され、実装は必要に応じてこの構造から自由に外れることができます。

2.1. HTTP フレーム

HTTP/2.0 は、HTTP セマンティクスの効率的なシリアライゼーションを提供します。HTTP リクエストとレスポンスは固定長フレームにエンコードされます (4.1節をご覧ください)。

HTTP ヘッダーは、ヘッダーブロックフラグメントを含む一連のフレームに圧縮されます (4.3節をご覧ください)。

2.2. HTTP 多重化

HTTP/2.0 は複数の HTTP リクエストとレスポンスを単一の接続上で多重化する機能を提供します。複数のリクエストやレスポンスは、ストリーム (5章) を使用することで送信することができます。独立したストリームを維持するために、フロー制御と優先付けが必要になります。

2.3. HTTP セマンティクス

HTTP/2.0 は HTTP リクエストとレスポンスがどのようにストリームに割り当てられるか (8章をご覧ください) や、新しいインタラクションモデルのサーバープッシュ (8.2節) について定義します。

3. HTTP/2.0 のはじまり

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

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

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

この文書で定義されたプロトコルは、"HTTP/2.0" という文字列を使用して識別します。この識別子は HTTP/1.1 Upgrade ヘッダーフィールドや、TLS application layer protocol negotiation extension [TLSALPN] フィールド、その他プロトコルの識別が必要とされる場所で使用されます。

"HTTP/2.0" で通信するということは、この文書で説明される伝送方式、セキュリティ、構造化、メッセージセマンティクスを使用することを意味します。

[[anchor6: 編集者注: この文書の最終版を公開する前に、次の文章は削除してください。]]

最終的な実装に限り、公開された RFC は自身を "HTTP/2.0" として識別することができます。RFC が公開されるまでは、実装は "HTTP/2.0" を使用して自身を識別してはいけません (MUST NOT)。

この文書の文末までの用例や文章では、編集の利便性のために "HTTP/2.0" を使用します。ドラフト版の実装では、この文字列を使用して識別してはいけません (MUST NOT)。

このプロトコルのドラフト版の実装は、区切り文字 ('/') の前に、"-draft-" という文字列と識別子として対応するドラフト番号を追加しなければなりません (MUST)。例えば、draft-ietf-httpbis-http2-03 は "HTTP-draft-03/2.0" という文字列を使用して識別されます。

これらのドラフト版に基づく非互換の実験では、"draft" 文字列の代わりに異なる識別子で置き換えなければなりません (MUST)。例えば、draft-ietf-httpbis-http2-07 に基づく Packet mood-based encoding の実装実験では、"HTTP-emo-07/2.0" として自身を識別することになります。ラベルは [HTTP-p1] の3.2.6節で定義される "token" シンタックスに従わなければなりません (MUST)。実験をするにあたっては、[email protected] メーリングリストで各実験についての調整をおこなうことをお勧めします。

3.2. "http" URI での HTTP/2.0 のはじまり

HTTP/2.0 への対応に関する予備知識なしに "http:" URI にリクエストをおこなうクライアントは、HTTP Upgrade メカニズムを使用します ([HTTP-p1] の6.7節)。クライアントは HTTP/2.0 を指定した Upgrade ヘッダーフィールドを含む HTTP/1.1 リクエストを送信します。また、HTTP/1.1 リクエストには HTTP2-Settings (3.2.1節) ヘッダーフィールドも含まなければなりません (MUST)。

例:

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

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

最初のリクエストとその後に続くリクエストの並行性が重要な場合は、追加のラウンドトリップを負担し、HTTP/2.0 へのアップグレードをおこなうための小さなリクエストを使用します。

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

HTTP/1.1 200 OK
Content-length: 243
Content-type: text/html
      ...

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

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

[ HTTP/2.0 connection ...

サーバーにより送信される最初の HTTP/2.0 フレームは SETTINGS フレーム (6.5節) です。101 レスポンスを受信すると、クライアントは SETTINGS フレームを含む接続ヘッダー (3.5節) を送信します。

アップグレードの前に送信された HTTP/1.1 リクエストはストリーム1に紐付けられ、可能な限り最も高い優先度が割り当てられます。ストリーム1は、リクエストが HTTP/1.1 リクエストとして完了するまで、クライアントからサーバーに対して暗黙的に半切断状態になります。HTTP/2.0 接続が開始された後、ストリーム1はレスポンスのために使用されます。

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

HTTP/1.1 から HTTP/2.0 にアップグレードするクライアントは、"HTTP2-Settings" ヘッダーフィールドを送信しなければなりません (MUST)。"HTTP2-Settings" ヘッダーフィールドは、サーバーがアップグレードリクエストを受け付けることを予想して提供される、HTTP/2.0 接続を制御する設定を含むホップ間のヘッダーフィールドです。このヘッダーが設定されていない場合、サーバーはアップグレードを拒否しなければなりません (MUST)。

HTTP2-Settings = token68

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

クライアントは次の設定の値 (6.5.1節) を含めなければなりません (MUST):

ホップ間ヘッダーフィールドとしての "Connection" ヘッダーフィールドが、HTTP/2.0 にアップグレードする時には、"Upgrade" に加えて "HTTP2-Settings" の値を含まなければなりません (MUST)。

サーバーは他の SETTINGS フレームと同じように、これらの値をデコードし、解釈します。このような値をアップグレードリクエストで提供することで、プロトコルが上記設定のデフォルト値を必要としないことを保証し、サーバーからフレームを受信するよりも前に、クライアントが他の設定を提供する機会を与えます。

3.3. "https" URI での HTTP/2.0 のはじまり

HTTP/2.0 への対応に関する予備知識のない、"https" URI へのリクエストをおこなうクライアントは Application layer protocol negotiation extension [TLSALPN] と TLS [RFC5246] を使用します。

TLS ネゴシエーションが完了すると、クライアントとサーバーは接続ヘッダー (3.5節) を送信します。

3.4. 予備知識による HTTP/2.0 のはじまり

クライアントは、他の方法で特定のサーバーが HTTP/2.0 に対応することを知ることができます。 クライアントは、HTTP/2.0 に対応していることが分かっているサーバーに対しては、接続ヘッダー (3.5節) に続いて直ちに HTTP/2.0 フレームを送信してもよいものとします (MAY)。これは "http" URI の解決にのみ影響し、"https" URI については HTTP/2.0 に対応するサーバーが TLS のプロトコルネゴシエーション [TLSALPN] に対応する必要があります。

HTTP/2.0 のための事前対応は、指定されたサーバーが今後の接続に対しても HTTP/2.0 に対応するという強いシグナルではありません。これはサーバーの設定を変更したり、クラスター化されたサーバーのインスタンス間で異なる設定をすることを可能にするためです。中継プロキシ (透過性プロキシとしてよく知られます) もまた状況が変わる要因になります。

3.5. 接続ヘッダー

TCP 接続が確立し、両方のピアが HTTP/2.0 の使用を決定するにあたり、各エンドポイントは最終的な確認と HTTP/2.0 接続の初期設定の確立のために、接続ヘッダーを送信しなければなりません (MUST)。

SETTINGS フレーム (6.5節) に続くクライアント接続ヘッダーは、24オクテットの配列であり、hex 表現は以下のようになります (文字列表現: "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"):

505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

この接続ヘッダーの後には SETTINGS フレーム (6.5節) が続きます。101 Switching Protocols レスポンス (Upgrade の完了を示します) を受信するか、サーバーから TLS 完了メッセージを受信した後には、クライアントはただちにクライアント接続ヘッダーを送信します。サーバーが対応するプロトコルについての予備知識による HTTP/2.0 接続を開始する場合は、クライアントは接続の確立にあたり接続ヘッダーを送信します。

クライアント接続ヘッダーは、HTTP/1.1 または HTTP/1.0 のサーバーと中継システムの大半は、さらにフレームを処理しないようにすることが選択されます。これは、[TALKING] で提起された懸念には対応しないことに注意してください。

SETTINGS フレーム (6.5節) で構成されるサーバー接続ヘッダーは、HTTP/2.0 接続においてサーバーが送信する最初のフレームでなければなりません (MUST)。

不要なレイテンシを防ぐために、クライアントはクライアント接続ヘッダーの送信後、サーバー接続ヘッダーの受信を待たずに、すぐに追加のフレームをサーバーに送信することが認められています。しかしながら、サーバー接続ヘッダーの SETTINGS フレームは、クライアントがどのようにサーバーと通信するかの設定を変更するパラメーターを含んでいるかもしれないことに、注意することが重要です。SETTINGS フレームを受信すると、クライアントは受信したすべてのパラメーターに従うことが求められます。

いずれかのピアが有効な接続ヘッダーにより通信を開始しない場合は、クライアントとサーバーは TCP 接続を切断しなければなりません (MUST)。ピアが HTTP/2.0 を使用していないことが明らかな場合には、GOAWAY フレーム (6.8節) は省略してもよいものとします (MAY)。

4. HTTP フレーム

HTTP/2.0 接続が確立されると、クライアントとサーバーはフレームを送信し始めることが可能になります。

4.1. フレームヘッダー

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

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Length (16)           |   Type (8)    |   Flags (8)   |
+-+-------------+---------------+-------------------------------+
|R|                 Stream Identifier (31)                      |
+-+-------------------------------------------------------------+
|                   Frame Payload (0...)                      ...
+---------------------------------------------------------------+

                         フレームヘッダー

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

Length
符号なし16ビット整数で表現されるフレームペイロードの長さです。フレームヘッダーの8オクテットはこの値には含まれません。
Type
8ビットのフレームタイプです。フレームタイプは以降のフレームヘッダーとペイロードをどのように解釈するかを決定します。実装は未対応のフレームタイプや有効でないフレームタイプについては無視されなければなりません (MUST)。
Flags
フレームタイプ固有の真偽値フラグのために予約された8ビットのフィールドです。
フラグは、指定されたフレームタイプに固有のセマンティクスが割り当てられます。特定のフレームタイプにセマンティクスが定義されていないフラグは無視されなければならず (MUST)、また、送信時には解除 (0) しなければなりません (MUST)。
R
予約済みの1ビットのフィールドです。このビットのセマンティクスは定義されていません。送信する時は解除 (0) しなければならず (MUST)、受信時には無視されなければなりません (MUST)。
Stream Identifier
31ビットのストリーム識別子 (5.1.1節) です。値0は、個々のストリームではなく、接続そのものに関連するフレームのために予約されます。

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

4.2. フレームサイズ

フレームペイロードの最大サイズはフレームタイプと用途により異なります。絶対的な最大サイズは65,535オクテットです。全ての実装は、このサイズのフレームを受信し、最低限の処理が可能であるべきです (SHOULD)。

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

フレームサイズが定義された制限を越えていたり、必要なフレームデータを含むには小さすぎるような場合は、エンドポイントは FRAME_TOO_LARGE エラーを送信しなければなりません (MUST)。接続レベルの状態に影響するフレームのフレームサイズエラーは、接続エラー (5.4.1節) として扱われなければなりません (MUST)。

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

HTTP/2.0 におけるヘッダーは、1つ以上の値が設定された名前-値のペアです。これらは、HTTP リクエストとレスポンスのメッセージおよび、サーバープッシュ処理に使用されます (8.2節をご覧ください)。

ヘッダーセットは、アプリケーションレイヤーで用意される0個以上のヘッダーフィールドからなる論理的な集合です。接続を通じて転送されるとき、ヘッダーセットは HTTP ヘッダー圧縮 [COMPRESSION] を使用してヘッダーブロックにシリアライズされます。シリアライズされたヘッダーブロックは、ヘッダーブロックフラグメントと呼ばれる1つ以上のオクテット列に分割され、HEADERS (6.2節) または PUSH_PROMISE (6.6節) フレームのペイロードとして転送されます。受信側エンドポイントは個々のフラグメントを結合することでヘッダーブロックを再構築し、ヘッダーセットを復元するために伸張します。

ヘッダーブロックフラグメントは、HEADERS または PUSH_PROMISE フレームのペイロードでのみ送信することができます。

圧縮とエンコードされたヘッダーブロックは、1つ以上の HEADERS または PUSH_PROMISE フレームで転送されます。ブロックのオクテット数がフレームの残りの容量よりも大きい場合、ブロックは複数のフラグメントに分割され、複数のフレームで転送されます。

ヘッダーブロックは、他の種類のフレームや他のストリームのフレームとインターリーブされずに、連続した一連のフレームとして送信されなければなりません (MUST)。一連の HEADERS フレームの最後のフレームには、END_HEADERS フラグが設定されていなければなりません (MUST)。また、一連の PUSH_PROMISE フレームの最後のフレームには、END_PUSH_PROMISE フラグが設定されていなければなりません (MUST)。

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

5. ストリームと多重化

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

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  |
`-------------------->|        |<--------------------'
                      +--------+


                 図1: ストリームの状態

両方のエンドポイントは、フレームが転送中の間は異なる可能性があるストリームの状態について、主観的な見解をもちます。エンドポイントはストリームの作成について同期しません。ストリームはどちらかのエンドポイントにより一方的に作成されます。状態における不一致のネガティブな影響は、終了後にフレームがしばらくの間受信される場合がある、RST_STREAM を送信した後の "closed" 状態に限定されます。

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

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

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

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

"reserved (local)" 状態のストリームは、PUSH_PROMISE を送信されることで予約されたものです。PUSH_PROMISE フレームは、リモートピアにより開始された open ストリームとストリームを関連付けることで idle ストリームを予約します (8.2節をご覧ください)。

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

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

この状態において、エンドポイントはその他の種類のフレームを送信してはいけません (MUST NOT)。

reserved (remote)

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

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

  • HEADERS フレームを受信すると、ストリームは "half closed (local)" に遷移します。
  • いずれかのエンドポイントは、ストリームを "closed" にするために RST_STREAM を送信することができます。これはストリームの予約を解除します。
  • 他の種類のフレームを受信した場合は、PROTOCOL_ERROR のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。
open

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

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

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

half closed (local)

"half closed (local)" のストリームは、フレームの送信に使用することはできません。

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

half closed (remote)

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

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

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

closed

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

エンドポイントは closed ストリームにフレームを送信してはいけません (MUST NOT)。

RST_STREAM や END_STREAM フラグを含むフレームを受信した後に、さらにフレームを受信したエンドポイントは、STREAM_CLOSED のストリームエラーとして扱わなければなりません (MUST)。

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

エンドポイントは、RST_STREAM を送信した後に PUSH_PROMISE を受信するかもしれません。PUSH_PROMISE はストリームを "reserved" に遷移させます。もし予約済みのストリームが適切でなければ、これらのストリームを終了させるために RST_STREAM を使用することができます。

5.1.1. ストリームの識別子

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

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

ストリーム識別子を再利用することはできません。長時間の接続では、エンドポイントがストリーム識別子の使用可能な範囲を越えてしまう可能性があります。新しいストリーム識別子を生成できないクライアントは、新しいストリームのために新たな接続を確立することができます。

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

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

"open" または2つの "half closed" 状態のストリームは、エンドポイントが設定した開始可能なストリームの最大数に数えられます。これら3つの状態にあるストリームは SETTINGS_MAX_CONCURRENT_STREAMS 設定に指定された制限に数えられます (6.5.2節をご覧ください)。

アプリケーション状態を保持できる容量が少ない場合でも、予約済みストリームを正しく使用できることを保証するために、2つの "reserved" 状態のストリームは、開始されたストリームとしては数えられません。

5.2. フロー制御

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

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

5.2.1. フロー制御の原則

TCP の輻輳制御による経験は、プロトコルの変更を必要としなくても、アルゴリズムが時間をかけてより高度に進化することができることを示しています。TCPの輻輳制御アルゴリズムの進化は、同様のアプローチが HTTP/2.0 のフロー制御に適用可能なことを示していますが、TCP の輻輳制御とその進化は、HTTP/2.0 のフロー制御とは明らかに異なます。

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

  1. フロー制御はホップ間でおこなわれ、エンドポイント間でおこなわれるものではありません。
  2. フロー制御はウインドウ更新フレームに基づきます。受信者は、どれぐらいのバイトをストリームと接続全体から受信する準備ができているかを告知します。これは信頼に基づいた仕組みです。
  3. フロー制御は、受信者から全体的な制御がおこなわれる、一方的なものです。受信者は、各ストリームと接続全体に対して求めるウインドウサイズを設定することを選択してもよいものとします (MAY)。送信者は、受信者が設定したフロー制御を尊重しなければなりません (MUST)。クライアント、サーバーそして仲介者は、すべて独立して、受信者としてフロー制御設定を告知し、送信する際はピアによって設定されたフロー制御制限に従います。
  4. 新しいストリームと接続全体のフロー制御ウインドウの初期値は、どちらも65536バイトです。
  5. フレームタイプは、フレームにフロー制御を提供するかどうかを決定します。この文書で述べられるフレームのうち、DATA フレームのみがフロー制御の対象となります。他の全てのフレームタイプは、告知されたフロー制御ウインドウの容量を消費しません。これは、重要なコントロールフレームがフロー制御によりブロックされないことを保証します。
  6. フロー制御は受信者により無効化されることがあります。受信者は、特定のフラグと共にウインドウ更新フレームを送信することで、ストリームや接続に対するフロー制御を無効化するかどうかを選択することができます。詳細はフロー制御の終了 (6.9.4節) をご覧ください。
  7. HTTP/2.0 は WINDOW_UPDATE フレーム (6.9節) のフォーマットのみを標準化します。このフレームを送信するタイミングや、送信する値を受信者がどのように決定するかについては規定しません。また、送信者がパケットの送信を選択する方法についても規定しません。実装は、自身のニーズにあった任意のアルゴリズムを選択することができます。

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

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

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

この機能を必要としない構成では、受信されたデータに対するフロー制御は無効化すべきです (SHOULD)。フロー制御は送信者からは無効化できないことに注意してください。送信されるデータは常に受信者により告知されたフロー制御ウインドウの影響を受けます。

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

最新の帯域幅遅延積についての十分な知識があるとしても、フロー制御の実装は困難です。しかしながら、接続率を低下させることなく、リソースが保護されることを保証することができます。

5.3. ストリームの優先度

新しいストリームを確立するエンドポイントは、ストリームに対して優先度を割り当てることができます。優先度は符合なし31ビット整数で表現されます。0は最も高い優先度を表し、2^31-1は最も低い優先度を表します。

この値の目的は、あるストリームのフレームが、他の並行するアクティブストリームよりも高い優先度で処理されることを、ストリームを開始したエンドポイントが要求できるようにすることです。これにより、あるエンドポイントが複数のストリームからインターリーブされたフレームを受信した場合、そのエンドポイントは、優先順位の低いストリームのフレームを処理するより前に、優先度の高いストリームのフレームの処理をベストエフォートで試みるべきです。

明示的にストリームの優先度を設定することは、他の任意のストリームに対して、相対的にストリームの特定の処理順序を保証するものではありません。また、ストリームを開始する側が、他のストリームからのフレームを処理するよりも前に、あるストリームからのフレームを処理することを、受信側エンドポイントに強制または要求することができる仕組みでもありません。

ストリームを生成する間に HEADERS フレーム (6.2節) で明示的に指定されない限り、デフォルトのストリーム優先度は2^30になります。 プッシュストリーム (8.2節) は関連付けされたストリームの優先度に1を加えた値 (関連付けされたストリームの優先度が2^31-1である場合には、2^31-1になります) が継承されると見なされます。すなわち、プッシュストリームは関連付けされたストリームよりも1つ少ない優先順位を持つことになります。

5.4. エラー処理

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

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

5.4.1. 接続エラー処理

接続エラーとは、構造化レイヤーの処理の妨げとなるエラーや、接続状態を破壊するエラーです。

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

GOAWAY は受信側エンドポイントで期待通りに受信されない可能性があります。接続エラーが発生した場合、GOAWAY はピアに対して接続が終了した理由をベストエフォートで伝える試みのみを提供します。

エンドポイントはいつでも接続を終了することができます。特に、エンドポイントは、エラーが再発する場合はストリームエラーを接続エラーとして扱うことを選択してもよいものとします (MAY)。状況が許す限り、エンドポイントは接続を終了するときに GOAWAY フレームを送信するべきです (SHOULD)。

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

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

ストリームエラーを検知したエンドポイントは、エラーが発生したストリームのストリーム識別子を含む 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. 接続の終了

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

6. フレーム定義

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

特定のフレームタイプの送信は、接続の状態を変更することができます。エンドポイントが接続状態の同期ビューの維持に失敗した場合、その接続においてこれ以上正常な通信をおこなうことはできません。したがって、エンドポイントは特定のフレームを使用することで、状態にどのような影響を与えるかの共通理解を持つことが重要です。このため、このプロトコルの拡張では新しいフレームタイプの導入が予想されますが、接続状態を変更することが認められるのは、この文書で定義されるフレームのみとなります。

6.1. DATA

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

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

END_STREAM (0x1)
ビット1が設定されると、エンドポイントが特定のストリームに送信する最後のフレームであることを示します。このフラグを設定することで、ストリームは "half closed" 状態 (5.1節) に遷移します。
RESERVED (0x2)
ビット2は将来的な使用のために予約されます。

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

6.2. HEADERS

HEADERS フレーム (type=0x1) は名前-値のペアを転送します。HEADERS はストリームの開始 (5.1節) に使用されます。HEADERS フレームは、既存のストリームに対して、任意の数を任意のタイミングで送信することができます。

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|                        Priority (31)                        |
+-+-------------------------------------------------------------+
|                   Header Block Fragment (*)                 ...
+---------------------------------------------------------------+

                     HEADERS フレームペイロード

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

END_STREAM (0x1)
ビット1が設定されると、エンドポイントが特定のストリームに送信する最後のフレームであることを示します。このフラグを設定することで、ストリームは "half closed" 状態 (5.1節) に遷移します。
RESERVED (0x2)
ビット2は将来的な使用のために予約されます。
END_HEADERS (0x4)
END_HEADERS ビットは、完全なヘッダーのセットを提供するために必要な一連のヘッダーブロックフラグメントが、このフレームで終わることを示します。
完全なヘッダーブロックのペイロードは、END_HEADERS フラグが設定された HEADERS フレームで終わる一連の HEADERS フレームとして提供されます。一連の HEADER フレームのペイロードは結合され、1つのブロックとして解釈されます。
END_HEADERS フラグが設定されていない HEADERS フレームは、同一ストリームの HEADERS フレームに連続していなければなりません (MUST)。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR の接続エラー (5.4.1節) として扱わなければなりません (MUST)。
PRIORITY (0x8)
ビット4は、このフレームが最初の4オクテットに1ビットの予約ビットと31ビットの優先度を含むことを示します (5.3節をご覧ください)。このビットが設定されない場合には、最初の4バイトは設定されず、フレームはヘッダーブロックフラグメントのみを含みます。

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

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

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

6.3. PRIORITY

PRIORITY フレーム (type=0x2) は、送信者からのストリーム優先度を指定します。このフレームは既存のストリームに対していつでも送信することができ、既存のストリームの優先付けを可能にします。

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|                        Priority (31)                        |
+-+-------------------------------------------------------------+

                    PRIORITY フレームペイロード

PRIORITY フレームのペイロードは、1つの予約ビットと31ビットの優先度を含みます。

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

PRIORITY フレームは既存のストリームに関連付けられます。ストリーム識別子が0x0の PRIORITY フレームを受信した場合、受信者は PROTOCOL_ERROR の接続エラー (5.4.1節) として応答しなければなりません (MUST)。

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

6.5. SETTINGS

SETTINGS フレーム (type=0x4) は、エンドポイントの通信方法に影響を与える設定パラメーターを転送します。このパラメーターはピアの動作や設定のいずれかを制限します。

SETTINGS フレームは接続開始時に送信されなければなりません (MUST)。また、接続中の任意の時点で、いずれかのエンドポイントにより送信してもよいものとします (MAY)。

実装はこの仕様で定義される全ての設定に対応しなければなりません (MUST)。また、拡張で定義された追加の設定にも対応してもよいものとします (MAY)。対応していない、または有効でない設定は無視されなければなりません (MUST)。また、新しい設定は、エンドポイントが正常に通信をおこなうためにそれらを理解する必要があるまで、定義や実装をしてはいけません (MUST NOT)。

SETTINGS フレームには定義された全ての設定を含む必要はありません。送信者は適切な値を持ち、それを伝える必要のあるパラメーターだけを含むことができます。複数のパラメーターを送信する場合には、数が小さい ID から大きい ID の順番に送信すべきです (SHOULD)。1つの SETTINGS フレームには、同じ ID の値を複数含んではいけません (MUST NOT)。SETTINGS フレームの受信者が、同じ ID に対して複数の値が設定されていることを検知した場合は、その ID の最初の値以外は全て無視しなければなりません (MUST)。

接続を持続している間、エンドポイントは、過去に未設定のパラメーターやすでに値を送信したパラメーターの新しい値を含む、複数の SETTINGS フレームを送信してもよいものとします (MAY)。設定値には最も新しい値のみが適用されます。

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

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

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

6.5.1. 設定フォーマット

SETTINGS フレームのペイロードは0個以上の設定からなります。各設定は、8ビットの予約フィールドと符号なし24ビットの設定識別子、そして符号なし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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Reserved (8) |            Setting Identifier (24)            |
+---------------+-----------------------------------------------+
|                        Value (32)                             |
+---------------------------------------------------------------+

                        設定フォーマット

6.5.2. 定義済みの設定

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

SETTINGS_MAX_CONCURRENT_STREAMS (4)
送信者が許可する同時ストリームの最大数を示します。この制限は一方的であり、送信者が受信者に作成を許可するストリームの数に適用されます。デフォルトは無制限です。並列性の不要な制限をしないために、この値は100以下にしないことをおすすめします。
SETTINGS_INITIAL_WINDOW_SIZE (7)
ストリームレベルのフロー制御のための、送信者の初期ウインドウサイズ (バイト) を示します。
この設定は、既存のストリームを含む、全てのストリームのウインドウサイズに影響します。6.9.2節をご覧ください。
SETTINGS_FLOW_CONTROL_OPTIONS (10)
送信者に向けたストリームがフロー制御の対象とならないことを示します。この値の最下位ビット (0x1) は新しいストリームがフロー制御されないことを示すために設定されます。他のビットは全て予約済みです。
この設定は、既存のストリームを含む全てのストリームに適用されます。
これらのビットは1度設定されると初期化することができません。詳しくは6.9.4節をご覧ください。

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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|                Promised-Stream-ID (31)                      |
+-+-------------------------------------------------------------+
|                 Header Block Fragment (*)                   ...
+---------------------------------------------------------------+

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

PUSH_PROMISE のペイロードには "Promised-Stream-ID" が含まれます。この符号なし31ビットの整数は、エンドポイントがフレームを送信する予定のストリームであることを明確にします。予約済みストリーム識別子は、送信者により送信される次のストリーム (ストリームの識別子 (5.1.1節) をご覧ください) が適切に選択されなければなりません (MUST)。

"Promised-Stream-ID" の後には、ヘッダーブロックフラグメントが続きます (4.3節)。

PUSH_PROMISE フレームは、ピアが開始した、既存のストリームに関連付けられなければなりません (MUST)。Stream Identifier フィールドに0x0の値が指定されていた場合、受信者は PROTOCOL_ERROR の接続エラー (5.4.1節) として応答しなければなりません (MUST)。

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

END_PUSH_PROMISE (0x1)
END_PUSH_PROMISE ビットは、完全なヘッダーのセットを提供するために必要な一連のヘッダーブロックフラグメントが、このフレームで終わることを示します。
完全なヘッダーブロックのペイロードは、END_PUSH_PROMISE フラグが設定された PUSH_PROMISE フレームで終わる一連の PUSH_PROMISE フレームで提供されます。一連のフレームを受信後、全ての PUSH_PROMISE フレームのペイロードは結合され、1つのブロックとして解釈されます。
END_PUSH_PROMISE フラグが設定されていない PUSH_PROMISE フレームは、同一ストリームの PUSH_PROMISE フレームに連続していなければなりません (MUST)。受信者は、他の種類のフレームや、異なるストリームでのフレームの受信を PROTOCOL_ERROR の接続エラー (5.4.1節) として扱わなければなりません (MUST)。

予約済みストリームは、予約した順番で使用する必要はありません。PUSH_PROMISE は今後使用するストリーム識別子のみを予約します。

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

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

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)。送信者はペイロードに任意の値を選択して含めることができ、任意の方法でそれらのバイトを使用することができます。

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

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

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

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

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

6.8. GOAWAY

GOAWAY フレーム (type=0x7) は、リモートピアが接続におけるストリームの作成を終了することを伝えます。これは、クライアントとサーバーのどちらからでも送信することができます。このフレームが送信されると、送信者は現在の接続に残っている新しいストリームに送信されたフレームを無視します。GOAWAY フレームの受信者は、現在の接続上で新しい追加のストリームを開始してはなりません (MUST NOT)。しかしながら、新しいストリームのために新しい接続は確立することができます。このフレームの目的は、エンドポイントが以前確立したストリームの処理を完了している間であっても、(おそらく、再起動やメンテナンスのために) 新しいストリームの受け入れを適切に停止できるようにすることです。

新しくストリームを開始したエンドポイントと、GOAWAY フレームを送信したリモートの間には、固有の競合状態があります。このような場合に対処するため、GOAWAY には、現在の接続において送信側エンドポイントが処理した最後のストリームのストリーム識別子が含まれます。GOAWAY の受信者が、指定されたストリーム識別子よりも新しいストリームを使用した場合、送信者による処理はおこなわれず、受信者はそれらはまったく作成されなかったストリームとして扱うかもしれません (したがって、受信者は新しい接続でストリームを再生成しようとするかもしれません)。

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

GOAWAY フレームの送信後、送信者は新しいストリームのフレームを破棄します。しかしながら、接続状態を変更するフレームは完全には無視されません。たとえば、HEADERS と PUSH_PROMISE フレームは、圧縮状態 (4.3節をご覧ください) の維持を保証するために、最低限処理されなければなりません (MUST)。

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|                  Last-Stream-ID (31)                        |
+-+-------------------------------------------------------------+
|                      Error Code (32)                          |
+---------------------------------------------------------------+
|                  Additional Debug Data (*)                    |
+---------------------------------------------------------------+

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

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

GOAWAY フレームは特定のストリームではなく、接続に対して適用されます。

ストリーム識別子は0でなければなりません (MUST)。

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

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

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

最終ストリーム識別子の値と等しいかまたはそれ以下の識別子をもつストリームでの処理は、正常に完了する可能性があります。GOAWAY フレームの送信者は、処理中のストリームが全て完了するまで open 状態で接続を維持し、GOAWAY フレームを送信することで適切に接続を終了するかもしれません。

有効なストリームが存在しなかった場合は、Last-Stream-ID は0でなければなりません (MUST)。

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

エンドポイントは、GOAWAY フレームのペイロードに不明瞭なデータを追加してもよいものとします (MAY)。追加のデバッグデータは診断のみを目的とし、意味のある値は含みません。デバッグデータは機密情報を含むことができるため、永続的に保存されてはなりません (MUST NOT)。

6.9. WINDOW_UPDATE

WINDOW_UPDATE フレーム (type=0x9) フロー制御を実行するために使用されます。

フロー制御は、個々のストリームと接続全体の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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|              Window Size Increment (31)                     |
+-+-------------------------------------------------------------+

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

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

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

END_FLOW_CONTROL (0x1)
ビット1は、特定のストリームまたは接続のフロー制御が終了し、その後に続くフレームにはフロー制御の必要がないことを示すために設定します。

WINDOW_UPDATE フレームは、ストリームや接続を特定することができます。ストリームの場合、フレームのストリーム識別子が対象のストリームを示し、接続の場合は、ストリーム識別子 "0" がこのフレームの対象が接続全体であることを示します。

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

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

ストリームフロー制御ウインドウと、接続フロー制御ウインドウの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.0 接続が最初に確立された時に、65536バイトの初期フロー制御ウインドウサイズと共に新しいストリームが作成されます。接続フロー制御ウインドウは65535バイトになります。どちらのエンドポイントも、接続ヘッダーの一部として、SETTINGS フレームに SETTINGS_INITIAL_WINDOW_SIZE の値を含めることで、新しいストリームのための初期ウインドウサイズを調整することができます。

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

SETTINGS フレームは、現在の全てのストリームの初期フロー制御ウインドウサイズを変更することができます。SETTINGS_INITIAL_WINDOW_SIZE の値が変更された時は、受信者は新しい値と古い値の差分を維持し、全てのストリームのフロー制御ウインドウサイズを調整しなければなりません (MUST)。SETTINGS フレームは接続フロー制御ウインドウを変更することはできません。

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

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

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

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

受信者には、フロー制御の制限を超えたストリームの処理について、2つの選択肢があります:

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

受信者がストリームの受け入れを決めた場合は、送信者と受信者ともに、SETTINGS に設定された初期ウインドウサイズに基づいて、使用可能なフロー制御ウインドウを再計算しなければなりません (MUST)。

6.9.4. フロー制御の終了

受信者がストリームの終了を示したフレームを読み込んだ後では、そのストリームの WINDOW_UPDATE フレームの送信を終了しなければなりません (MUST)。送信者には、これ以上送信されることがないストリームの使用可能なフロー制御ウインドウを維持する責任はありません。

SETTINGS_FLOW_CONTROL_OPTIONS を使用することで、接続における全てのストリームのフロー制御を無効化することができます。ストリームのフロー制御をおこないたくない実装は、最初の SETTINGS 交換において、これを使用することができます。

END_FLOW_CONTROL フラグを設定した WINDOW_UPDATE を送信することで、個別のストリームや接続全体のフロー制御を無効化することができます。END_FLOW_CONTROL フラグが設定された WINDOW_UPDATE のペイロードは無視されます。

一度無効化したフロー制御を再び有効化することはできません。WINDOW_UPDATE の送信や、SETTINGS_FLOW_CONTROL_OPTIONS 設定のビットを削除といった、フロー制御の再有効化の試みは、FLOW_CONTROL_ERROR エラーコードと共に拒否されなければなりません (MUST)。

7. エラーコード

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

エラーコードは共通のコード領域を共有します。一部のエラーコードは特定の状況にのみ適用され、いくつかのフレームタイプにおいては意味が定義されません。

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

NO_ERROR (0)
関連する状態は、エラーの結果ではありません。例えば、GOAWAY は接続が適切に終了することを示すためにこのコードを含むかもしれません。
PROTOCOL_ERROR (1)
エンドポイントが不特定のエラーを検知しました。このエラーは明確なエラーコードが提供されていない時に使用されます。
INTERNAL_ERROR (2)
エンドポイントで予期せぬ内部エラーが発生しました。
FLOW_CONTROL_ERROR (3)
エンドポイントがピアのフロー制御プロトコル違反を検知しました。
STREAM_CLOSED (5)
エンドポイントが半切断にされたストリームからフレームを受信しました。
FRAME_TOO_LARGE (6)
エンドポイントが対応する最大サイズよりも大きいフレームを受信しました。
REFUSED_STREAM (7)
エンドポイントがアプリケーション処理をおこなう前にストリームを拒否しました。詳細は8.1.5節をご覧ください。
CANCEL (8)
ストリームが必要がなくなったことを示すために、エンドポイントが使用します。
COMPRESSION_ERROR (9)
エンドポイントが接続のための圧縮コンテキストの維持に失敗しました。

8. HTTP メッセージの交換

HTTP/2.0 は既存の Web ベースのアプリケーションに可能な限り互換であることを目指しています。 これは、サーバーのビジネスロジックやアプリケーション API の観点から、HTTP の機能を変更しないことを意味します。これを実現することで、転送シンタックスのセマンティクスは変更されるものの、全てのアプリケーションのリクエストとレスポンスヘッダーのセマンティクスは保たれます。したがって、HTTP/1.1 ([HTTP-p1], [HTTP-p2], [HTTP-p4], [HTTP-p5], [HTTP-p6], [HTTP-p7]) からの規約にはこの章の変更が適用されます。

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

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

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

これら一連のフレームの最後のフレームは END_STREAM フラグを持ちます。

HEADERS を含むこの他のフレームは、上記のフレームにインターリーブされてもよいものとします (MAY)。しかし、これらのフレームは HTTP のセマンティクスを転送しません。

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

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

8.1.1. 例

例えば、リクエストヘッダーフィールドを含み、ボディがない HTTP GET リクエストは、リクエストヘッダーフィールドのシリアライズされたブロックを含む、連続した一連の HEADERS フレームとして転送されます。最後の HEADERS フレームには END_HEADERS と END_STREAM のフラグの両方が設定されます:

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

同様に、レスポンスヘッダーフィールドを含むレスポンスも、レスポンスヘッダーフィールドのシリアライズされたブロックを含む、一連の HEADERS フレームとして転送されます。最後の HEADERS フレームには、END_HEADERS と END_STREAM のフラグの両方が設定されます:

HTTP/1.1 204 No Content       HEADERS
Content-Length: 0        ===>   + END_STREAM
                                + END_HEADERS
                                  :status = 204
                                  content-length: 0

リクエストヘッダーフィールドとペイロードデータを含む HTTP POST リクエストは、リクエストヘッダーを含む 1つ以上の HEADER フレームと、それに続く1つ以上の DATA フレームとして転送されます。最後の 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
                                   :scheme = https
{binary data}                      :host = example.org
                                   :path = /resource
                                   content-type = image/jpeg
                                   content-length = 123

                               DATA
                                 + END_STREAM
                                   {binary data}

ヘッダーフィールドとペイロードデータを含むレスポンスは、1つ以上の HEADERS フレームとそれに続く、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_HEADERS と END_STREAM の両方のフラグが設定された終了フレームを含みます。

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

                              HEADERS
                                + END_STREAM
                                + END_HEADERS
                                  foo: bar

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

リクエストヘッダーフィールドの定義は、いくつかの注目すべき例外を除き、HTTP/1.1 から大きな変更はありません:

全ての HTTP リクエストは ":method"、":path"、":host"、そして ":scheme" ヘッダーフィールドを含まなければなりません (MUST)。

名前が ":" ではじまるヘッダーフィールドは (この文書またはこの文書の将来的な拡張かどうかにかかわらず)、他のヘッダーフィールドよりも前に登場しなければなりません (MUST)。[[anchor15: 編集注: この要件は現在レビュー待ちです。現時点では "on hold" と見なします。]]

リクエストボディを含む全ての HTTP リクエストは "content-length" ヘッダーフィールドを含むべきです (SHOULD)。サーバーが受信したリクエストの DATA フレームの合計と、"content-length" ヘッダーフィールドの値が等しくなかった場合、サーバーは 400 (Bad Request) エラーを返さなければなりません (MUST)。

クライアントが必須のヘッダーフィールドをリクエストし忘れた場合は、サーバーは HTTP 400 Bad Request を返信しなければなりません (MUST)。

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

レスポンスヘッダーフィールドの定義は、いくつかの注目すべき例外を除き、HTTP/1.1 から大きな変更はありません:

名前が ":" ではじまるヘッダーフィールドは (この文書またはこの文書の将来的な拡張かどうかにかかわらず)、他のヘッダーフィールドよりも前に登場しなければなりません (MUST)。[[anchor15: 編集注: この要件は現在レビュー待ちです。現時点では "on hold" と見なします。]]

8.1.4. GZip コンテンツエンコーディング

クライアントは HTTP レスポンスボディの gzip 圧縮に対応しなければなりません (MUST)。accept-encoding ヘッダーフィールドの値にかかわらず、サーバーは gzip または deflate でエンコードしたレスポンスを送信してもよいものとします (MAY)。圧縮されたレスポンスには、適切な content-encoding ヘッダーフィールドを伴わなければなりません (MUST)。

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

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

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

いずれのケースも、クライアントは自動的に冪等でないメソッドのリクエストも含む、全てのリクエストを再試行してもよいものとします (MAY)。

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

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

8.2. サーバープッシュ

HTTP/2.0 では、1つのリクエストに対するレスポンスとして、複数の関連するリソースをサーバーがクライアントに先行送信すること (または "プッシュ") を可能にします。最初にリクエストしたリソースを完全に処理するために、クライアントが持っている必要があるリソースについてをサーバーが知っていた場合は、この機能は特に有益になりえます。

追加リソースのプッシュは任意であり、個々のエンドポイントの間でのみやり取りされます。例えば、仲介者はプッシュされたリソースをサーバーから受信することができますが、それらをクライアントに転送する必要はありません。プッシュリソースの利用方法については、仲介者に委ねられています。同様に、仲介者は、サーバーからの実行なしに、クライアントに追加のリソースをプッシュすることを選択するかもしれません。

サーバープッシュは、リソースに対して GET リクエストした際のサーバーの応答と意味的に等しくなります。サーバーから送信される PUSH_PROMISE フレームは、サーバーが想定したリクエストヘッダーのヘッダーブロックを含みます。

プッシュリソースは、常にクライアントからの明確なリクエストに関連付けられます。サーバーから送信される PUSH_PROMISE フレームは、最初のリクエストで作成されたストリームに送信されます。PUSH_PROMSE フレームは、サーバーで使用可能なストリーム識別子 (5.1.1節をご覧ください) から選択された予約済みストリーム識別子を含みます。サーバーから送信される PUSH_PROMISE フレームに指定されていないヘッダーフィールドは、クライアントが送信した最初のリクエストから継承されます。

PUSH_PROMISE のヘッダーフィールドには、プッシュされたリソースを特定するために ":scheme"、":host"、":path" ヘッダーフィールドが含まれなければなりません (MUST)。PUSH_PROMISE は常に HTTP メソッド GET の結果を示します。クライアントが、これらのヘッダーフィールドや ":method" ヘッダーフィールドの値を含まない PUSH_PROMISE を受信した場合、PROTOCOL_ERROR のストリームエラー (5.4.2節) として応答しなければなりません (MUST)。

PUSH_PROMISE フレームを送信後、サーバーは予約済みストリーム識別子を使用して新たにサーバーが開始したストリーム上で、プッシュリソースの送信を開始することができます。このストリームは、クライアントに対して暗黙的に "half closed" です (5.1節)。サーバーは、8.1節で定義されたような一連のフレームを使用して、HTTP レスポンスを送信するためにこのストリームを使用します。

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

サーバーは、予約済みリソースに関連する HEADERS や DATA フレームを送信する前に、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 フレームに点在することができないことを除けば、レスポンスを構成するフレーム内に点在することができます。

クライアントは、サーバーから同時にプッシュされるリソースの数を制限するために SETTINGS_MAX_CONCURRENT_STREAMS 設定を使用することができます。値が0に設定された SETTINGS_MAX_CONCURRENT_STREAMS を告知することで、サーバーが必要とするストリームの生成を防ぎ、サーバープッシュを無効にします。

PUSH_PROMISE フレームで提供されるリクエストヘッダーフィールドは、リソースのキャッシュがすでに提供済みであるかどうかをクライアントが確認するために、十分な情報を含むべきです (SHOULD)。クライアントが何らかの理由でサーバーからプッシュされたリソースの受信を望まないと判断した場合や、サーバーが予約済みリソースの送信開始まで時間がかかりすぎる場合には、クライアントは CANCEL または REFUSED_STREAM コードのいずれかを使用し、予約済みストリーム識別子を参照する RST_STREAM フレームを送信することができます。

プッシュリソースを受信するクライアントは、サーバーが Same-Origin Policy を使用して、リソースのプッシュを許可していることを検証しなければなりません (MUST) ([RFC6454], 3節)。例えば、"example.com" への HTTP/2.0 接続では、一般的に [[anchor17: 編集注: 安易な "一般的" の使用であり、よりよい記述が必要です]] "www.example.org" のレスポンスをプッシュすることは認められません。

9. 追加の HTTP 要件/検討

TODO: SNI、gzip と deflate、Content-Encoding など..

9.1. HTTP 向けフレームサイズ制限

HTTP メッセージ向けに使用されるフレームは、8 オクテットのフレームヘッダーを除いた長さが 2^14-1 (16383) オクテットを超えてはいけません (MUST NOT)。エンドポイントは、巨大なフレームの受信に対しては FRAME_TOO_LARGE エラー (4.2節をご覧ください) として扱わなければなりません (MUST)。

9.2. 接続管理

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

クライアントは、特定のオリジン ([RFC6454]) に対して同時に2つ以上の HTTP/2.0 接続を開始すべきではありません (SHOULD NOT)。クライアントは、提供可能なストリーム識別子が少なくなった接続の交換 (5.1.1節) や、エラーが発生した接続の交換 (5.4.1節) のいずれかのために、追加の接続をおこなうことができます。

サーバーは可能な限り長く開かれた接続を維持することが推奨されますが、必要に応じてアイドル状態の接続を終了することが認められています。いずれかのエンドポイントがトランスポート層の TCP 接続を終了することを選択した時、両方のエンドポイントが、先に送信したフレームが処理され、適切に完了したのか、必要な残りのタスクが中断されたのかどうかを期待通りに確認することができるように、終了側エンドポイントは最初に GOAWAY (6.8節) フレームを送信しなければなりません (MUST)。

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

10.1. サーバーの権限と Same-Origin

この仕様では、オリジンサーバーがコンテンツの提供を許可したかどうかを確認するために Same-Origin Policy を使用します ([RFC6454], 3節)。

TLS を使用して通信するサーバーは、TLS ハンドシェイク ([RFC2818] 3節をご覧ください)で提示される証明書に基づいて認証されます。提供されるリソースのオリジンのドメイン部についての認証が成功した場合、サーバーは信頼できる "https" リソースと見なします。

サーバーは、リソースのオリジンのドメインとして解決される IP アドレスで接続が確立された場合は、信頼できる "http" リソースと見なします。

信頼できないサーバーが提供するリソースは、いかなる場合でもクライアントは使用してはいけません (MUST NOT)。

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

TLS を使用する場合、私たちは HTTP/2.0 が新しいクロスプロトコル攻撃を引き起こすことはないと考えています。TLS は (自身のハンドシェイクを除いて) 転送する全ての内容を暗号化し、攻撃者がクロスプロトコル攻撃で使用することができるデータの制御を困難にします。[[anchor23: Issue: これはもはや本当ではない]]

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

プッシュリソースは明確なリクエストがないレスポンスです。プッシュリソースに対するリクエストは、プッシュをきっかけとするリクエストと、サーバーが提供するリソース識別子情報から合成されます。 リクエストヘッダーフィールドは (Vary ヘッダーフィールドのような) HTTP キャッシュ制御の検証動作に必要です。このため、キャッシュはプッシュに関連付けられたストリームのリクエストヘッダーフィールドを継承しなければなりません (MUST)。これには Cookie ヘッダーフィールドも含まれます。

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

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

信頼できないオリジンサーバーのプッシュリソースを、使用したりキャッシュすることはありません。

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

HTTP/2.0 では、ユーザーがリクエストをおこなった時のレイテンシを削減するために、クライアントとサーバーの間で長時間接続を開いたまま維持することを目指しています。長時間の接続維持は、個人情報の漏洩につながる可能性があります。例えば、前のユーザーが使用した後のブラウザを別のユーザーが使用することで、前のユーザーがおこなっていたことを知ることができるかもしれません。これは、現在の形の HTTP にも同様に問題があります。しかし、接続時間を短くすることでリスクを減らすことができます。

12. IANA への配慮

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

この文書では HTTP で使用する "HTTP2-Settings" ヘッダーフィールドも登録します。

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

この文書は HTTP/2.0 フレームタイプのレジストリを制定します。"HTTP/2.0 Frame Type" レジストリは、"IETF Review" ポリシー [RFC5226] に従って運用します。

フレームタイプは8ビットの値です。新しいフレームタイプの登録をレビューする際には、定義済みのフレームタイプの固有フラグについて特に注意することを推奨します。フレームフラグは既存のフラグと互いに作用することができ、また全体適用可能なフラグの追加を防ぐことができます。

"HTTP/2.0 Frame Type" レジストリの初期値をテーブル1に示します。

+-----------+---------------+---------------------------------------+
| Frame     | Name          | Flags                                 |
| Type      |               |                                       |
+-----------+---------------+---------------------------------------+
| 0         | DATA          | END_STREAM(1)                         |
| 1         | HEADERS       | END_STREAM(1), END_HEADERS(4),        |
|           |               | PRIORITY(8)                           |
| 2         | PRIORITY      | -                                     |
| 3         | RST_STREAM    | -                                     |
| 4         | SETTINGS      | -                                     |
| 5         | PUSH_PROMISE  | END_PUSH_PROMISE(1)                   |
| 6         | PING          | PONG(1)                               |
| 7         | GOAWAY        | -                                     |
| 9         | WINDOW_UPDATE | END_FLOW_CONTROL(1)                   |
+-----------+---------------+---------------------------------------+

                             テーブル1

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

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

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

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

Error Code
32ビットのエラーコードの値。
Name
エラーコードの名前。 エラーコードの名前の指定は任意です。
Description
エラーコードに該当する状態の説明。
Specification
エラーコードを定義する仕様への任意の参照。

登録されたエラーコードの初期セットは7章で確認することができます。

12.3. 設定レジストリ

この文書は HTTP/2.0 設定のレジストリを制定します。"HTTP/2.0 Settings" レジストリは24ビットの空間を管理します。 "HTTP/2.0 Settings" レジストリは、"Expert Review" ポリシー [RFC5226] に従って運用します。

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

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

Setting
24ビットの設定値。
Name
設定の名前。名前の指定は任意です。
Flags
設定値とセマンティクスを含み、適用される設定固有のフラグ。
Description
設定の説明。これは、値の範囲や適用される単位、値が与えられた時にどのように振る舞うのかを含む場合があります。
Specification
設定を定義する仕様への任意の参照。

登録された設定の初期セットは6.5.2節で確認することができます。

12.4. 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)
RFC XXXX (この文書)
Related information
このヘッダーフィールドは、HTTP/2.0 クライアントの Upgrade に基づくネゴシエーションにのみ使用されます。

13. 謝辞

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

14. 参考文献

14.1. 引用文書

[COMPRESSION]
Ruellan, H. and R. Peon, "HTTP Header Compression", draft-ietf-httpbis-header-compression-00 (work in progress), June 2013.
[HTTP-p1]
Fielding, R. and J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", draft-ietf-httpbis-p1-messaging-22 (work in progress), February 2013.
[HTTP-p2]
Fielding, R. and J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", draft-ietf-httpbis-p2-semantics-22 (work in progress), February 2013.
[HTTP-p4]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", draft-ietf-httpbis-p4-conditional-22 (work in progress), February 2013.
[HTTP-p5]
Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", draft-ietf-httpbis-p5-range-22 (work in progress), February 2013.
[HTTP-p6]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", draft-ietf-httpbis-p6-cache-22 (work in progress), February 2013.
[HTTP-p7]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", draft-ietf-httpbis-p7-auth-22 (work in progress), February 2013.
[RFC0793]
Postel, J., "Transmission Control Protocol", STD 7, RFC 793, September 1981.
[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.
[RFC5246]
Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.
[RFC6454]
Barth, A., "The Web Origin Concept", RFC 6454, December 2011.
[TLSALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application Layer Protocol Negotiation Extension", draft-ietf-tls-applayerprotoneg-01 (work in progress), April 2013.

14.2. 参考文書

[BCP90]
Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.
[RFC1323]
Jacobson, V., Braden, B., and D. Borman, "TCP Extensions for High Performance", RFC 1323, May 1992.
[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>.

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

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

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

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

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

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

著者の連絡先

Mike Belshe
Twist
EMail: [email protected]
Roberto Peon
Google, Inc
EMail: [email protected]
Martin Thomson (editor)
Microsoft
3210 Porter Drive
Palo Alto 94304
US
EMail: [email protected]
Alexey Melnikov (editor)
Isode Ltd
5 Castle Business Village
36 Station Road
Hampton, Middlesex TW12 2BX
UK
EMail: [email protected]