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

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

公開日:
2013-11-14
更新日:
2013-12-03
翻訳者:
Moto Ishizawa <>
翻訳協力:
Shigeki Ohtsu

概要

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

この文書は HTTP/1.1 のメッセージシンタックスを変更するものですが、これを廃止するものではありません。HTTP の既存のセマンティクスを変更することもありません。

このドラフトは、実装に向けたバージョンとして位置づけられます。相互接続テストは、2014年1月22日から始まるスイス、チューリッヒでの 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 に要約されています。

このメモの状態

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

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

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

このインターネットドラフトは2014年5月15日に期限切れとなります。

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. はじめに

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

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

さらに、 HTTP/1.1 のヘッダーフィールドはしばしば重複であり冗長です。これよって巨大なネットワークパケットを多数生成することになり、TCP 輻輳の小さな初期ウインドウはすぐいっぱいになってしまいます。そして結果的に、1つの新しい 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 接続におけるエラー。
エンドポイント
コネクションにおけるクライアントまたはサーバー。
フレーム
ヘッダー、フレームタイプに従って構成される可変長のバイト列からなる HTTP/2.0 接続内部での最小の通信単位。
ピア
エンドポイントの1つ。特定のエンドポイントを議論するときに、"ピア" は議論の対象となる主なリモートエンドポイントを示します。
受信者
フレームを受信するエンドポイント。
送信者
フレームを送信するエンドポイント。
サーバー
HTTP 接続を受け付けるエンドポイント。
ストリーム
HTTP/2.0 接続内部の仮想チャンネルを通る双方向のフレームの流れ。
ストリームエラー
個々の HTTP/2.0 ストリームにおけるエラー。

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

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

HTTP/2.0 接続は TCP 接続の上で動作するアプリケーションレベルのプロトコルです ([TCP])。また、クライアントが 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.1節をご覧ください) を定義します。そして HTTP/2.0 は、新しいインタラクションモデルであるサーバープッシュ (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)。このルールの例外として、HTTP/2.0 接続確立直後にクライアントから送信されるコネクションヘッダー (3.5節をご覧ください) に含まれる文字列があります。この固定長のオクテット列は変更しません。

このプロトコルのドラフト版の実装は、区切り文字 ('/') の前に、"-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 リクエストには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が割り当てられ、可能な限り最も高い優先度が割り当てられます。リクエストが HTTP/1.1 リクエストとして完了しているため、ストリーム 1 はクライアントからサーバーに対して暗黙的に half closed 状態になります。HTTP/2.0 接続を開始した後、ストリーム 1はレスポンスのために使用されます。

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

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

HTTP2-Settings = token68

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

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

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

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

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

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

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. HTTP/2.0 コネクションヘッダー

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

クライアントコネクションヘッダーは、24オクテットの配列ではじまり、16進数表現は以下のようになります (文字列表現: "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から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) オクテットです。全ての実装は、最大サイズまでのフレームを受信し、最低限の処理が可能であるべきです (SHOULD)。

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

フレームサイズが定義された制限を越えていたり、必要なフレームデータを含むには小さすぎるような場合は、エンドポイントは FRAME_SIZE_ERROR エラーを送信しなければなりません (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節)、または CONTINUATION (6.10節) フレームのペイロードとして転送されます。

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

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

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

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

5. ストリームと多重化

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

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節で説明されるようにストリーム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)。HEADERS や 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)" になります。END_STREAM フラグを設定した HEADERS フレームの後には CONTINUATION フレームが続くことができます。

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

half closed (local)

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

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

この状態では、受信者は WINDOW_UPDATE や PRIORITY フレームを無視することができます。END_STREAM フラグが設定されたフレームを送信した後の短時間に、これらのフレームタイプが到着することがあります。

half closed (remote)

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

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

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

closed

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

エンドポイントは closed ストリームにフレームを送信してはいけません (MUST NOT)。RST_STREAM フレームを受信した後に、さらにフレームを受信したエンドポイントは、STREAM_CLOSED のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。同様に、END_STREAM フラグが設定された DATA フレームを受信した後にさらにフレームを受信したり、END_STREAM フラグが設定された HEADERS フレームを受信した後に、CONTINUATION フレームを以外のフレームを受信したエンドポイントも、STREAM_CLOSED のストリームエラー (5.4.2節) として扱わなければなりません (MUST)。

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

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

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

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

この文書の他の場所においてより具体的な指針が存在しない場合、実装は、状態の説明において明示的に許可されていないメッセージの受信についてを PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱うべきです (SHOULD)。

5.1.1. ストリームID

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

ストリームIDの1 (0x1) は、Upgrade (3.2節) 中に発行された HTTP/1.1 リクエストの応答で使用されます。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を生成できないクライアントは、新しいストリームのために新たなコネクションを確立することができます。

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 フレームの使用を通じて、フロー制御を提供します。

5.2.1. フロー制御の原則

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

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

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

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

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

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

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

最新の帯域幅遅延積についての十分な知識があるとしても、フロー制御の実装は困難である可能性があります。フロー制御を使用する時、受信者は TCP の受信バッファを直ちに読み込まなければなりません (MUST)。読み込みに失敗すると、WINDOW_UPDATE などの重要なフレームが HTTP/2.0 で使えず、デッドロックを引き起こす可能性があります。しかしながらフロー制御は、コネクションの利便性を低下させることなく、制約のあるリソースを保護することを保証します。

5.3. ストリームの優先度

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

この値の目的は、エンドポイントが相対的なストリームの優先度を表現できるようにすることです。エンドポイントはストリームに対して優先的にリソースを割り当てるために、この情報を使用することができます。HTTP/2.0 では、送信容量が制限されるような場合にフレームを送信するストリームを選ぶために優先度は使用されます。例えば、エンドポイントは全ての同時アクティブストリームのフレームを送信キューに入れるでしょう。送信が可能になると、優先度の低いストリームよりも前に優先度が高いストリームのフレームが送信されるでしょう。

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

ストリームを生成する間に HEADERS フレーム (6.2節) で明示的に指定されない限り、デフォルトのストリーム優先度は2^30になります。

プッシュストリーム (8.2節) は関連付けられたストリームよりも低い優先度を持ちます。予約済みストリームは関連付けられたストリームの優先度に1を加えた値を継承します。この値の最大値は2^31-1です。

5.4. エラー処理

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

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

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

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

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

GOAWAY は受信側エンドポイントで期待通りに受信されない可能性があります。コネクションエラーが発生した場合、GOAWAY はコネクションが終了した理由をベストエフォートでピアに対して伝えるだけです。

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

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

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

ストリームエラーを検知したエンドポイントは、エラーが発生したストリームのストリーム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)。

6. フレーム定義

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

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

6.1. DATA

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

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

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

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

DATA フレームはフロー制御の対象となり、ストリームが "open" または "half closed (remote)" 状態の問にのみ送信することができます。"open" または "half closed (local)" 状態にないストリームから DATA フレームを受信した場合は、受信者は PROTOCOL_ERROR のコネクションエラー (5.4.1節) で応答しなければなりません (MUST)。

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

                     HEADERS フレームペイロード

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)。
PRIORITY (0x8)
ビット4は、このフレームが最初の4オクテットに1ビットの予約ビットと31ビットの優先度を含むことを示します (5.3節をご覧ください)。このビットが設定されない場合には、最初の4バイトは設定されず、フレームはヘッダーブロックフラグメントのみを含みます。

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

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

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

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

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

SETTINGS フレームはコネクション開始時に送信されなければなりません (MUST)。また、コネクション中どんな時でもいずれかのエンドポイントから送信してもよいものとします (MAY)。

実装はこの仕様で定義される全ての設定に対応しなければなりません (MUST)。また、拡張で定義された追加の設定にも対応してもよいものとします (MAY)。対応していない設定、もしくは有効でない設定は無視されなければなりません (MUST)。また、正常に通信を行うために設定の解釈を求めるような方法で新しい設定を定義したり、実装したりしてはいけません (MUST NOT)。

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でなければなりません (MUST)。Stream Identifier フィールドに0x0以外の値が設定された SETTINGS フレームを受信した場合、エンドポイントは PROTOCOL_ERROR のコネクションエラー (5.4.1節) として応答しなければなりません (MUST)。

SETTINGS フレームは接続状態に影響します。不正な形式や不完全な SETTINGS フレームは、PROTOCOL_ERROR のコネクションエラー (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_HEADER_TABLE_SIZE (1)
送信者が、リモートエンドポイントがヘッダーブロックのデコードに使用するヘッダー圧縮テーブルのサイズを通知することを可能にします。エンコーディングのために利用できる領域は変更されません。すなわちそれは、ヘッダーブロックを受信するピアから送信された設定により決定されます。デフォルトの値は4096バイトです。
SETTINGS_ENABLE_PUSH (2)
この設定はサーバープッシュ (8.2節) を無効化するために使用することができます。値が0になっているこの設定を受信した場合、エンドポイントは PUSH_PROMISE フレームを送信してはいけません (MUST NOT)。初期値は1であり、これはプッシュが許可されていることを示します。
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.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節に記述されています。

ピアエンドポイントの SETTINGS_ENABLE_PUSH 設定が0に設定された場合、PUSH_PROMISE を送信してはいけません (MUST NOT)。

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

PUSH_PROMISE のペイロードには "Promised-Stream-ID" が含まれます。この符号なし31ビットの整数は、エンドポイントがフレームを送信する予定のストリームであることを明確にします。予約済みストリームIDは、送信者により送信される次のストリーム (ストリームID (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 (0x4)
ビット3は、このフレームの後には CONTINUATION フレームが続かず、このフレームに完全なヘッダーブロック (4.3節) が含まれていることを示します。
END_PUSH_PROMISE フラグが設定されていない PUSH_PROMISE フレームの後には、同一ストリームに CONTINUATION フレームが続かなければなりません (MUST)。受信者は、他の種類のフレームや異なるストリームでのフレームの受信を PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

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

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

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

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 への応答も、受信者が関連付けられたストリーム (5.1節をご覧ください) をキャンセルするために RST_STREAM を送信した直後でなければ、PROTOCOL_ERROR のコネクションエラー (5.4.1節) として扱わなければなりません (MUST)。

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 フレームの受信者は、現在のコネクション上で新しい追加のストリームを開始してはなりません (MUST NOT)。しかし、新しいストリームを生成するために新しくコネクションを確立することができます。このフレームの目的は、以前確立したストリームの処理を終了している間であっても、(おそらく、再起動やメンテナンスのために) エンドポイントが新しいストリームの受け入れを適切に停止できるようにすることです。

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

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

GOAWAY フレームの送信後、送信者は新しいストリームのフレームを破棄します。しかしながら、接続状態を変更するフレームは完全には無視されません。たとえば、HEADERS、PUSH_PROMISE、CONTINUATION フレームは、矛盾がない圧縮状態 (4.3節をご覧ください) を保証するために、最低限処理されなければなりません (MUST)。同様に、DATA フレームはコネクションフロー制御ウインドウに対して計算されなければなりません (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 フレームは特定のストリームではなく、コネクションに対して適用されます。

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

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

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

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

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

最終ストリームIDの値と等しいかまたはそれ以下のIDをもつストリームでの処理は、正常に完了する可能性があります。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 フレームはフラグを定義しません。

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.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 接続が最初に確立された時に、65,535バイトの初期フロー制御ウインドウサイズと共に新しいストリームが作成されます。コネクションフロー制御ウインドウは65,535バイトになります。どちらのエンドポイントも、コネクションヘッダーの一部として、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)。

例えば、クライアントがコネクション確立と同時に60KBを送信し、サーバーが初期ウインドウサイズを16KBに設定した場合、クライアントは SETTINGS フレームの受信時に、使用可能なフロー制御ウインドウを-44KBに再計算します。クライアントは、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 交換において、これを使用することができます。

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

6.10. CONTINUATION

CONTINUATION フレーム (type=0xA) は連続するヘッダーブロックフラグメントの続きに使用されます (4.3節)。同一ストリームの直前のフレームが END_HEADERS や END_PUSH_PROMISE が設定されていない 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 フレームは以下のフラグを定義します:

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

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

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 (0)
関連する状態は、エラーの結果ではありません。例えば、GOAWAY はコネクションが適切に終了することを示すためにこのコードを含むかもしれません。
PROTOCOL_ERROR (1)
エンドポイントが不特定のエラーを検知しました。このエラーは明確なエラーコードが提供されていない時に使用されます。
INTERNAL_ERROR (2)
エンドポイントで予期せぬ内部エラーが発生しました。
FLOW_CONTROL_ERROR (3)
エンドポイントがピアのフロー制御プロトコル違反を検知しました。
SETTINGS_TIMEOUT (4)
エンドポイントが SETTINGS フレームを送信したものの、適切な時間内にそのレスポンスを受信しませんでした。設定の同期 (6.5.3節) をご覧ください。
STREAM_CLOSED (5)
エンドポイントが half closed のストリームからフレームを受信しました。
FRAME_SIZE_ERROR (6)
エンドポイントが対応する最大サイズよりも大きいフレームを受信しました。
REFUSED_STREAM (7)
エンドポイントがアプリケーション処理をおこなう前にストリームを拒否しました。詳細は8.1.3節をご覧ください。
CANCEL (8)
ストリームが必要がなくなったことを示すために、エンドポイントが使用します。
COMPRESSION_ERROR (9)
エンドポイントがコネクションのための圧縮コンテキストの維持に失敗しました。
CONNECT_ERROR (10)
CONNECT リクエスト (8.3節) に応じて確立された接続が、リセットまたは不正終了しました。
ENHANCE_YOUR_CALM (420)
ピアが、さらなるフレーム処理の拒否を引き起こす挙動を一定時間にわたって示したことをエンドポイントが検出しました。

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 リクエスト/レスポンスの交換

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

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

  1. 1つの HEADERS フレーム
  2. すぐ後に続く0個以上の連続した CONTINUATION フレーム
  3. 0個以上の DATA フレーム
  4. HEADERS フレームに始まる、0個以上の CONTINUATION フレーム が続く、任意の連続したフレーム

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

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

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

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

8.1.1. 情報提供レスポンス

[[anchor12: この章は大幅に変更する可能性があります。現在はさわりだけ記載しています。]]

HTTP レスポンスコードの 1xx ([HTTP-p2]、6.2節) は HTTP/2.0 ではサポートされません。

HTTP/1.1 リクエストを HTTP/2.0 に変換する中継者は強制的に情報提供レスポンスを生成しなければなりません (MUST)。例えば、変換をおこなう中継者はリクエストが Expect ヘッダーフィールドと "100-continue" トークン ([HTTP-p2]、5.1.1節) を含む場合、100 (Continue) レスポンスを生成します。

HTTP/1.1 レスポンスを HTTP/2.0 に変換する中継者は、情報提供レスポンスを無視しなければなりません (MUST)。

8.1.2. 例

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

リクエストヘッダーフィールドを含み、ボディがない 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
                                   :authority = 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 フレームとその後に続く、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
                                   :scheme = https
{binary data}                      :authority = example.org
                                   :path = /resource
                                   content-type = image/jpeg
                                   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/CONTINUATION フレームは、END_HEADERS と END_STREAM の両方のフラグが設定された終了フレームを含みます。

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

                              HEADERS
                                + END_STREAM
                                + END_HEADERS
                                  foo: bar

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

HTTP/2.0 のリクエストとレスポンスのヘッダーフィールドは、一連のキーと値のペアとして情報を転送します。これには、リクエストの対象 URI や、レスポンスのステータスコード、HTTP ヘッダーフィールドが含まれます。

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

しかしながら、コネクション管理やリクエストのフレーミングに関連するヘッダーフィールドはもはや必要ありません。HTTP ヘッダーフィールドのセマンティクスはこの仕様では変更されません。HTTP/2.0 リクエストは次のヘッダーフィールドを含んではいけません (MUST NOT): Connection、Keep-Alive、Proxy-Connection、TE、Transfer-Encoding、Upgrade。これらのヘッダーフィールドを含むリクエストやレスポンスは不正な形式 (8.1.3.3節) として扱わなければなりません (MUST)。

注: HTTP/2.0 は、HTTP/2.0 から他のプロトコルへのアップグレードを意図的にサポートしません。3章で説明したハンドシェイク方式は、他のプロトコルの使用をネゴシエーションするのに十分だからです。

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

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

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

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

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

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

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

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

8.1.3.3. 不正な形式のリクエストとレスポンス

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

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

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

不正な形式のリクエストやレスポンスを検出する実装は、ストリームが終了したことを保証する必要があります。サーバーは不正な形式のリクエストについて、ストリームを終了したり、リセットをする前に HTTP レスポンスを送信してもよいものとします (MAY)。クライアントは不正な形式のレスポンスを受け入れてはいけません (MUST NOT)。

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

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

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

クライアントは処理されていないリクエストを失敗したものとして扱ってはいけません (MUST NOT)。クライアントは、これら冪等でないメソッドも含むリクエストを自動的に再試行してもよいものとします (MAY)。

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

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

8.2. サーバープッシュ

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

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

サーバーは、安全 ([HTTP-p2]、4.2.1節をご覧ください) で、キャッシュ可能 ([HTTP-p6]、3章をご覧ください) な、リクエストボディを持たないプッシュリクエストのみを送信することができます。

8.2.1. プッシュリクエスト

サーバープッシュは、リクエストした際のサーバーのレスポンスと意味的に等しくなります。サーバーが送信する PUSH_PROMISE フレームは、サーバに対するリクエストヘッダフィールドが全部入ったヘッダーブロックを含みます。ボディを含むリクエストに対するレスポンスをプッシュすることはできません。

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

PUSH_PROMISE のヘッダーフィールドと、その後に続く CONTINUATION フレームは、正しく完全なリクエストヘッダーフィールドのセット(8.1.3.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.3.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 の送信を禁止するものではありません。その場合、クライアントは必要のない予約済みのストリームをリセットする必要があります。

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

8.3. CONNECT メソッド

HTTP 擬似メソッドの CONNECT は HTTP/1.1 接続をリモートホストへのトンネルに変換するために使用されます。CONNECT は、"https" リソースをやりとりする目的でサーバーと TLS セッションを確立するために、主に HTTP プロキシと共に使用されます。

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

CONNECT をサポートするプロキシは、":path" ヘッダーフィールドに指定されたサーバーと TCP コネクション [TCP] を確立します。コネクションの確立に成功すると、[HTTP-p2]、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.0 接続のエラーを検出した場合、プロキシは RST ビットを設定した TCP セグメントを送信しなければなりません (MUST)。

9. 追加の HTTP 要件/検討

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

9.1. コネクション管理

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

クライアントは、特定のオリジン ([RFC6454]) に対して同時に2つ以上の HTTP/2.0 接続を開始すべきではありません (SHOULD NOT)。クライアントは、利用可能なストリームIDが少なくなったコネクションを交換 (5.1.1節) したり、エラーが発生したコネクションを交換 (5.4.1節) したりするために、追加のコネクションを生成することができます。

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

9.2. TLS の機能の利用

HTTP/2.0 の実装は TLS 1.1 [TLS11] に対応しなければなりません (MUST)。[[anchor19: ワーキンググループはこの文書を発行する前に、少なくとも TLS 1.2 [TLSS12] の使用を要求する意向です。TLS 1.1 のネゴシエーションは、初期のドラフトにおける相互運用可能な実装を作成可能にするために認められます。]]

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

TLS 1.1 または SNI のいずれかを含まない TLS ハンドシェイクを受信したサーバーは、HTTP/2.0 のネゴシエーションをしてはなりません (MUST NOT)。 HTTP/2.0 プロトコルを考慮から外すことによって、結果的にクライアントが提示するプロトコルのリストから全てのプロトコルが削除されることもあり得るでしょう。これは、[TLSALPN] の3.2節で述べられるように、プロトコルネゴシエーションの失敗を引き起こします。

実装には [RC4] のような既知の脆弱性がある TLS 暗号化方式をネゴシエーションで使用しないことを推奨します。

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

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

HTTP/2.0 ヘッダーフィールドの名前と値は、長さプレフィクスのあるオクテット列にエンコードされます。これは HTTP/2.0 が、ヘッダーフィールドの名前や値として、いかなる文字列のオクテットも送信すること可能にします。HTTP/2.0 のリクエストやレスポンスを HTTP/1.1 に直接変換する中継者は、不正な HTTP/1.1 メッセージを生成することが可能です。攻撃者は、不正なヘッダーフィールドや追加のヘッダーフィールドを含む HTTP/1.1 メッセージや、完全に改竄された新しいメッセージの生成を中継者が引き起こすよう、この振る舞いを利用するかもしれません。

HTTP/1.1 への変換をおこなう中継者は、リクエストやレスポンスのセマンティクスを変更することはできません。特に、行頭復帰 (U+000D) や改行 (U+000A) などの HTTP/1.1 では認められていない文字を含むヘッダーフィールドの名前や値は、[HTTP-p1]、3.2.4節で規定されているように、逐語的に変換されてはいけません (MUST NOT)。

HTTP/1.x から HTTP/2.0 への変換では、攻撃者に同様の機会を与えません。HTTP/2.0 への変換をおこなう中継者は、ヘッダーフィールドの値からいかなる "obs-fold" な文字を削除しなければなりません (MUST)。

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

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

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

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

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

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

HTTP/2.0 接続は、HTTP/1.1 接続よりも機能するためのリソースの割り当てをより大きく要求します。ヘッダー圧縮とフロー制御の使用により、多くの状態を保存するために実装がリソースを割り当てる必要があります。これらの機能の設定は、各機能に対するメモリーの割り当てを厳密に制限することを保証します。処理能力については、同様のやり方で保護することはできません。

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

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

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

これらの全ての場合においても、このようなプロトコルの仕組みを使用する正当な理由があります。これらの機能は、それらが不要または過剰に使用された時にのみ負荷になります。

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

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

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

12. IANA への配慮

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

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

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

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

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

Protocol
HTTP/2.0
Identification Sequence
0x48 0x54 0x54 0x50 0x2f 0x32 0x2e 0x30 ("HTTP/2.0")
Specification
この文書 (RFCXXXX)

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

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

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

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

+--------+---------------+---------------------------+--------------+
| Frame  | Name          | Flags                     | Section      |
| Type   |               |                           |              |
+--------+---------------+---------------------------+--------------+
| 0      | DATA          | END_STREAM(1)             | Section 6.1  |
| 1      | HEADERS       | END_STREAM(1),            | Section 6.2  |
|        |               | END_HEADERS(4),           |              |
|        |               | PRIORITY(8)               |              |
| 2      | PRIORITY      | -                         | Section 6.3  |
| 3      | RST_STREAM    | -                         | Section 6.4  |
| 4      | SETTINGS      | ACK(1)                    | Section 6.5  |
| 5      | PUSH_PROMISE  | END_PUSH_PROMISE(4)       | Section 6.6  |
| 6      | PING          | ACK(1)                    | Section 6.7  |
| 7      | GOAWAY        | -                         | Section 6.8  |
| 9      | WINDOW_UPDATE | -                         | Section 6.9  |
| 10     | CONTINUATION  | END_HEADERS(4)            | Section 6.10 |
+--------+---------------+---------------------------+--------------+

                              テーブル1

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

この文書は 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.4. 設定レジストリ

この文書は 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.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.0 クライアントの Upgrade に基づくネゴシエーションにのみ使用されます。

13. 謝辞

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

14. 参考文献

14.1. 引用文書

[COMPRESSION]
Ruellan, H. and R. Peon, "HPACK - Header Compression for HTTP/2.0", draft-ietf-httpbis-header-compression-04 (work in progress), October 2013.
[HTTP-p1]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", draft-ietf-httpbis-p1-messaging-24 (work in progress), September 2013.
[HTTP-p2]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", draft-ietf-httpbis-p2-semantics-24 (work in progress), September 2013.
[HTTP-p4]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", draft-ietf-httpbis-p4-conditional-24 (work in progress), September 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-24 (work in progress), September 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-24 (work in progress), September 2013.
[HTTP-p7]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", draft-ietf-httpbis-p7-auth-24 (work in progress), September 2013.
[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.
[RFC6454]
Barth, A., "The Web Origin Concept", RFC 6454, December 2011.
[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.
[TLS11]
Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.1", RFC 4346, April 2006.
[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-02 (work in progress), September 2013.

14.2. 参考文書

[BCP90]
Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.
[RC4]
Rivest, R., "The RC4 encryption algorithm", RSA Data Security, Inc. , March 1992.
[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-07 からの変更

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

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

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

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

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

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

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

A.9. 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]