4. HTTP/3におけるHTTPセマンティクスの表現 (Expressing HTTP Semantics in HTTP/3)
4.1. HTTPメッセージのフレーム化 (HTTP Message Framing)
クライアントはリクエストストリーム (Request Stream) でHTTPリクエストを送信します。これはクライアントが開始した双方向QUICストリームです(セクション6.1参照)。クライアントは、特定のストリームで単一のリクエストのみを送信しなければなりません (MUST)。サーバーは、リクエストと同じストリームで0個以上の暫定HTTP応答 (Interim HTTP Responses) を送信し、その後に単一の最終HTTP応答 (Final HTTP Response) を送信します。暫定および最終HTTP応答の説明については、[HTTP]のセクション15を参照してください。
プッシュ応答 (Pushed Responses) は、サーバーが開始した単方向QUICストリームで送信されます(セクション6.2.2参照)。サーバーは、標準応答と同じ方法で0個以上の暫定HTTP応答を送信し、その後に単一の最終HTTP応答を送信します。プッシュについては、セクション4.6でより詳しく説明されています。
特定のストリームで複数のリクエストを受信すること、または最終HTTP応答の後に追加のHTTP応答を受信することは、不正な形式 (Malformed) として扱わなければなりません (MUST)。
HTTPメッセージ(リクエストまたは応答)は次の要素で構成されます:
-
ヘッダーセクション (Header Section)、メッセージ制御データを含み、単一のHEADERSフレームとして送信されます。
-
オプションで、コンテンツ (Content)(存在する場合)、一連のDATAフレームとして送信されます。および
-
オプションで、トレーラーセクション (Trailer Section)(存在する場合)、単一のHEADERSフレームとして送信されます。
ヘッダーおよびトレーラーセクションは[HTTP]のセクション6.3および6.5で説明されています。コンテンツは[HTTP]のセクション6.4で説明されています。
無効なフレームシーケンスを受信した場合、H3_FRAME_UNEXPECTEDタイプの接続エラー (Connection Error) として扱わなければなりません (MUST)。特に、任意のHEADERSフレームの前のDATAフレーム、またはトレーラーHEADERSフレームの後のHEADERSまたはDATAフレームは無効と見なされます。他のフレームタイプ、特に未知のフレームタイプは、独自のルールに従って許可される場合があります(セクション9参照)。
サーバーは、応答メッセージのフレームの前、後、または間に1つ以上のPUSH_PROMISEフレームを送信できます (MAY)。これらのPUSH_PROMISEフレームは応答の一部ではありません。詳細については、セクション4.6を参照してください。PUSH_PROMISEフレームはプッシュストリームでは許可されません。PUSH_PROMISEフレームを含むプッシュ応答は、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱わなければなりません (MUST)。
未知のタイプのフレーム(セクション9)、予約フレーム (Reserved Frames)(セクション7.2.8)を含むフレームは、このセクションで説明されている他のフレームの前、後、または間にリクエストまたはプッシュストリームで送信できます (MAY)。
HEADERSおよびPUSH_PROMISEフレームは、QPACK動的テーブル (Dynamic Table) への更新を参照する場合があります。これらの更新はメッセージ交換の直接的な部分ではありませんが、メッセージが消費される前に受信および処理される必要があります。詳細については、セクション4.2を参照してください。
転送符号化 (Transfer Codings)([HTTP/1.1]のセクション7参照)はHTTP/3では定義されていません。Transfer-Encodingヘッダーフィールドを使用してはなりません (MUST NOT)。
応答は、1つ以上の暫定応答(1xx、[HTTP]のセクション15.2参照)が同じリクエストに対する最終応答の前にある場合に限り、複数のメッセージで構成できます (MAY)。暫定応答にはコンテンツまたはトレーラーセクションは含まれません。
HTTPリクエスト/応答交換は、クライアントが開始した双方向QUICストリームを完全に消費します。リクエストを送信した後、クライアントは送信用にストリームを閉じなければなりません (MUST)。CONNECTメソッドを使用しない限り(セクション4.4参照)、クライアントはリクエストへの応答の受信に依存してストリームを閉じてはなりません (MUST NOT)。最終応答を送信した後、サーバーは送信用にストリームを閉じなければなりません (MUST)。この時点で、QUICストリームは完全に閉じられます。
ストリームが閉じられると、最終HTTPメッセージの終わりを示します。一部のメッセージは大きいか無制限であるため、エンドポイントは進行するのに十分なメッセージを受信した後、すぐに部分的なHTTPメッセージの処理を開始すべきです (SHOULD)。クライアントが開始したストリームが完全な応答を提供するのに十分なHTTPメッセージなしで終了した場合、サーバーはエラーコードH3_REQUEST_INCOMPLETEで応答ストリームを中止すべきです (SHOULD)。
応答がまだ送信および受信されていないリクエストの一部に依存しない場合、サーバーはクライアントがリクエスト全体を送信する前に完全な応答を送信できます。サーバーがリクエストの残りを受信する必要がない場合、リクエストストリームの読み取りを中止し、完全な応答を送信し、ストリームの送信部分をきれいに閉じることができます (MAY)。クライアントにリクエストストリームでの送信を停止するよう要求する場合、エラーコードH3_NO_ERRORを使用すべきです (SHOULD)。クライアントは、リクエストが突然終了したために完全な応答を破棄してはなりません (MUST NOT)が、クライアントは他の理由で常に自己の判断で応答を破棄できます。サーバーが部分的または完全な応答を送信するがリクエストの読み取りを中止しない場合、クライアントはリクエストのコンテンツの送信を続け、通常通りストリームを閉じるべきです (SHOULD)。
4.1.1. リクエストのキャンセルと拒否 (Request Cancellation and Rejection)
リクエストストリームが開かれると、いずれのエンドポイントもリクエストをキャンセルできます (MAY)。クライアントは応答に興味がなくなった場合にリクエストをキャンセルします。サーバーは応答できない、または応答しないことを選択した場合にリクエストをキャンセルします。可能であれば、サーバーは既に処理を開始したリクエストをキャンセルするのではなく、適切なステータスコードを持つHTTP応答を送信することが推奨されます (RECOMMENDED)。
実装は、まだ開いているストリームの任意の方向を突然終了することによってリクエストをキャンセルすべきです (SHOULD)。これを行うには、実装はストリームの送信部分をリセットし、ストリームの受信部分の読み取りを中止します([QUIC-TRANSPORT]のセクション2.4参照)。
サーバーがアプリケーション処理を実行せずにリクエストをキャンセルする場合、そのリクエストは「拒否された」(Rejected) と見なされます。サーバーは、エラーコードH3_REQUEST_REJECTEDで応答ストリームを中止すべきです (SHOULD)。このコンテキストでは、「処理された」(Processed) とは、ストリームからのデータが何らかの上位層のソフトウェアに渡され、そのソフトウェアが何らかのアクションを実行した可能性があることを意味します。クライアントは、サーバーが拒否したリクエストを送信されなかったものとして扱うことができ、後で再試行できます。
サーバーは、部分的または完全に処理されたリクエストに対してH3_REQUEST_REJECTEDエラーコードを使用してはなりません (MUST NOT)。サーバーが部分処理後に応答を放棄する場合、エラーコードH3_REQUEST_CANCELLEDで応答ストリームを中止すべきです (SHOULD)。
クライアントは、エラーコードH3_REQUEST_CANCELLEDを使用してリクエストをキャンセルすべきです (SHOULD)。このエラーコードを受信すると、処理が実行されていない場合、サーバーはエラーコードH3_REQUEST_REJECTEDで応答を突然終了できます (MAY)。クライアントは、サーバーがこのエラーコードでリクエストストリームを閉じることを要求していない限り、H3_REQUEST_REJECTEDエラーコードを使用してはなりません (MUST NOT)。
完全な応答を受信した後にストリームがキャンセルされた場合、クライアントはキャンセルを無視して応答を使用できます (MAY)。ただし、部分的な応答を受信した後にストリームがキャンセルされた場合、応答を使用すべきではありません (SHOULD NOT)。GET、PUT、DELETEなどの冪等操作 (Idempotent Actions) のみを安全に再試行できます。クライアントは、リクエストセマンティクスがメソッドに依存せずに冪等であることを知る方法がない限り、または元のリクエストが適用されなかったことを検出する方法がない限り、非冪等メソッドを持つリクエストを自動的に再試行すべきではありません (SHOULD NOT)。詳細については、[HTTP]のセクション9.2.2を参照してください。
4.1.2. 不正な形式のリクエストと応答 (Malformed Requests and Responses)
不正な形式のリクエストまたは応答とは、それ以外は有効なフレームシーケンスですが、次の理由で無効なものです:
-
禁止されたフィールドまたは疑似ヘッダーフィールド (Pseudo-Header Fields) の存在、
-
必須の疑似ヘッダーフィールドの欠落、
-
疑似ヘッダーフィールドの値が無効、
-
疑似ヘッダーフィールドがフィールドの後にある、
-
HTTPメッセージのシーケンスが無効、
-
大文字のフィールド名を含む、または
-
フィールド名または値に無効な文字を含む。
Content-Lengthヘッダーフィールド([HTTP]のセクション8.6)を含む場合、コンテンツを持つと定義されたリクエストまたは応答は、Content-Lengthヘッダーフィールドの値が受信したDATAフレームの長さの合計と等しくない場合、不正な形式です。コンテンツを持たないと定義された応答(Content-Lengthが存在する場合でも)は、DATAフレームにコンテンツが含まれていない場合でも、非ゼロのContent-Lengthヘッダーフィールドを持つことができます。
HTTPリクエストまたは応答を処理する中間者(つまり、トンネルとして機能しない中間者)は、不正な形式のリクエストまたは応答を転送してはなりません (MUST NOT)。検出された不正な形式のリクエストまたは応答は、H3_MESSAGE_ERRORタイプのストリームエラー (Stream Error) として扱わなければなりません (MUST)。
不正な形式のリクエストの場合、サーバーはストリームを閉じるかリセットする前にエラーを示すHTTP応答を送信できます (MAY)。クライアントは不正な形式の応答を受け入れてはなりません (MUST NOT)。これらの要件は、HTTPに対するいくつかの一般的な攻撃タイプから保護することを目的としています。これらは意図的に厳格です。なぜなら、寛容であることは実装をこれらの脆弱性にさらす可能性があるためです。
4.2. HTTPフィールド (HTTP Fields)
HTTPメッセージは、「HTTPフィールド」(HTTP Fields) と呼ばれる一連のキーと値のペアとしてメタデータを運びます([HTTP]のセクション6.3および6.5参照)。登録されたHTTPフィールドのリストについては、https://www.iana.org/assignments/http-fields/ で管理されている「ハイパーテキスト転送プロトコル (HTTP) フィールド名レジストリ」(Hypertext Transfer Protocol (HTTP) Field Name Registry) を参照してください。HTTP/2と同様に、HTTP/3には、フィールド名での文字の使用、Connectionヘッダーフィールド、および疑似ヘッダーフィールドに関する追加の考慮事項があります。
フィールド名は、ASCII文字のサブセットを含む文字列です。HTTPフィールド名と値のプロパティは、[HTTP]のセクション5.1でより詳細に説明されています。フィールド名の文字は、エンコーディングの前に小文字に変換されなければなりません (MUST)。フィールド名に大文字を含むリクエストまたは応答は、不正な形式として扱わなければなりません (MUST)。
HTTP/3は、接続固有のフィールドを示すためにConnectionヘッダーフィールドを使用しません。このプロトコルでは、接続固有のメタデータは他の手段で伝達されます。エンドポイントは、接続固有のフィールドを含むHTTP/3フィールドセクションを生成してはなりません (MUST NOT)。接続固有のフィールドを含むメッセージは、不正な形式として扱わなければなりません (MUST)。
唯一の例外はTEヘッダーフィールドで、HTTP/3リクエストヘッダーに存在できます (MAY)。存在する場合、「trailers」以外の値を含んではなりません (MUST NOT)。
HTTP/1.xメッセージをHTTP/3に変換する中間者は、[HTTP]のセクション7.6.1で説明されているように、接続固有のヘッダーフィールドを削除しなければなりません (MUST)。そうしないと、メッセージは他のHTTP/3エンドポイントによって不正な形式として扱われます。
4.2.1. フィールド圧縮 (Field Compression)
[QPACK]は、圧縮によって引き起こされるヘッドオブラインブロッキング (Head-of-Line Blocking) の量をエンコーダーがある程度制御できるHPACKの変形を説明しています。これにより、エンコーダーは圧縮効率とレイテンシーのバランスを取ることができます。HTTP/3は、QPACKを使用してヘッダーおよびトレーラーセクションを圧縮します。これには、ヘッダーセクションに存在する制御データが含まれます。
より良い圧縮効率を可能にするために、Cookieヘッダーフィールド ([COOKIES]) は、圧縮前に個別のフィールド行に分割できます (MAY)。各行には1つ以上のcookieペアが含まれます。解凍されたフィールドセクションに複数のcookieフィールド行が含まれている場合、これらは、HTTP/2またはHTTP/3以外のコンテキスト(HTTP/1.1接続や汎用HTTPサーバーアプリケーションなど)に渡される前に、2バイトの区切り文字「; 」(ASCII 0x3b、0x20)を使用して単一のバイト文字列に連結されなければなりません (MUST)。
4.2.2. ヘッダーサイズの制約 (Header Size Constraints)
HTTP/3実装は、個々のHTTPメッセージで受け入れるメッセージヘッダーの最大サイズに制限を課すことができます (MAY)。処理する意思のあるヘッダーセクションよりも大きいヘッダーセクションを受信したサーバーは、HTTP 431(リクエストヘッダーフィールドが大きすぎる)(Request Header Fields Too Large) ステータスコード ([RFC6585]) を送信できます。クライアントは、処理できない応答を破棄できます。フィールドリストのサイズは、名前と値のバイト長を含むフィールドの非圧縮サイズに基づいて計算され、各フィールドに32バイトのオーバーヘッドが追加されます。
実装がこの制限をピアに通知したい場合、SETTINGS_MAX_FIELD_SECTION_SIZEパラメーターでバイト数として伝達できます。このパラメーターを受信した実装は、示されたサイズを超えるHTTPメッセージヘッダーを送信すべきではありません (SHOULD NOT)。ピアがそれを処理することを拒否する可能性が高いためです。ただし、HTTPメッセージはオリジンサーバーに到達する前に1つ以上の中間者を通過する可能性があります([HTTP]のセクション3.7参照)。この制限はメッセージを処理する各実装によって個別に適用されるため、この制限を下回るメッセージが受け入れられることは保証されません。
4.3. HTTP制御データ (HTTP Control Data)
HTTP/2と同様に、HTTP/3は一連の疑似ヘッダーフィールド (Pseudo-Header Fields) を採用しています。フィールド名は:文字(ASCII 0x3a)で始まります。これらの疑似ヘッダーフィールドはメッセージ制御データを伝達します([HTTP]のセクション6.2参照)。
疑似ヘッダーフィールドはHTTPフィールドではありません。エンドポイントは、このドキュメントで定義されているもの以外の疑似ヘッダーフィールドを生成してはなりません (MUST NOT)。ただし、拡張機能はこの制限の変更を交渉できます(セクション9参照)。
疑似ヘッダーフィールドは、定義されたコンテキストでのみ有効です。リクエスト用に定義された疑似ヘッダーフィールドは応答に現れてはなりません (MUST NOT)。応答用に定義された疑似ヘッダーフィールドはリクエストに現れてはなりません (MUST NOT)。疑似ヘッダーフィールドはトレーラーセクションに現れてはなりません (MUST NOT)。エンドポイントは、未定義または無効な疑似ヘッダーフィールドを含むリクエストまたは応答を不正な形式として扱わなければなりません (MUST)。
すべての疑似ヘッダーフィールドは、ヘッダーセクション内の通常のヘッダーフィールドの前に現れなければなりません (MUST)。通常のヘッダーフィールドの後のヘッダーセクションに現れる疑似ヘッダーフィールドを含むリクエストまたは応答は、不正な形式として扱わなければなりません (MUST)。
4.3.1. リクエスト疑似ヘッダーフィールド (Request Pseudo-Header Fields)
リクエスト用に次の疑似ヘッダーフィールドが定義されています:
":method": HTTPメソッド (HTTP Method) を含みます([HTTP]のセクション9)
":scheme": ターゲットURIのscheme部分を含みます([URI]のセクション3.1)。
:scheme疑似ヘッダーは、schemeが「http」および「https」のURIに限定されません。プロキシまたはゲートウェイは、非HTTPスキームのリクエストを変換でき、HTTPを使用して非HTTPサービスと対話できるようになります。
「https」以外のschemeの使用に関するガイダンスについては、セクション3.1.2を参照してください。
":authority": ターゲットURIのauthority部分を含みます([URI]のセクション3.2)。authorityは、schemeが「http」または「https」のURIの非推奨のuserinfoサブコンポーネントを含んではなりません (MUST NOT)。
HTTP/1.1リクエスト行を正確に再現できるようにするため、メソッド固有の形式のリクエストターゲットを持つHTTP/1.1リクエストから変換する場合、この疑似ヘッダーフィールドは省略されなければなりません (MUST)([HTTP]のセクション7.1参照)。HTTP/3リクエストを直接生成するクライアントは、Hostヘッダーフィールドの代わりに:authority疑似ヘッダーフィールドを使用すべきです (SHOULD)。HTTP/3リクエストをHTTP/1.1に変換する中間者は、リクエストにHostフィールドが存在しない場合、:authority疑似ヘッダーフィールドの値をコピーしてHostフィールドを作成しなければなりません (MUST)。
":path": ターゲットURIのpathおよびquery部分を含みます(「path-absolute」プロダクションおよびオプションで?文字(ASCII 0x3f)に続く「query」プロダクション。[URI]のセクション3.3および3.4を参照)。
この疑似ヘッダーフィールドは、「http」または「https」URIでは空であってはなりません (MUST NOT)。pathコンポーネントを含まない「http」または「https」URIは、値/(ASCII 0x2f)を含まなければなりません (MUST)。pathコンポーネントを含まないOPTIONSリクエストは、:path疑似ヘッダーフィールドの値*(ASCII 0x2a)を含みます([HTTP]のセクション7.1参照)。
すべてのHTTP/3リクエストは、リクエストがCONNECTリクエストでない限り、:method、:scheme、および:path疑似ヘッダーフィールドの正確に1つの値を含まなければなりません (MUST)(セクション4.4参照)。
:scheme疑似ヘッダーフィールドが必須のauthorityコンポーネントを持つscheme(「http」および「https」を含む)を識別する場合、リクエストは:authority疑似ヘッダーフィールドまたはHostヘッダーフィールドのいずれかを含まなければなりません (MUST)。これらのフィールドが存在する場合、空であってはなりません (MUST NOT)。両方のフィールドが存在する場合、同じ値を含まなければなりません (MUST)。schemeに必須のauthorityコンポーネントがなく、リクエストターゲットに提供されていない場合、リクエストは:authority疑似ヘッダーまたはHostヘッダーフィールドを含んではなりません (MUST NOT)。
必須の疑似ヘッダーフィールドを省略するか、これらの疑似ヘッダーフィールドに無効な値を含むHTTPリクエストは、不正な形式です。
HTTP/3は、HTTP/1.1リクエスト行に含まれるバージョン識別子を運ぶ方法を定義していません。HTTP/3リクエストは暗黙的にプロトコルバージョン「3.0」を持ちます。
4.3.2. 応答疑似ヘッダーフィールド (Response Pseudo-Header Fields)
応答の場合、HTTPステータスコードを運ぶ単一の「:status」疑似ヘッダーフィールドが定義されています([HTTP]のセクション15参照)。この疑似ヘッダーフィールドはすべての応答に含まれなければなりません (MUST)。そうでない場合、応答は不正な形式です(セクション4.1.2参照)。
HTTP/3は、HTTP/1.1ステータス行に含まれるバージョンまたは理由句 (Reason Phrase) を運ぶ方法を定義していません。HTTP/3応答は暗黙的にプロトコルバージョン「3.0」を持ちます。
4.4. CONNECTメソッド (The CONNECT Method)
CONNECTメソッドは、受信者がリクエストターゲットによって識別される宛先オリジンサーバーへのトンネル (Tunnel) を確立することを要求します([HTTP]のセクション9.3.6参照)。これは主にHTTPプロキシと共に使用され、「https」リソースと対話するためにオリジンサーバーとのTLSセッションを確立します。
HTTP/1.xでは、CONNECTはHTTP接続全体をリモートホストへのトンネルに変換するために使用されます。HTTP/2およびHTTP/3では、CONNECTメソッドは単一のストリーム上でトンネルを確立するために使用されます。
CONNECTリクエストは次のように構築されなければなりません (MUST):
-
:method疑似ヘッダーフィールドを「CONNECT」に設定
-
:schemeおよび:path疑似ヘッダーフィールドを省略
-
:authority疑似ヘッダーフィールドに接続先のホストとポートを含める(CONNECTリクエストのリクエストターゲットのauthority-formと同等。[HTTP]のセクション7.1参照)。
リクエストストリームは、転送されるデータを運ぶためにリクエストの終了時に開いたままになります。これらの制限に準拠しないCONNECTリクエストは不正な形式です。
CONNECTをサポートするプロキシは、:authority疑似ヘッダーフィールドで識別されるサーバーへのTCP接続 ([RFC0793]) を確立します。この接続が正常に確立されると、プロキシは、[HTTP]のセクション15.3で定義されているように、2xxシリーズのステータスコードを含むHEADERSフレームをクライアントに送信します。
ストリーム上のすべてのDATAフレームは、TCP接続で送信または受信されたデータに対応します。クライアントが送信するDATAフレームのペイロードは、プロキシによってTCPサーバーに送信されます。TCPサーバーから受信したデータは、プロキシによってDATAフレームにパッケージ化されます。TCPセグメントのサイズと数は、HTTP DATAまたはQUIC STREAMフレームのサイズと数に予測可能にマッピングされることは保証されていません。
CONNECTメソッドが完了すると、ストリームで送信できるのはDATAフレームのみです。拡張機能の定義で明示的に許可されている場合、拡張フレームを使用できます (MAY)。他の既知のフレームタイプを受信した場合、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱わなければなりません (MUST)。
TCP接続はいずれのピアによっても閉じることができます。クライアントがリクエストストリームを終了すると(つまり、プロキシでの受信ストリームが「Data Recvd」状態に入ると)、プロキシはTCPサーバーへの接続でFINビットを設定します。プロキシがFINビットが設定されたパケットを受信すると、クライアントに送信する送信ストリームを閉じます。単一方向で半分閉じた (Half-Closed) ままのTCP接続は無効ではありませんが、サーバーによって適切に処理されないことが多いため、クライアントはCONNECTのターゲットからデータを受信することをまだ期待している間は、送信用のストリームを閉じるべきではありません (SHOULD NOT)。
TCP接続エラーは、ストリームを突然終了することによって通知されます。プロキシは、RSTビットが設定されたTCPセグメントの受信を含むTCP接続のエラーを、H3_CONNECT_ERRORタイプのストリームエラーとして扱います。
対応して、プロキシがストリームまたはQUIC接続でエラーを検出した場合、TCP接続を閉じなければなりません (MUST)。プロキシがクライアントがストリームをリセットしたか、ストリームからの読み取りを中止したことを検出した場合、TCP接続を閉じなければなりません (MUST)。ストリームがリセットされたか、クライアントによって読み取りが中止された場合、プロキシは、ストリームの両方向がキャンセルされることを保証するために、他の方向でも同じ操作を実行すべきです (SHOULD)。これらすべてのケースで、基礎となるTCP実装が許可する場合、プロキシはRSTビットが設定されたTCPセグメントを送信すべきです (SHOULD)。
CONNECTは任意のサーバーへのトンネルを作成するため、CONNECTをサポートするプロキシは、その使用を既知のポートのセットまたは安全なリクエストターゲットのリストに制限すべきです (SHOULD)。詳細については、[HTTP]のセクション9.3.6を参照してください。
4.5. HTTPアップグレード (HTTP Upgrade)
HTTP/3は、HTTPアップグレードメカニズム (HTTP Upgrade Mechanism)([HTTP]のセクション7.8)または101(プロトコル切り替え)(Switching Protocols) 情報ステータスコード([HTTP]のセクション15.2.2)をサポートしていません。
4.6. サーバープッシュ (Server Push)
サーバープッシュ (Server Push) は、クライアントがリクエストを行うことを予期して、サーバーがリクエスト-応答交換をクライアントにプッシュすることを許可するインタラクションモードです。クライアントは、SETTINGSフレームでSETTINGS_ENABLE_PUSHを0に設定することにより、サーバープッシュを無効にできます。サーバーは、SETTINGS_ENABLE_PUSHが0に設定されたクライアントにプッシュを送信してはなりません (MUST NOT)。これに違反するサーバーの動作は、H3_SETTINGS_ERRORタイプの接続エラーとして扱わなければなりません。
HTTP/2と同様に、サーバーはクライアントが開始したリクエストストリームでPUSH_PROMISEフレーム(セクション7.2.5)を送信することによってプッシュを開始します。プッシュIDは、サーバープッシュを識別するために使用されます(セクション4.6.1参照)。プッシュIDはPUSH_PROMISEフレームで運ばれます。このフレームには、[HTTP]のセクション15で説明されているように、サーバーが生成したリクエストに帰属するリクエストヘッダーセクションも含まれます。
サーバーは、自身が開始したプッシュストリーム(セクション6.2.2)から応答を送信します。プッシュ応答の配信は、通常のリクエストへの応答と同じ方法で行われます。プッシュ応答の応答ヘッダーセクションは、セクション7.2.4で説明されているHEADERSフレームで運ばれます。サーバーは、プッシュストリームでプッシュIDを含むCANCEL_PUSHフレームを送信することにより、約束されたプッシュをキャンセルできます。
クライアントは、MAX_PUSH_IDフレームを使用して、サーバーが約束できるプッシュの数を制御します(セクション7.2.7)。サーバーは、クライアントが接続に対して提供した最大プッシュIDよりも大きいプッシュIDを持つPUSH_PROMISEフレームまたはCANCEL_PUSHフレームを送信してはなりません (MUST NOT)。これを試みるクライアントは、H3_ID_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。
プッシュストリームがPUSH_PROMISEフレームによって開かれるか予約されると、クライアントがプッシュをキャンセルしない限り、プッシュストリームを使用できます。クライアントがコントロールストリームからCANCEL_PUSHフレームを受信するか、プッシュストリームからストリーム終了を受信すると、プッシュはキャンセルされます。プッシュストリームがCANCEL_PUSHなしで終了した場合、プッシュは正常に完了したと見なされます。
クライアントは、CANCEL_PUSHフレームを送信することによってプッシュを中止できます。サーバーが受信した後、プッシュがまだ完了していない場合、サーバーはプッシュの送信を中止しなければなりません (MUST)。クライアントは、プッシュストリームをリセットすることによってプッシュを中止することもできます。どちらの場合も、受信者は受信済みのプッシュ応答ステータスを安全に破棄できます。
リクエストストリームが閉じられると、実装はプッシュ応答への参照のみをバッファリングすることを選択するか、プッシュ応答への参照を完全に削除することができます。プッシュ応答が受信され、関連するリクエストストリームが閉じられた場合、これはプッシュの失敗を示すものではありません。
プッシュストリームは常にプッシュIDによって参照されます。PUSH_PROMISEフレームの受信者は、プッシュIDをクライアントが開始したストリームに関連付け、プッシュストリームでHEADERSフレームを受信するクライアントは、プッシュIDを受信したプッシュと照合します。
4.6.1. プッシュID (Push IDs)
プッシュIDは、サーバープッシュを識別するために使用される62ビットの符号なし整数([QUIC-TRANSPORT]のセクション16参照)です。プッシュIDは接続の有効期間内で一意です。
プッシュID空間はゼロから始まり、整数空間のサブセットです。したがって、プッシュIDは、ストリームIDまたはリクエストIDが必要なコンテキストには現れることができません。特に、プッシュIDはGOAWAYフレーム(セクション5.2参照)に現れることは許可されていません。
プッシュIDは、単一のPUSH_PROMISEフレーム(セクション7.2.5参照)および単一のプッシュストリーム(セクション4.6および6.2.2参照)に使用されます。これらの使用は、接続の有効期間内にサーバーが行った同じ約束のプッシュを参照しなければなりません。
プッシュストリームでプッシュ応答を送信した後、プッシュIDを再利用することはできません。クライアントが同じプッシュIDで異なるストリームから別のプッシュストリームヘッダーまたは別のPUSH_PROMISEを受信した場合、これはH3_ID_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。