Open13

Hypertext Transfer Protocol Version 3 (HTTP/3)

voluntasvoluntas

Hypertext Transfer Protocol Version 3 (HTTP/3)

概要

QUICトランスポートプロトコルは、ストリームの多重化、ストリームごとのフロー制御、低レイテンシーのコネクション確立など、HTTPのトランスポートとして望ましい機能をいくつか備えています。本ドキュメントでは、QUIC上のHTTPセマンティクスのマッピングについて説明します。また、本文書では、QUIC に包含される HTTP/2 の機能を特定し、HTTP/2 の拡張機能をどのように HTTP/3 に移植するかを説明しています。

voluntasvoluntas

1. はじめに

HTTP セマンティクス ([SEMANTICS]) は、インターネット上のさまざまなサービスに使用されています。これらのセマンティクスは、HTTP/1.1 と HTTP/2 で最も一般的に使用されています。HTTP/1.1 はさまざまなトランスポート層やセッション層で使用されてきましたが、HTTP/2 は主に TLS over TCP で使用されてきました。HTTP/3は、新しいトランスポートプロトコルであるQUICで同じセマンティクスをサポートしています。

1.1. HTTP の旧バージョン

HTTP/1.1 ([HTTP11])では、HTTP メッセージの伝達に空白で区切られたテキストフィールドを使用していました。これらのメッセージは人間が読むことができますが、メッセージのフォーマットにホワイトスペースを使用すると、解析が複雑になり、異なる動作が許容されすぎてしまいます。

また、HTTP/1.1には多重化層がないため、複数のTCPコネクションを使ってリクエストを並行して処理することが多い。しかし、TCPは複数の接続で輻輳制御を共有しないため、輻輳制御やネットワーク効率に悪影響を及ぼします。

HTTP/2 ([HTTP2])では、トランスポート層に手を加えることなくレイテンシーを改善するために、バイナリフレーミングとマルチプレクス層を導入しました。しかし、HTTP/2 の多重化の並列性は、TCP の損失回復メカニズムからは見えないため、パケットの損失や順序変更は、そのトランザクションが損失パケットの影響を直接受けたかどうかに関わらず、すべてのアクティブなトランザクションにストールを引き起こします。

1.2. QUICへの委譲

QUICのトランスポートプロトコルには、HTTP/2のフレーミングレイヤーで提供されるものと同様に、ストリームの多重化とストリームごとのフローコントロールが組み込まれています。ストリームレベルでの信頼性と接続全体での輻輳制御を提供することで、QUICはTCPマッピングと比較してHTTPのパフォーマンスを向上させる能力を持っています。また、QUICはトランスポート層にTLS 1.3([TLS13])を組み込んでおり、TCP上でTLSを実行するのと同等の機密性と完全性を提供するとともに、TCP Fast Open([TFO])による接続設定の待ち時間を改善しています。

本文書では、HTTP/2 の設計を参考に、QUIC トランスポートプロトコル上の HTTP セマンティクスのマッピングである HTTP/3 を定義しています。HTTP/3は、データの機密性と完全性の保護、ピア認証、そして信頼性の高いインオーダーでのストリームごとの配信を実現するためにQUICに依存しています。ストリームの寿命やフローコントロールの問題をQUICに委ねる一方で、HTTP/2のフレーミングに似たバイナリフレーミングが各ストリームで使用されています。いくつかのHTTP/2の機能はQUICに包含され、他の機能はQUICの上に実装されています。

QUICは[QUIC-TRANSPORT]で説明されています。HTTP/2の完全な説明については、[HTTP2]を参照してください。

voluntasvoluntas

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

HTTP/3 は、QUIC トランスポートプロトコルと、HTTP/2 と同様の内部フレーミングレイヤーを用いて、HTTP セマンティクスのトランスポートを提供します。

クライアントは、あるエンドポイントに HTTP/3 サーバーが存在することを知ると、QUIC 接続を開きます。QUICはプロトコルネゴシエーション、ストリームベースのマルチプレックス、フローコントロールを提供します。HTTP/3エンドポイントの発見については、セクション3.1で説明します。

各ストリーム内では、HTTP/3通信の基本単位はフレームです(7.2項)。各フレームタイプは、それぞれ異なる目的を持っています。例えば、HEADERSやDATAフレームは、HTTPリクエストやレスポンスの基本となるものです (セクション4.1)。接続全体に適用されるフレームは、専用の制御ストリームで伝達されます。

リクエストの多重化は、[QUIC-TRANSPORT]のセクション2で説明されているQUIC stream abstractionを使用して実行されます。各リクエストとレスポンスのペアは、1つのQUICストリームを消費する。ストリームは互いに独立しているため、1つのストリームがブロックされたりパケットロスが発生しても、他のストリームの進行が妨げられることはない。

サーバープッシュとは、HTTP/2 ([HTTP2])で導入されたインタラクションモードで、クライアントが指示されたリクエストを行うのを見越して、サーバーがリクエストとレスポンスの交換をクライアントにプッシュすることができます。これにより、ネットワークの使用量と潜在的な遅延の増加が相殺されます。PUSH_PROMISE、MAX_PUSH_ID、CANCEL_PUSH など、いくつかの HTTP/3 フレームがサーバーのプッシュを管理するために使用されます。

HTTP/2 と同様に、リクエストとレスポンスのフィールドは送信のために圧縮されます。HPACK ([HPACK])は、圧縮されたフィールドセクションの順不同の伝送に依存しているため(QUICでは保証されていません)、HTTP/3はHPACKをQPACK ([QPACK])に置き換えました。QPACKでは、フィールドテーブルの状態を変更・追跡するために別の一方向ストリームを使用しますが、エンコードされたフィールドセクションはテーブルの状態を変更せずに参照します。

2.1. ドキュメントの構成

以下のセクションでは、HTTP/3接続のライフサイクルについて詳しく説明しています。

  • Connection Setup and Management (Section 3) では、HTTP/3 エンドポイントが発見され、HTTP/3 接続が確立されるまでを説明します。
  • HTTP Request Lifecycle (セクション 4) では、HTTP セマンティクスがフレームを使ってどのように表現されるかを説明します。
  • Connection Closure (セクション5)では、HTTP/3の接続がどのようにして優雅に、あるいは突然に終了するかを説明します。

ワイヤプロトコルの詳細とトランスポートとの相互作用については、後続のセクションで説明します。

  • Stream Mapping and Usage (セクション6) では、QUICストリームの使用方法について説明します。
  • HTTPフレーム層(セクション7)では、ほとんどのストリームで使用されるフレームについて説明しています。
  • エラー処理(セクション8)では、特定のストリームまたは接続全体において、エラー状態をどのように処理し、表現するかについて説明しています。

最後のセクションでは、追加のリソースを提供します。

  • HTTP/3 の拡張 (セクション 9) では、将来のドキュメントで新しい機能を追加する方法を説明しています。
  • HTTP/2 と HTTP/3 のより詳細な比較は、付録 A にあります。

2.2. 規約と用語

本文書のキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「NOT RECOMMENDED」、「MAY」、「OPTIONAL」は、ここに示すようにすべて大文字で表示されている場合に限り、BCP 14 [RFC2119] [RFC8174]に記載されたとおりに解釈されます。

本文書では、[QUIC-TRANSPORT]の可変長整数エンコーディングを使用しています。

以下の用語を使用しています。

アボート
コネクションやストリームの突然の終了(おそらくエラー状態が原因)。

クライアント。
HTTP/3接続を開始するエンドポイント。クライアントは、HTTPリクエストを送信し、HTTPレスポンスを受信します。

接続。
2つのエンドポイント間のトランスポート層の接続で、トランスポートプロトコルとしてQUICを使用する。

コネクションエラー。
HTTP/3コネクション全体に影響するエラー。

エンドポイント
コネクションのクライアントまたはサーバーのいずれか。

フレーム。
HTTP/3におけるストリーム上の通信の最小単位で、フレームタイプに応じて構造化されたヘッダと可変長のバイト列で構成されます。

フレーム」と呼ばれるプロトコル要素は、本文書と[QUIC-TRANSPORT]の両方に存在します。QUIC-TRANSPORT]のフレームを参照する場合は、フレーム名の前に "QUIC "を付けます。例:"QUIC CONNECTION_CLOSE frames." この前書きのない参照は、7.2節で定義されたフレームを指します。

HTTP/3接続。
ネゴシエートされたアプリケーションプロトコルがHTTP/3であるQUIC接続のこと。

peer。
エンドポイントのこと。特定のエンドポイントについて議論する場合、「ピア」とは、議論の対象となる主な対象に対して遠隔地にあるエンドポイントを指す。

受信機。
フレームを受信しているエンドポイント。

sender:フレームを送信するエンドポイント。
フレームを送信しているエンドポイント。

サーバー
HTTP/3の接続を受け付けるエンドポイントです。サーバーは、HTTPリクエストを受信し、HTTPレスポンスを送信します。

ストリーム。
QUICトランスポートで提供される双方向または片方向のバイテストリーム。HTTP/3接続内のすべてのストリームは「HTTP/3ストリーム」とみなすことができますが、HTTP/3では複数のストリームタイプが定義されています。

ストリームエラー。
個々のストリームに関するアプリケーションレベルのエラー。

コンテンツ」という用語は、[SEMANTICS]の6.4節で定義されています。

最後に、「リソース」、「メッセージ」、「ユーザーエージェント」、「オリジンサーバー」、「ゲートウェイ」、「インターミディエイト」、「プロキシ」、「トンネル」という用語は、[SEMANTICS]のセクション3で定義されています。

本文書のパケット図は、[QUIC-TRANSPORT]の1.3節で定義されているフォーマットを使用して、フィールドの順序とサイズを示しています。

voluntasvoluntas

3. 接続の設定と管理

3.1. HTTP/3 エンドポイントの発見

HTTP は、権威あるレスポンスという概念に依存しています。これは、ターゲット URI 内で特定されたオリジンサーバーによって (またはその指示によって) レスポンスメッセージが発信された時点で、ターゲットリソースの状態を考慮して、そのリクエストに対する最も適切なレスポンスであると判断されたレスポンスです。HTTP URIの権威あるサーバーを探すことについては、[SEMANTICS]のセクション4.3で説明されています。

https」スキームでは、権威を、URIの権威コンポーネントで識別されるホス トに対してクライアントが信頼できると考える証明書の所有と関連付ける。TLSハンドシェイクでサーバーの証明書を受け取ると、クライアントは、[SEMANTICS]のセクション4.3.4で説明されているプロセスを使用して、その証明書がURIのオリジンサーバーに対して受け入れ可能な一致であることを検証しなければなりません(MUST)。URIのオリジンサーバーに関して証明書が検証できない場合、クライア ントはそのオリジンに対してそのサーバーを権威あるものとみなしてはならない(MUST NOT)。

クライアントは、ホスト識別子をIPアドレスに解決し、指定されたポートでそのアドレスへのQUIC接続を確立し(上述のサーバー証明書の検証を含む)、その安全な接続を介してサーバーにURIをターゲットにしたHTTP/3リクエストメッセージを送信することで、「https」URIを持つリソースへのアクセスを試みてもよい[MAY]。HTTP/3を選択するために他のメカニズムが使用されていない限り、トークン「h3」は、TLSハンドシェイク中のApplication-Layer Protocol Negotiation(ALPN、[RFC7301]参照)エクステンションで使用されます。

接続性の問題(UDPのブロックなど)により、QUICの接続確立が失敗することがあります。この場合、クライアントはTCPベースのHTTPバージョンの使用を試みるべきです(SHOULD)。

サーバーは、任意のUDPポートでHTTP/3を提供してもよいものとします(MAY)。代替サービスの広告は常に明示的なポートを含み、URIは明示的なポートまたはスキームに関連付けられたデフォルトポートのいずれかを含みます。

3.1.1. HTTP 代替サービス

HTTP オリジンは、Alt-Svc HTTP レスポンスヘッダーフィールドや HTTP/2 ALTSVC フレーム ([ALTSVC]) を通じて、"h3" ALPN トークンを用いて、同等の HTTP/3 エンドポイントが利用可能であることを宣伝することができます。

例えば、オリジンは HTTP レスポンスの中で、同じホスト名の UDP ポート 50781 で HTTP/3 が利用可能であることを、以下のようなヘッダーフィールドを含むことで示すことができます。

Alt-Svc: h3=":50781"

HTTP/3のサポートを示すAlt-Svcレコードを受信すると、クライアントは、指定されたホストとポートへのQUIC接続の確立を試みてもよいものとします(MAY)。

3.1.2. その他のスキーム

HTTPはトランスポートプロトコルから独立しているが、「http」スキームは、権限コンポーネント内で識別されたあらゆるホストの指定されたポート上でTCP接続を受信する能力を権限に関連付けるものである。HTTP/3はTCPを使用しないため、HTTP/3は「http」URIで識別されるリソースの権威サーバーへの直接アクセスには使用できません。しかし、[ALTSVC]のようなプロトコル拡張は、権威サーバが権威を持ち、HTTP/3で到達可能な他のサービスを特定することを可能にします。

スキームが「https」ではないオリジンへのリクエストを行う前に、クライアントは、サーバーがそのスキームを提供する意思があることを確認しなければなりません(MUST)。スキームが "http "であるオリジンに対しては、これを実現するための実験的な方法が[RFC8164]に記述されている。将来的には、さまざまなスキームに対して他のメカニズムが定義されるかもしれない。

3.2. 接続の確立

HTTP/3は、基礎となるトランスポートとしてQUICバージョン1に依存しています。HTTP/3での他のQUICトランスポートバージョンの使用は、将来の仕様で定義されてもよいものとします。

QUICバージョン1は、ハンドシェークプロトコルとしてTLSバージョン1.3以上を使用します。HTTP/3クライアントは、TLSハンドシェイク中にサーバーにターゲットホストを示すメカニズムをサポートしなければなりません(MUST)。サーバがドメイン名([DNS-TERMS])で識別される場合、クライアントは、ターゲットホストを示す別のメカニズムが使用されない限り、Server Name Indication (SNI; [RFC6066])のTLS拡張を送信しなければなりません(MUST)。

QUICコネクションは[QUIC-TRANSPORT]に記載されている方法で確立されます。接続確立時には、TLSハンドシェイクでALPNトークン「h3」を選択することで、HTTP/3のサポートが示されます。他のアプリケーション層のプロトコルのサポートを同じハンドシェイクで提供してもよいものとします。

コアのQUICプロトコルに関する接続レベルのオプションは最初のcryptoハンドシェイクで設定されますが、HTTP/3固有の設定はSETTINGSフレームで伝えられます。QUIC接続の確立後、各エンドポイントは、それぞれのHTTP制御ストリームの最初のフレームとして、SETTINGSフレーム(セクション7.2.4)を送信しなければなりません(セクション6.2.1参照)。

3.3. 接続の再利用

HTTP/3 のコネクションは、複数のリクエストに渡って持続します。最高のパフォーマンスを得るために、クライアントは、サーバーとのコミュニケーションが必要ないと判断されるまで(例えば、ユーザーが特定のウェブページからナビゲートしたときなど)、あるいはサーバーが接続を閉じるまで、接続を閉じないことが期待されます。

サーバのエンドポイントへの接続がいったん存在すると、この接続は、複数の異なるURI権限コンポーネントを持つリクエストに再利用してもよい(MAY)。既存の接続を新しいオリジンに使用するために、クライアントは [SEMANTICS]のセクション4.3.4で説明されているプロセスを使用して、 新しいオリジンサーバーのためにサーバーが提示した証明書を検証しなければ なりません(MUST)。これは、クライアントがサーバの証明書と、その証明書を検証するために必要な追加情報を保持する必要があることを意味している。

そうしないクライアントは、追加のオリジンに対して接続を再利用することができません。何らかの理由で新しいオリジンに関して証明書が受け入れられない場合、接続を再利用してはならず、新しいオリジンに対して新しい接続を確立すべきです(MUST NOT)。証明書が検証できない理由が、すでに接続に関連付けられている他のオリジンにも当てはまる可能性がある場合、クライアントはそれらのオリジンに対してサーバの証明書を再検証するべきです(SHOULD)。例えば、証明書の有効期限が切れていたり、取り消されていたりして、証明書の検証に失敗した場合、その証明書を使用して権限を確立していた他のすべてのオリジンを無効にするために使用される可能性があります。

クライアントは、与えられたIPアドレスとUDPポートに対して、複数のHTTP/3接続を開くべきではありません。IPアドレスとポートは、URI、選択された代替サービス([ALTSVC])、設定されたプロキシ、またはこれらのいずれかの名前解決から得られるかもしれません。クライアントは、同一のIPアドレスとUDPポートに対して、異なるトランスポートまたはTLSの設定を用いて複数のHTTP/3接続を開いてもよい(MAY)が、同じ設定で複数の接続を作成することは避けるべきである(SHOULD)。

サーバーは、できるだけ長くオープンなHTTP/3接続を維持することが推奨されますが、必要に応じてアイドル状態の接続を終了することも認められます。どちらかのエンドポイントが HTTP/3 接続の終了を選択した場合、終了するエンドポイントは最初に GOAWAY フレーム (5.2節) を送信するべきであり、これにより両方のエンドポイントは以前に送信されたフレームが処理されたかどうかを確実に判断し、必要な残存タスクを優雅に完了または終了することができます。

クライアントが特定のオリジンのためにHTTP/3コネクションを再利用することを望まないサーバーは、リクエストに応答して421 (Misdirected Request) ステータスコードを送信することで、リクエストに対して権威を持たないことを示すことができます([SEMANTICS]のセクション7.4を参照)。

voluntasvoluntas

4. HTTP リクエストのライフサイクル

4.1. HTTPメッセージの交換

クライアントは、クライアント主導の双方向QUICストリームであるリクエストストリーム上でHTTPリクエストを送信します。クライアントは、1つのストリームに1つのリクエストのみを送信しなければなりません(MUST)。サーバーは、リクエストと同じストリーム上で、0個以上の暫定的なHTTPレスポンスを送信し、その後、以下に詳述するように、1個の最終的なHTTPレスポンスを送信します。中間および最終のHTTPレスポンスについては、[SEMANTICS]のセクション15を参照してください。

プッシュされたレスポンスは、サーバー主導の一方向性QUICストリームで送信されます(セクション6.2.2参照)。サーバーは、標準的なレスポンスと同じ方法で、0個以上の中間的なHTTPレスポンスと、それに続く1個の最終的なHTTPレスポンスを送信します。プッシュについては、セクション4.4で詳しく説明しています。

あるストリームにおいて、複数のリクエストの受信や、最終的なHTTPレスポンスに続く追加のHTTPレスポンスの受信は、不正なものとして扱われなければなりません(セクション4.1.3)。

HTTP メッセージ(リクエストまたはレスポンス)は以下のように構成されます。

  1. 単一の HEADERS フレームとして送信されるヘッダーセクション (7.2.2 節参照)。
    オプションとして、コンテンツがある場合は、一連の DATA フレーム (7.2.1 参照) として送信されます。
    必要に応じて、1つのHEADERSフレームとして送信されるトレイラーセクション(存在する場合)。

ヘッダー部とトレイラー部は、[SEMANTICS]の6.3節と6.5節に記載されており、コンテンツは[SEMANTICS]の6.4節に記載されています。

無効なフレーム列の受信は、H3_FRAME_UNEXPECTED タイプの接続エラーとして扱われなければなりません (MUST)。特に、HEADERSフレームの前のDATAフレーム、または最後のHEADERSフレームの後のHEADERSまたはDATAフレームは、無効とみなされます。他のフレームタイプ、特に未知のフレームタイプは、独自のルールに従って許可されるかもしれません;セクション9を参照してください。

サーバーは、レスポンスメッセージのフレームの前、後、またはフレームとのインターリーブで、1つ以上の PUSH_PROMISE フレーム (7.2.5節) を送信してもよいものとします。これらのPUSH_PROMISE フレームはレスポンスの一部ではありません。詳細はセクション4.4を参照してください。PUSH_PROMISE フレームはプッシュストリームでは許可されていません。PUSH_PROMISE フレームを含むプッシュレスポンスは、H3_FRAME_UNEXPECTED タイプのコネクションエラーとして扱われなければなりません (セクション 8 を参照)。

PUSH_PROMISE フレームを含むプッシュされたレスポンスは、H3_FRAME_UNEXPECTED タイプのコネクションエラーとして扱われなければなりません。

HEADERSとPUSH_PROMISEフレームは、QPACKダイナミックテーブルのアップデートを参照することがあります。これらの更新はメッセージ交換に直接含まれていませんが、メッセージが消費される前に受信して処理されなければなりません。詳細については、セクション4.1.1を参照してください。

Transfer codings (See section 6.1 of [HTTP11])はHTTP/3では定義されていません。Transfer-Encodingヘッダーフィールドは使用してはいけません(MUST NOT)。

応答は、同じリクエストに対する最終応答の前に、1つ以上の中間応答(1xx; [SEMANTICS]の15.2項参照)がある場合に限り、複数のメッセージで構成してもよい(MAY)とします。中間応答は、コンテンツやトレーラセクションを含みません。

HTTPリクエスト/レスポンスの交換は、クライアントが開始した双方向のQUICストリームを完全に消費します。リクエストの送信後、クライアントは送信用のストリームを閉じなければなりません(MUST)。CONNECTメソッド(セクション4.2参照)を使用しない限り、クライアントはストリームのクローズをリクエストに対するレスポンスの受信に依存させてはなりません(MUST NOT)。最終応答を送信した後、サーバーは送信用のストリームを閉じなければならない(MUST)。この時点で、QUICストリームは完全に閉じられる。

ストリームが閉じられると、これは最終的なHTTPメッセージの終了を示します。メッセージの中にはサイズが大きいものや束縛されていないものがあるため、エンドポイントは、進行するのに十分な量のメッセージを受信したら、部分的なHTTPメッセージの処理を開始すべきです(SHOULD)。クライアントが開始したストリームが、完全なレスポンスを提供するのに十分な量のHTTPメッセージを受信せずに終了した場合、サーバーはそのレスポンスストリームをエラーコードH3_REQUEST_INCOMPLETEで中止するべきです(セクション8を参照)。

サーバーは、レスポンスが送受信されていないリクエストのどの部分にも依存していない場合、クライアントがリクエスト全体を送信する前に完全なレスポンスを送信することができます。サーバは、リクエストの残りの部分を受信する必要がない場合、リクエストストリームの読み込みを中止し、完全なレスポンスを送信して、ストリームの送信部分をきれいに閉じてもよい(MAY)。クライアントにリクエストストリームの送信停止を要求する際には、エラーコードH3_NO_ERRORを使用すべきです(SHOULD)。クライアントは、リクエストが突然終了した結果、完全なレスポンスを破棄してはいけません(MUST NOT)。ただし、クライアントは他の理由で任意にレスポンスを破棄することができます。サーバーが部分的または完全な応答を送ったが、リクエストの読み取りを中止しなかった場合、クライアントはリクエストのボディの送信を続け、ストリームを通常通り閉じるべきです(SHOULD)。

4.1.1. フィールドのフォーマットと圧縮

HTTP メッセージは、HTTP フィールドと呼ばれる一連のキーと値のペアでメタデータを伝えます。[SEMANTICS]の 6.3 節と 6.5 節を参照してください。登録されているHTTPフィールドの一覧は、https://www.iana.org/assignments/http-fields/ で管理されている "Hypertext Transfer Protocol (HTTP) Field Name Registry "を参照してください。

注:このレジストリは、[SEMANTICS]が承認されるまで存在しません。RFC編集者の方は、発行前にこの注記を削除してください。
フィールド名は、ASCII文字のサブセットを含む文字列です。HTTP のフィールド名と値のプロパティについては、[SEMANTICS]のセクション 5.1 で詳しく説明しています。HTTP/2 と同様に、フィールド名に含まれる文字は、エンコードする前に小文字に変換しなければなりません(MUST)。フィールド名に大文字を含むリクエストやレスポンスは、不正なものとして扱われなければなりません(セクション4.1.3)。

HTTP/2 と同様に、HTTP/3 はコネクション固有のフィールドを示す Connection ヘッダーフィールドを使用しません。このプロトコルでは、コネクション固有のメタデータは他の手段で伝えられます。エンドポイントは、接続固有のフィールドを含む HTTP/3 のフィールドセクションを生成してはなりません (MUST NOT)。接続固有のフィールドを含むメッセージは、不正なものとして扱われなければなりません (セクション 4.1.3)。

唯一の例外はTEヘッダーフィールドで、これはHTTP/3リクエストヘッダーに存在しても構いません(MAY)。存在する場合は、「trailers」以外の値を含んではなりません(MUST NOT)。

HTTP/1.xメッセージをHTTP/3に変換する仲介者は、[SEMANTICS]のセクション7.6.1で議論されているように、コネクション固有のヘッダーフィールドを削除しなければなりません(MUST)。さもなければ、彼らのメッセージは他のHTTP/3エンドポイントによって不正なものとして扱われます(セクション4.1.3)。

4.1.1.1. 疑似ヘッダーフィールド

HTTP/2 と同様に、HTTP/3 は、フィールド名が ':' 文字 (ASCII 0x3a) で始まる一連の疑似ヘッダーフィールドを採用しています。これらの疑似ヘッダーフィールドは、ターゲットURI、リクエストのメソッド、レスポンスのステータスコードを伝えます。

疑似ヘッダフィールドは、HTTPフィールドではありません。エンドポイントは、このドキュメントで定義されているもの以外の擬似ヘッダーフィールドを生成してはなりません(MUST NOT)。ただし、エクステンションはこの制限の修正をネゴシエートすることができます(セクション9参照)。

擬似ヘッダーフィールドは、それが定義されている文脈においてのみ有効である。リクエスト用に定義された疑似ヘッダーフィールドは、レスポン スに現れてはならない(MUST NOT)。レスポンス用に定義された疑似ヘッ ダーフィールドは、リクエストに現れてはならない(MUST NOT)。疑似ヘッダーフィールドはトレーラーセクションに現れてはならない(MUST NOT)。エンドポイントは、未定義または無効な疑似ヘッダーフィールドを含むリクエストまたはレスポンスを不正なものとして扱わなければならない(セクション4.1.3)。

すべての疑似ヘッダーフィールドは、通常のヘッダーフィールドの前にヘッダーセクションに現れなければなりません(MUST)。レギュラーヘッダーフィールドの後にヘッダーセクションに現れる疑似ヘッダーフィールドを含むリクエストまたはレスポンスは、不正なものとして扱われなければなりません(セクション4.1.3)。

リクエストでは、以下の疑似ヘッダーフィールドが定義されています。

":method":
HTTPメソッドを含みます([SEMANTICS]のセクション9)。

":scheme":
対象となるURIのスキーム部分を含む([URI]の3.1項)。

":scheme "は、スキームが "http "と "https "のURIに限定されない。プロキシやゲートウェイは、非HTTPスキームのリクエストを翻訳し、HTTPを使用して非HTTPサービスとのやり取りを可能にします。

https」以外のスキームを使用する際のガイダンスについては、セクション3.1.2を参照してください。

"「:authority」。
対象となるURIのオーソリティ部分を含みます([URI]のセクション3.2)。権威は、スキームが「http」または「https」のURIに対して、非推奨の「userinfo」サブコンポーネントを含んではならない(MUST NOT)。

HTTP/1.1リクエストの行が正確に再現できることを保証するために、オリジンまたはアスタリスク形式のリクエストターゲットを持つHTTP/1.1リクエストから翻訳する際には、この擬似ヘッダーフィールドを省略しなければなりません(MUST)。HTTP/3リクエストを直接生成するクライアントは、Hostフィールドの代わりに「:authority」疑似ヘッダフィールドを使用すべきです(SHOULD)。HTTP/3 リクエストを HTTP/1.1 に変換する仲介者は、Host フィールドがリクエストに存在しない場合、":authority" 疑似ヘッダーフィールドの値をコピーして Host フィールドを作成しなければなりません (MUST)。

":path":
対象となるURIのパスおよびクエリ部分を含みます(「path-absolute」プロダクション、およびオプションとして「? アスタリスク形式のリクエストは、「:path」擬似ヘッダーフィールドに「*」という値を含みます。

この疑似ヘッダーフィールドは、「http」または「https」のURIでは空であってはならない(MUST NOT)。パスコンポーネントを含まない「http」または「https」のURIは、「/」の値を含まなければならない(MUST)。この規則の例外は、パスコンポーネントを含まない「http」または「https」URIに対するOPTIONSリクエストである。これらは、値が「*」の「:path」擬似ヘッダーフィールドを含まなければならない([SEMANTICS]のセクション7.1参照)。

すべての HTTP/3 リクエストは、CONNECT リクエストでない限り、":method"、":scheme"、および ":path" 疑似ヘッダフィールドに正確に一つの値を含まなければなりません (MUST); セクション 4.2 参照。

擬似ヘッダーフィールド「:scheme」が、必須の権威コンポーネント(「http」と「https」を含む)を持つスキームを特定する場合、リクエストは「:authority」擬似ヘッダーフィールドまたは「Host」ヘッダーフィールドのいずれかを含まなければならない(MUST)。これらのフィールドが存在する場合、それらは空であってはなりません(MUST NOT)。両方のフィールドが存在する場合、それらは同じ値を含まなければなりません(MUST)。スキームが必須のオーソリティコンポーネントを持たず、リクエストターゲットに何も提供されていない場合、リクエストは ":authority" 擬似ヘッダーフィールドまたは "Host" ヘッダーフィールドを含んではなりません (MUST NOT)。

必須の疑似ヘッダーフィールドを省略したり、それらの疑似ヘッダーフィールドに無効な値を含むHTTPリクエストは、不正な形式です(セクション4.1.3)。

HTTP/3 は、HTTP/1.1 リクエストラインに含まれるバージョン識別子を運ぶ方法を定義していません。

レスポンスについては、HTTPステータスコードを伝える単一の":status "擬似ヘッダーフィールドが定義されています;[SEMANTICS]のセクション15を参照してください。この疑似ヘッダフィールドは、すべての応答に含まれなければなりません(MUST)。そうでなければ、応答は不正なものとなります(セクション4.1.3)。

HTTP/3は、HTTP/1.1のステータスラインに含まれるバージョンや理由のフレーズを伝える方法を定義していません。

4.1.1.2. フィールド圧縮

QPACK]では、HPACKのバリエーションとして、圧縮によるヘッドオブライン・ブロックの量をエンコーダが制御できるようにすることを説明しています。これにより、エンコーダーは圧縮効率と待ち時間のバランスを取ることができます。HTTP/3 は QPACK を使用して、ヘッダセクションに存在する疑似ヘッダフィールドを含む、ヘッダとトレーラセクションを圧縮します。

より良い圧縮効率を可能にするために、「クッキー」フィールド([RFC6265])は、圧縮前に、それぞれが1つ以上のクッキーペアを持つ別々のフィールドラインに分割してもよいものとします。解凍されたフィールドセクションが複数のクッキーフィールドラインを含む場合は、HTTP/1.1 接続や一般的な HTTP サーバーアプリケーションなど、HTTP/2 や HTTP/3 以外のコンテキストに渡される前に、0x3b, 0x20 の 2 バイト区切りの文字列 (ASCII 文字列 "; ") を使って、これらを 1 バイトの文字列に連結しなければなりません (MUST)。

4.1.1.3. ヘッダーサイズの制約

HTTP/3 の実装は、個々の HTTP メッセージで受け付けるメッセージヘッダの最大サイズに制限を課してもよいものとします (MAY)。扱うことができるよりも大きなヘッダーセクションを受け取るサーバーは、HTTP 431 (Request Header Fields Too Large) ステータスコード ([RFC6585])を送ることができます。クライアントは、処理できないレスポンスを破棄することができます。フィールドリストのサイズは、名前と値の長さをバイトで表したフィールドの圧縮されていないサイズに、各フィールドの32バイトのオーバーヘッドを加えたものに基づいて計算されます。

実装がこの制限を相手に通知したい場合は、SETTINGS_MAX_FIELD_SECTION_SIZEパラメータでバイト数として伝えることができます。このパラメータを受け取った実装は、指示されたサイズを超えるHTTPメッセージヘッダを送信すべきではありません(相手が処理を拒否する可能性が高いため)。しかし,HTTPメッセージは,オリジンサーバに到達するまでに1つ以上の中間体を経由することができます([SEMANTICS]の3.7節参照)。この制限は、メッセージを処理する各実装によって個別に適用されるため、この制限以下のメッセージが受け入れられることは保証されません。

4.1.2. リクエストのキャンセルと拒否

リクエストストリームがオープンされると、どちらのエンドポイントでもリクエストをキャンセルしてもよいものとします(MAY)。クライアントは、応答に興味がなくなった場合にリクエストをキャンセルします。サーバーは、応答できないか、応答しないことを選択した場合にリクエストをキャンセルします。可能であれば、サーバーはすでに処理を開始しているリクエストをキャンセルするのではなく、適切なステータスコードを持つHTTPレスポンスを送信することが推奨されます(RECOMMENDED)。

実装は、まだ開いているストリームのすべての方向を突然終了させることで、リクエストをキャンセルするべきです(SHOULD)。これは、ストリームの送信部分をリセットし、ストリームの受信部分の読み取りを中止することを意味します。[QUIC-TRANSPORT]のセクション2.4を参照してください。

サーバーがアプリケーション処理を行わずにリクエストをキャンセルした場合、そのリクエストは "拒否された "とみなされる。サーバーは、エラーコードH3_REQUEST_REJECTEDで応答ストリームを中止するべきである(SHOULD)。この文脈では、「処理された」とは、ストリームからの何らかのデータが、結果として何らかのアクションを取るかもしれないソフトウェアのある上位層に渡されたことを意味します。クライアントは、サーバーによって拒否されたリクエストを、あたかも何も送られなかったかのように扱うことができ、それによって後に再試行することができます。

サーバーは、一部または全部が処理されたリクエストに対して、H3_REQUEST_REJECTEDエラーコードを使用してはなりません(MUST NOT)。サーバーが部分的な処理の後に応答を放棄するとき、サーバーはエラーコードH3_REQUEST_CANCELLEDでその応答ストリームを中止するべきです(SHOULD)。

クライアントは、エラーコードH3_REQUEST_CANCELLEDを使ってリクエストをキャンセルするべきです。このエラーコードを受け取ったサーバーは、処理が行われなかった場合、エラーコードH3_REQUEST_REJECTEDを使って突然応答を終了してもよい(MAY)。クライアントは、サーバがこのエラーコードでリクエストストリームの終了を要求した場合を除き、H3_REQUEST_REJECTEDエラーコードを使用してはなりません(MUST NOT)。

完全なレスポンスを受信した後にストリームがキャンセルされた場合、クライアントはキャンセルを無視してレスポンスを使用してもよいものとします。しかし、部分的なレスポンスを受信した後にストリームがキャンセルされた場合、そのレスポンスは使用すべきではありません(SHOULD NOT)。GET、PUT、DELETEなどのidempotentアクションのみが安全に再試行できます。クライアントは、リクエストのセマンティクスがメソッドに依存しないidempotentであることを知るための何らかの手段、またはオリジナルのリクエストが適用されなかったことを検出するための何らかの手段を持っていない限り、idempotentではないメソッドを使用したリクエストを自動的に再試行するべきではありません。詳細は[SEMANTICS]の9.2.2項を参照してください。

4.1.3. 不正なリクエストとレスポンス

不正なリクエストやレスポンスとは、他の方法では有効な一連のフレームですが、以下の理由で無効となるものです。

禁止されているフィールドや疑似ヘッダーフィールドの存在
必須の疑似ヘッダー・フィールドがない場合
疑似ヘッダーフィールドの値が無効である。
フィールドの後に擬似ヘッダーフィールドがある。
HTTPメッセージの順序が無効であること。
大文字のフィールド名が含まれていたり
フィールド名や値に無効な文字が含まれている場合。
Content-Lengthヘッダーフィールド([SEMANTICS]の6.4.1項)を含むときにコンテンツを持つと定義されるリクエストまたはレスポンスは、Content-Lengthヘッダーフィールドの値が、受信したDATAフレームの長さの合計に等しくない場合、不正な形式となります。Content-Length が存在していても、コンテンツを持たないと定義されているレスポンスは、DATA フレームにコンテンツが含まれていなくても、0 ではない Content-Length フィールドを持つことができます。

HTTP リクエストまたはレスポンスを処理する仲介者 (すなわち、トンネルとして機能しないすべての仲介者) は、マルフォームのリクエストまたはレスポンスを転送してはなりません (MUST NOT)。検出された不正なリクエストまたはレスポンスは、H3_MESSAGE_ERROR タイプのストリームエラー (セクション 8) として扱われなければなりません (MUST)。

不正な形式のリクエストに対しては、サーバはストリームを閉じるかリセットする前に、エラーを示すHTTPレスポンスを送信してもよい(MAY)。クライアントは不正なレスポンスを受け入れてはいけません(MUST NOT)。これらの要件は、HTTP に対する一般的な攻撃のいくつかのタイプから保護することを目的としていることに注意してください。寛容にすると、実装がこれらの脆弱性にさらされる可能性があるため、意図的に厳しくしています。

4.2. CONNECTメソッド

CONNECT メソッドは、受信者が request-target で指定された宛先オリジンサーバーへのトンネルを確立するよう要求します。CONNECTメソッドは、"https "リソースを操作するためにオリジンサーバーとのTLSセッションを確立するために、主にHTTPプロキシで使用されます。

HTTP/1.x では、CONNECT は HTTP 接続全体をリモートホストへのトンネルに変換するために使用されます。HTTP/2 と HTTP/3 では、CONNECT メソッドは単一のストリーム上でトンネルを確立するために使用されます。

CONNECTリクエストは以下のように構成されなければなりません(MUST)。

疑似ヘッダーフィールドの ":method" は "CONNECT" に設定されます。
スキーム "および "パス "疑似ヘッダーフィールドは省略されます。
疑似ヘッダ・フィールド「:authority」には、接続先のホストとポートが含まれます(CONNECTリクエストのrequest-targetのauthority形式と同等です。
リクエスト・ストリームは、転送されるデータを運ぶために、リクエストの最後に開いたままになります。これらの制限に従わないCONNECTリクエストはマルフォームである; セクション4.1.3参照。

CONNECTをサポートするプロキシは、「:authority」疑似ヘッダーフィー ルドで識別されるサーバーへのTCP接続([RFC0793])を確立する。この接続が正常に確立されると、プロキシは[SEMANTICS]の15.3節で定義されているように、2xxシリーズのステータスコードを含むHEADERSフレームをクライアントに送信します。

ストリーム上のすべてのDATAフレームは、TCP接続で送受信されるデータに対応します。クライアントから送信されたDATAフレームのペイロードは、プロキシによってTCPサーバに送信され、TCPサーバから受信したデータは、プロキシによってDATAフレームにパッケージ化されます。TCPサーバから受信したデータは、プロキシによってDATAフレームにまとめられます。なお、TCPセグメントのサイズと数は、HTTP DATAフレームやQUIC STREAMフレームのサイズと数に予測可能に対応することは保証されていません。

CONNECTメソッドが完了すると、DATAフレームのみがストリーム上で送信されることが許可されます。拡張フレームは、拡張機能の定義で特に許可されている場合に使用してもよいものとします。他の既知のフレームタイプの受信は、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱われなければなりません(セクション8を参照)。

このTCPコネクションは、どちらのピアからでも閉じることができます。クライアントが要求ストリームを終了する(すなわち、プロキ シでの受信ストリームが「Data Recvd」状態になる)と、プロキ シは、TCPサーバへの接続にFINビットを設定する。プロキシは、FINビットが設定されたパケットを受信すると、クライアントに送信する送信ストリームをクローズします。一方向に半クローズされたままのTCPコネクションは無効ではありませんが、サーバーでは不適切に扱われることが多いので、クライアントは、CONNECTのターゲットからデータを受け取ることをまだ期待している間は、送信用ストリームをクローズすべきではありません。

TCP接続エラーは、ストリームを突然終了させることで通知されます。プロキシは、RSTビットが設定されたTCPセグメントの受信を含む、TCP接続のいかなるエラーも、H3_CONNECT_ERROR型のストリームエラーとして扱う(セクション8参照)。これに対応して、プロキシがストリームまたはQUIC接続のエ ラーを検出した場合、プロキシはTCP接続を閉じなければならない [MUST]。基礎となるTCP実装が許可している場合、プロキシはRSTビットをセットしたTCPセグメントを送信するべきである(SHOULD)。

CONNECTは任意のサーバーへのトンネルを生成するので、CONNECTを サポートするプロキシはその使用を一連の既知のポートまたは安全なリクエス トターゲットのリストに制限するべきである[SHOULD]。

4.3. HTTPアップグレード

HTTP/3は、HTTPアップグレードメカニズム(SEMANTICS]の7.8項)や101(Switching Protocols)情報ステータスコード(SEMANTICS]の15.2.2項)をサポートしていません。

4.4. サーバープッシュ

サーバープッシュは、クライアントが指示された要求を行うことを期待して、サーバーが要求-応答のやり取りをクライアントにプッシュすることを可能にする対話モードです。これにより、ネットワークの使用量と潜在的な遅延の増加が相殺されます。HTTP/3 のサーバープッシュは、[HTTP2]のセクション 8.2 で説明されているものと似ていますが、異なるメカニズムを使用しています。

各サーバープッシュには、サーバーから一意のプッシュIDが割り当てられます。プッシュ ID は、HTTP/3 接続の存続期間中、様々なコンテキストでプッシュを参照するために使用されます。

プッシュIDの空間はゼロから始まり、MAX_PUSH_IDフレームで設定された最大値で終わります;7.2.7項参照。特に、サーバーはクライアントがMAX_PUSH_IDフレームを送信した後でなければ、プッシュすることができません。クライアントはMAX_PUSH_IDフレームを送信して、サーバーが約束できるプッシュの数を制御します。サーバーはPush IDを0から順に使用すべきです(SHOULD)。MAX_PUSH_IDフレームが送信されていない場合や、ストリームが最大Push IDよりも大きいPush IDを参照している場合、クライアントはプッシュストリームの受信をH3_ID_ERROR (セクション8)型の接続エラーとして扱わなければなりません (MUST)。

Push ID は、リクエストメッセージのヘッダーセクションを運ぶ 1 つ以上の PUSH_PROMISE フレーム (7.2.5 節) で使用されます。これらのフレームは、プッシュを生成したリクエストストリーム上で送信されます。これにより、サーバーのプッシュをクライアントのリクエストと関連付けることができます。同じプッシュIDが複数のリクエストストリームで約束されている場合、解凍されたリクエストフィールドセクションには、同じフィールドが同じ順番で含まれていなければならず(MUST)、各フィールドの名前と値の両方が同一でなければなりません(MUST)。

このプッシュIDは、最終的にそれらの約束を果たすプッシュストリームに含まれます。プッシュストリームは、実行する約束のPush IDを識別し、セクション4.1で説明したように、約束されたリクエストに対するレスポンスを含みます。

最後に、プッシュIDはCANCEL_PUSHフレームで使用することができます(7.2.3項参照)。クライアントはこのフレームを使用して、約束されたリソースの受信を希望しないことを示します。サーバーはこのフレームを使用して、以前の約束を果たさないことを示します。

すべてのリクエストをプッシュできるわけではありません。サーバーは以下のプロパティを持つリクエストをプッシュしてもよいものとします。

  • cacheable; [SEMANTICS]の9.2.3項参照。
  • safe; [SEMANTICS]のセクション9.2.1を参照。
  • リクエストボディやトレイラーセクションを含まない

サーバーは、「:authority」疑似ヘッダーフィールドに、サーバーが権威を持つ値を含めなければなりません(MUST)。プッシュされたリクエストが示すオリジンについて、クライアントがまだコネクションを検証していない場合、クライアントは、コネクション上でそのオリジンに対するリクエストを送信する前に行うのと同じ検証プロセスを実行しなければなりません(セクション3.3参照)。この検証が失敗した場合、クライアントはサーバーがそのオリジンに 対して権威があるとみなしてはならない(MUST NOT)。

クライアントは、キャッシュ不可能なリクエスト、安全性が確認できないリクエスト、リクエストボディの存在を示すリクエスト、またはサーバーの権限を考慮していないリクエストを運ぶPUSH_PROMISEフレームを受信すると、CANCEL_PUSHフレームを送信するべきです。対応するすべてのレスポンスは、使用したりキャッシュしたりしてはいけません (MUST NOT)。

プッシュされた各レスポンスは、1つまたは複数のクライアントのリクエストに関連付けられています。プッシュは、PUSH_PROMISE フレームを受信したリクエストストリームに関連付けられます。同じサーバーのプッシュは、複数のリクエストストリームで同じPUSH IDを持つPUSH_PROMISEフレームを使用して、追加のクライアントリクエストと関連付けることができます。これらの関連付けはプロトコルの動作には影響しませんが、ユーザーエージェントがプッシュされたリソースをどのように使用するかを決定する際に考慮してもよいものとします(MAY)。

レスポンスの特定の部分に関連するPUSH_PROMISEフレームの順序は重要です。サーバーは、約束されたレスポンスを参照する HEADERS または DATA フレームを送信する前に PUSH_PROMISE フレームを送信するべきです (SHOULD)。これにより、クライアントがサーバーによってプッシュされるリソースを要求する可能性を減らすことができます。

並び替えにより、プッシュストリームのデータが対応するPUSH_PROMISEフレームよりも先に到着することがあります。クライアントが、まだ知られていないプッシュIDを持つ新しいプッシュストリームを受信すると、関連するクライアントリクエストとプッシュされたリクエストの両方のヘッダーフィールドが知られていません。クライアントは、一致するPUSH_PROMISEを期待して、ストリームデータをバッファリングすることができます。クライアントは、ストリームフローコントロール([QUIC-TRANSPORT]のセクション4.1参照)を使用して、サーバーがプッシュストリームにコミットできるデータ量を制限することができます。

プッシュストリームのデータは、クライアントがプッシュをキャンセルした後に到着することもあります。この場合、クライアントは、H3_REQUEST_CANCELLEDのエラーコードでストリームの読み取りを中止することができます。これは、追加のデータを転送しないようにサーバーに要求し、受信時に破棄することを示しています。

キャッシュ可能なプッシュレスポンス([CACHING]のセクション3を参照)は、クライアントがHTTPキャッシュを実装している場合には、クライアントが保存することができます。プッシュされたレスポンスは、その受信時にオリジンサーバー上で正常に検証されたものとみなされます(例えば、[CACHING]の5.2.2.3項にある "no-cache "キャッシュレスポンス指示が存在する場合)。

キャッシュできないプッシュされたレスポンスは、どの HTTP キャッシュにも保存してはいけません (MUST NOT)。アプリケーションが別途利用できるようにしてもかまいません。

voluntasvoluntas

5. 接続の終了

一度確立されたHTTP/3接続は、接続が閉じられるまで、多くのリクエストとレスポンスに使用することができます。接続の終了は、いくつかの異なる方法で起こります。

5.1. アイドル接続

QUICの各エンドポイントは、ハンドシェイク時にアイドルタイムアウトを宣言します。QUICの各エンドポイントは、ハンドシェーク中にアイドルタイムアウトを宣言しており、この時間を超えてQUICコネクションがアイドル状態(パケットを受信しない状態)になると、相手はコネクションが閉じられたと判断します。HTTP/3の実装は、既存の接続がQUICハンドシェイク中にネゴシエートされたアイドルタイムアウトよりも長くアイドル状態であった場合、新しいリクエストのために新しいHTTP/3接続を開く必要があり、アイドルタイムアウトに近づいている場合はそうすべきです([QUIC-TRANSPORT]のセクション10.1を参照)。

HTTPクライアントは、[QUIC-TRANSPORT]のセクション10.1.2に記載されているように、リクエストやサーバープッシュに対して未処理のレスポンスがある間、トランスポートが接続を維持することを要求することが期待されます。クライアントがサーバーからの応答を期待していない場合、アイド ルなコネクションをタイムアウトさせる方が、必要とされないかもしれないコネク ションを維持するために労力を費やすよりも好ましい。ゲートウェイは、サーバへの接続確立のためのレイテンシーコストを発生させるよりも、必要性を予測して接続を維持してもよい。サーバーは積極的に接続を維持すべきではありません。

5.2. コネクションのシャットダウン

5.2.1 接続の終了 接続がアイドル状態でない場合でも、いずれかのエンドポイントが接続の使用を停止し、グレースフルな接続の終了を開始することができます。エンドポイントは GOAWAY フレーム (7.2.6節) を送信することで、HTTP/3 コネクションのグレースフルシャットダウンを開始します。GOAWAY フレームは、このコネクションで処理された、または処理される可能性のあるリクエストまたはプッシュの範囲を受信者に示す識別子を含んでいます。サーバーはクライアント主導の双方向ストリームIDを送信し、クライアントはプッシュIDを送信します(4.4項)。指示された識別子以上のリクエストやプッシュは、GOAWAYの送信者によって拒否されます(セクション4.1.2)。この識別子は、リクエストやプッシュが処理されなかった場合には、ゼロにしてもよい(MAY)。

GOAWAY フレームの情報により、クライアントとサーバーは、HTTP/3 接続のシャットダウン前に、どのリクエストまたはプッシュが受け入れられたかについて合意することができます。GOAWAY フレームを送信すると、エンドポイントは影響を受けるストリームのトランスポートステートをクリーンアップするために、示された識別子以上の識別子を持つリクエストまたはプッシュを明示的にキャンセルするべきです (4.1.2項および7.2.3項を参照)。エンドポイントは、より多くのリクエストやプッシュが到着すると、そうし続けるべきです(SHOULD)。

エンドポイントは、ピアから GOAWAY フレームを受信した後の接続で、新しいリクエストを開始したり、新しいプッシュを約束してはいけません (MUST NOT)。クライアントは追加のリクエストを送信するために新しいコネクションを確立してもかまいません。

リクエストやプッシュの中には、すでに転送中のものもあります。

  • GOAWAYフレームの受信時に、クライアントがGOAWAYフレームに含まれる識別子以上のストリームIDを持つリクエストを既に送信していた場合、それらのリクエストは処理されません。クライアントは、処理されなかったリクエストを別のHTTPコネクションで安全に再試行することができます。リクエストを再試行できないクライアントは、サーバーが接続を閉じたときに、飛行中のすべてのリクエストを失います。

    サーバーからの GOAWAY フレームのストリーム ID よりも小さいストリーム ID のリクエストは、処理された可能性があります。そのステータスは、レスポンスを受信するか、ストリームが個別にリセットされるか、問題のリクエストのストリーム ID よりも小さいストリーム ID で別の GOAWAY を受信するか、接続が終了するまで知ることができません。

    サーバーは、指示されたID以下のストリームに対する個々のリクエストが処理されなかった場合、これを拒否してもよいものとします(MAY)。

  • サーバーが、GOAWAY フレームに含まれる識別子以上の Push ID を持つプッシュを約束した後に GOAWAY フレームを受信した場合、それらのプッシュは受け入れられません。
    サーバーは、リモートピアがリクエストが部分的に処理されたかどうかを知ることができるように、たとえ事前の通知が小さくても、接続の終了が事前に知られている場合には GOAWAY フレームを送信するべきです (SHOULD)。例えば、サーバーが QUIC 接続を閉じるのと同時に HTTP クライアントが POST を送信した場合、サーバーがどのストリームに作用したかを示す GOAWAY フレームを送信しなければ、クライアントはサーバーが POST リクエストの処理を開始したかどうかを知ることができません。

エンドポイントは、異なる識別子を示す複数の GOAWAY フレームを送信してもよいものとしますが、クライアントが別の HTTP 接続で未処理のリクエストを既に再試行している可能性があるため、各フレームの識別子は前のフレームの識別子よりも大きくしてはなりません (MUST NOT)。以前に受信したものよりも大きな識別子を含むGOAWAYを受信した場合、H3_ID_ERROR型のコネクションエラーとして扱わなければなりません(MUST)。

優雅に接続を終了しようとするエンドポイントは、可能な最大値 (サーバーでは 262-4、クライアントでは 262-1) に設定された GOAWAY フレームを送信できます。これにより、相手側が新しいリクエストやプッシュの作成を停止することができます。飛行中のリクエストやプッシュが到着するまでの時間を置いた後、エンドポイントは、接続が終了するまでに受け入れる可能性のあるリクエストやプッシュを示す別のGOAWAYフレームを送信できます。これにより、リクエストを失うことなく、きれいにコネクションを終了することができます。

クライアントは、送信するGOAWAYの中でプッシュIDに選択する値に、より柔軟性があります。262-1の値は、サーバーが既に約束されたプッシュを継続して実行できることを示します。より小さい値は、クライアントがこの値以上のプッシュIDを持つプッシュを拒否することを示します。サーバーと同様に、クライアントは、指定されたPush IDが以前に送信されたどの値よりも大きくない限り、後続のGOAWAYフレームを送信してもよい(MAY)。

GOAWAYが指定されたリクエストやプッシュが受信時に処理されない、または受け入れられないことを示している場合でも、基礎となるトランスポートリソースはまだ存在しています。これらのリクエストを開始したエンドポイントは、トランスポートの状態をクリーンアップするためにリクエストをキャンセルすることができます。

受け入れられたすべてのリクエストとプッシュが処理されると、エンドポイントは接続がアイドル状態になるのを許可するか、または接続の即時閉鎖を開始してもよい(MAY)。優雅なシャットダウンを行ったエンドポイントは、接続を閉じる際にH3_NO_ERRORエラーコードを使用すべきです(SHOULD)。

クライアントが利用可能なすべての双方向性ストリームIDをリクエストで消費した場合、クライアントはそれ以上のリクエストを行うことができないため、サーバーはGOAWAYフレームを送信する必要はありません。

5.3. アプリケーションの即時終了

HTTP/3の実装では、いつでもQUIC接続を直ちに閉じることができます。これは、アプリケーション層が接続を終了したことを示すQUIC CONNECTION_CLOSEフレームをピアに送信することになります。このフレーム内のアプリケーションエラーコードは、接続が閉じられる理由をピアに示します。HTTP/3で接続を閉じる際に使用できるエラーコードについては、セクション8を参照してください。

接続を閉じる前に、クライアントがいくつかのリクエストを再試行できるように、GOAWAY フレームを送信してもよいものとします。GOAWAYフレームをQUIC CONNECTION_CLOSEフレームと同じパケットに含めることで、フレームがクライアントに受信される可能性が高くなります。

明示的に閉じられていないオープンストリームがある場合は、接続が閉じられる際に暗黙的に閉じられます。

5.4. トランスポートのクローズ

様々な理由から、QUICトランスポートはアプリケーション層に接続の終了を示すことがあります。これは、ピアによる明示的なクローズ、トランスポートレベルのエラー、または接続を中断するネットワークトポロジーの変化が原因かもしれない。

GOAWAYフレームを送信せずにコネクションが終了した場合、クライアントは、送信されたリクエストの全部または一部が処理された可能性があると想定しなければなりません(MUST)。

voluntasvoluntas

6. ストリームのマッピングと使用方法

QUICのストリームは、信頼性の高いバイトのインオーダー配信を行いますが、他のストリーム上のバイトに関する配信順序については保証しません。QUICのバージョン1では、HTTPフレームを含むストリームデータはQUIC STREAMフレームによって運ばれますが、このフレーミングはHTTPフレーミング層からは見えません。トランスポート層は受信したストリームデータをバッファリングしてオーダーし、アプリケーションに信頼性の高いバイトストリームを提供します。QUICではストリーム内でのアウトオブオーダー配信が可能ですが、HTTP/3ではこの機能を利用していません。

QUICのストリームは、データを開始者から受信者にのみ伝送する一方向性と、双方向性があります。ストリームは、クライアントまたはサーバーのいずれかによって開始することができます。QUICストリームの詳細については、[QUIC-TRANSPORT]のセクション2を参照してください。

HTTPのフィールドとデータがQUIC上で送信される場合、QUICレイヤはストリーム管理のほとんどを処理します。QUICストリーム上で送信されたデータは、常に特定のHTTPトランザクションまたはHTTP/3接続コンテキスト全体にマッピングされます。

6.1. 双方向ストリーム

すべてのクライアント主導の双方向ストリームは、HTTPリクエストとレスポンスに使用されます。双方向ストリームは、レスポンスがリクエストと容易に関連づけられることを保証します。これらのストリームは、リクエストストリームと呼ばれています。

つまり、クライアントの最初のリクエストはQUICストリーム0で発生し、それ以降のリクエストはストリーム4、8などで発生することになる。これらのストリームのオープンを許可するために、HTTP/3サーバーは、許可されたストリームの数と最初のストリームフロー制御ウィンドウにゼロではない最小値を設定すべきです(SHOULD)。不必要に並列性を制限しないように、一度に少なくとも100のリクエストストリームが許可されるべきです(SHOULD)。

HTTP/3 は、拡張機能でこれらのストリームの用途を定義することができますが、サーバーが開始する双方向ストリームを使用しません。クライアントは、そのような拡張がネゴシエートされていない限り、サーバー主導の双方向ストリームの受信を、H3_STREAM_CREATION_ERROR (セクション8)型のコネクションエラーとして扱わなければなりません(MUST)。

6.2. 一方向性ストリーム

一方向ストリームは、どちらの方向にも使用でき、さまざまな目的で使用されます。6.2.1.1 一方向ストリーム 一方向ストリームは、さまざまな目的で使用されます。目的はストリームタイプで示され、ストリームの開始時に可変長の整数として送信されます。この整数に続くデータのフォーマットと構造は、ストリームタイプによって決定されます。

Unidirectional Stream Header {
  Stream Type (i),
}

図1:一方向性ストリームヘッダー
このドキュメントでは、コントロールストリーム(6.2.1項)とプッシュストリーム(6.2.2項)の2つのストリームタイプが定義されています。QPACK]では、さらに2つのストリームタイプが定義されています。その他のストリームタイプは、HTTP/3の拡張機能で定義できます。詳細はセクション9をご覧ください。いくつかのストリームタイプは予約されています(セクション6.2.3)。

HTTP/3 接続の寿命の初期段階におけるパフォーマンスは、一方向性ストリーム上でのデータの作成と交換に影響されます。ストリームの数やストリームのフローコントロールウィンドウを過度に制限するエンドポイントは、リモートピアが早期に限界に達してブロックされる可能性を高めます。特に、リモートピアが、使用が許可されている一方向性ストリームの一部で予約ストリーム動作(6.2.3項)を実行したいと考える可能性があることを、実装は考慮すべきです。ブロッキングを回避するために、クライアントとサーバーの両方から送信されるトランスポートパラメータは、HTTP制御ストリームに加えて、必須の拡張機能で必要とされる数の一方向ストリーム(基本のHTTP/3プロトコルとQPACKで必要とされる最小数は3)のために、少なくとも1つの一方向ストリームを作成することをピアに許可しなければならず(MUST)、各ストリームに少なくとも1024バイトのフロー制御クレジットを提供すべきである(SHOULD)としています。

エンドポイントは、重要な一方向性ストリームを作成する前にそのピアが初期クレジットをすべて消費した場合、より多くの一方向性ストリームを作成するために追加クレジットを付与する必要はないことに注意してください。エンドポイントは、HTTPコントロールストリームと、必須の拡張機能で必要とされる一方向性ストリーム(QPACKエンコーダーおよびデコーダーストリームなど)を最初に作成し、その後、ピアの許可に応じて追加のストリームを作成するべきです(SHOULD)。

ストリームヘッダーが、受信者がサポートしていないストリームタイプを示している場合、セマンティクスが不明なため、ストリームの残りの部分は消費できません。未知のストリームタイプの受信者は、H3_STREAM_CREATION_ERRORのエラーコードまたは予約済みのエラーコード(セクション8.1)でストリームの読み取りを中止してもよい(MAY)が、そのようなストリームをいかなる種類の接続エラーともみなしてはならない(MUST NOT)。

実装は、相手がサポートしているかどうかを知る前に、ストリームタイプを送信してもよい(MAY)。ただし、QPACKやその他の拡張を含む既存のプロトコルコンポーネントの状態やセマンティクスを変更する可能性があるストリームタイプは、相手がサポートしていることが判明するまで送信してはなりません(MUST NOT)。

送信者は、特に指定がない限り、一方向性ストリームをクローズまたはリセットすることができます。受信者は、一方向性ストリームヘッダーの受信前に一方向性ストリームがクローズまたはリセットされることを許容しなければならない(MUST)。

6.2.1. 制御ストリーム

制御ストリームは、ストリームタイプが 0x00 であることで示される。このストリームのデータは、7.2項で定義されているように、HTTP/3フレームで構成されています。

各サイドは、接続の開始時に単一の制御ストリームを開始し、このストリームの最初のフレームとしてSETTINGSフレームを送信しなければなりません (MUST)。制御ストリームの最初のフレームが他のフレームタイプである場合、これは H3_MISSING_SETTINGS タイプの接続エラーとして扱われなければなりません (MUST)。制御ストリームを名乗る2つ目のストリームの受信は、H3_STREAM_CREATION_ERROR型のコネクションエラーとして扱わなければなりません(MUST)。送信者は制御ストリームを閉じてはならず、受信者は送信者に制御ストリームを閉じることを要求してはなりません(MUST NOT)。いずれかの制御ストリームがいずれかの時点で閉じられた場合、これはH3_CLOSED_CRITICAL_STREAM型の接続エラーとして扱われなければなりません(MUST)。コネクション・エラーについては第8章で説明します。

制御ストリームの内容は、他のストリームの動作を管理するために使用されるため、エンドポイントは、相手の制御ストリームがブロックされないように十分なフロー制御クレジットを提供すべきです(SHOULD)。

単一の双方向ストリームではなく、一対の単方向ストリームが使用されます。これにより、どちらかのピアが可能になった時点ですぐにデータを送信することができます。QUIC接続で0-RTTが利用できるかどうかに応じて、クライアントまたはサーバのどちらかが先にストリームデータを送信できる場合があります。

6.2.2. プッシュストリーム

サーバープッシュは、HTTP/2 で導入されたオプション機能で、サーバーがリクエストの前にレスポンスを開始することができます。詳細はセクション 4.4 を参照してください。

プッシュストリームは、ストリームタイプが 0x01 であることを示し、その後に、果たすべき約束のプッシュ ID が可変長整数でエンコードされています。このストリームの残りのデータは、セクション7.2で定義されているように、HTTP/3フレームで構成されており、セクション4.1で定義されているように、0個以上の中間HTTPレスポンスとそれに続く1個の最終HTTPレスポンスによって、約束されたサーバープッシュを果たします。サーバープッシュとプッシュIDについては、4.4節で説明します。

サーバーだけがプッシュできます。もしサーバーがクライアントからのプッシュストリームを受信した場合は、H3_STREAM_CREATION_ERROR型のコネクションエラーとして扱わなければなりません(セクション8参照)。

Push Stream Header {
  Stream Type (i) = 0x01,
  Push ID (i),
}

図2: プッシュストリームヘッダー
各プッシュIDは、1つのプッシュストリームヘッダー内で一度だけ使用されなければなりません(MUST)。プッシュストリームヘッダーに、他のプッシュストリームヘッダーで使用されたプッシュIDが含まれていることをクライアントが検出した場合、クライアントはこれをH3_ID_ERROR型の接続エラーとして扱わなければなりません(セクション8参照)。

6.2.3. 予約済みストリームタイプ

0x1f * N + 0x21 (非負の整数) のストリームタイプは、未知のタイプを無視するという要件を満たすために予約されています。これらのストリームはセマンティクスを持たず、アプリケーション層のパディングが必要な場合に送信されます。また、現在データが転送されていない接続で送信してもよい(MAY)。エンドポイントは、これらのストリームが受信時に何らかの意味を持つと考えてはいけません(MUST NOT)。

ストリームのペイロードと長さは、送信側の実装が選択する任意の方法で選択されます。予約されたストリームタイプを送信する場合、実装はストリームをきれいに終了させるか、リセットしてもかまいません(MAY)。ストリームをリセットする際には、H3_NO_ERRORエラーコードまたは予約済みのエラーコード(セクション8.1)のいずれかを使用すべきです(SHOULD)。

voluntasvoluntas

7. HTTPフレーム層

HTTPフレームは、第6章で述べたように、QUICストリームで運ばれます。HTTP/3 では、コントロールストリーム、リクエストストリーム、プッシュストリームの 3 つのストリームタイプが定義されています。本節では、HTTP/3 のフレームフォーマットと、それらに許可されたストリームの種類について説明します(概要は表1を参照)。HTTP/2 と HTTP/3 のフレームの比較は、付録 A.2 に記載されています。

Frame Control Stream Request Stream Push Stream Section
DATA No Yes Yes Section 7.2.1
HEADERS No Yes Yes Section 7.2.2
CANCEL_PUSH Yes No No Section 7.2.3
SETTINGS Yes (1) No No Section 7.2.4
PUSH_PROMISE No Yes No Section 7.2.5
GOAWAY Yes No No Section 7.2.6
MAX_PUSH_ID Yes No No Section 7.2.7
Reserved Yes Yes Yes Section 7.2.8

表1: HTTP/3 フレームとストリームタイプの概要

SETTINGSフレームは、コントロール・ストリームの最初のフレームとしてのみ使用でき、表1では(1)で示されています。これは、表1に(1)で示されています。具体的なガイダンスは、関連するセクションに記載されています。

QUICフレームとは異なり、HTTP/3フレームは複数のパケットにまたがることができることに注意してください。

7.1. フレームのレイアウト

全てのフレームは以下の形式で構成されています。

HTTP/3 Frame Format {
  Type (i),
  Length (i),
  Frame Payload (..),
}

図3:HTTP/3フレームフォーマット
フレームは以下のフィールドを含みます。

タイプ。
可変長の整数で、フレームのタイプを識別します。

Length:
Frame Payloadのバイト数を表す可変長整数です。

フレームのペイロード。
ペイロードのセマンティクスはTypeフィールドによって決定されます。

各フレームのペイロードは、その説明で特定されたフィールドを正確に含まなければなりません(MUST)。識別されたフィールドの後に追加のバイトを含むフレームペイロード、または識別されたフィールドの終了前に終了するフレームペイロードは、H3_FRAME_ERRORタイプのコネクションエラーとして扱われなければなりません(セクション8参照)。特に、冗長な長さのエンコーディングは、自己矛盾がないことが検証されなければなりません(10.8項参照)。

ストリームがきれいに終了したとき、ストリームの最後のフレームが切り捨てられていた場合、これはH3_FRAME_ERROR型のコネクションエラーとして扱われなければなりません(セクション8参照)。突然終了したストリームは、フレーム内のどの時点でもリセットすることができます。

7.2. フレームの定義

7.2.1. DATA

DATA フレーム (type=0x00) は、HTTP リクエストまたはレスポンスのコンテンツに関連する任意の可変長のバイトシーケンスを伝えます。

DATA フレームは、HTTP リクエストまたはレスポンスと関連付けられなければなりません (MUST)。コントロールストリーム上で DATA フレームを受信した場合、受信者は H3_FRAME_UNEXPECTED タイプのコネクションエラーで応答しなければなりません (セクション 8 参照)。

DATA Frame {
  Type (i) = 0x00,
  Length (i),
  Data (..),
}

図4:DATAフレーム

7.2.2. HEADERS

HEADERSフレーム(type=0x01)は、QPACKを使用してエンコードされたHTTPフィールドセクションを運ぶために使用されます。詳細は[QPACK]を参照してください。

HEADERS Frame {
  Type (i) = 0x01,
  Length (i),
  Encoded Field Section (..),
}

図5:HEADERSフレーム
HEADERSフレームはリクエストストリームまたはプッシュストリームでのみ送信できます。コントロールストリームで HEADERS フレームを受信した場合、受信者は H3_FRAME_UNEXPECTED タイプのコネクションエラー (セクション 8) で応答しなければなりません (MUST)。

7.2.3. CANCEL_PUSH

CANCEL_PUSH フレーム (type=0x03) は、プッシュストリームを受信する前に、サーバープッシュのキャンセルを要求するために使用されます。CANCEL_PUSHフレームは可変長整数でエンコードされたPush ID (4.4項参照)によってサーバープッシュを識別します。

クライアントがCANCEL_PUSHを送信すると、約束されたリソースの受信を希望しないことを示します。サーバーはリソースの送信を中止すべきですが、そのメカニズムは対応するプッシュストリームの状態に依存します。サーバーがまだプッシュストリームを作成していない場合は、作成しません。プッシュストリームが開いている場合、サーバーはそのストリームを突然終了させるべきです(SHOULD)。プッシュストリームがすでに終了している場合、サーバーはまだそのストリームを突然終了させてもよいし、何もしなくてもよい。

サーバーはCANCEL_PUSHを送信して、以前に送信されたプロミスを履行しないことを示します。クライアントは、約束された応答をすでに受信して処理していない限り、対応する約束が果たされることを期待することはできません。プッシュストリームがオープンされているかどうかに関わらず、サーバーはプロミスが履行されないと判断した場合、CANCEL_PUSHフレームを送信するべきです(SHOULD)。ストリームがすでに開かれている場合、サーバーはH3_REQUEST_CANCELLEDのエラーコードでストリームでの送信を中断することができます。

CANCEL_PUSH フレームを送信しても、既存のプッシュストリームの状態には直接影響しません。クライアントは、対応するプッシュストリームをすでに受信している場合、CANCEL_PUSH フレームを送信すべきではありません(SHOULD NOT)。サーバーがCANCEL_PUSHを処理していない可能性があるため、クライアントがCANCEL_PUSHフレームを送信した後に、プッシュストリームが到着する可能性があります。クライアントはH3_REQUEST_CANCELLEDのエラーコードでストリームの読み込みを中断すべきです。

CANCEL_PUSHフレームはコントロールストリーム上で送信されます。制御ストリーム以外のストリームでCANCEL_PUSHフレームを受信すると、H3_FRAME_UNEXPECTED型の接続エラーとして扱わなければなりません(MUST)。

CANCEL_PUSH Frame {
  Type (i) = 0x03,
  Length (i),
  Push ID (i),
}

図6:CANCEL_PUSHフレーム
CANCEL_PUSH フレームは可変長整数でエンコードされた Push ID を運びます。プッシュIDはキャンセルされるサーバープッシュを識別します;セクション4.4参照。CANCEL_PUSHフレームを受信した際に、その接続で現在許可されているよりも大きなPush IDを参照していた場合、これはH3_ID_ERROR型の接続エラーとして扱われなければなりません (MUST)。

クライアントがCANCEL_PUSHフレームを受信した場合、そのフレームは並び替えのためにPUSH_PROMISEフレームでまだ言及されていないPush IDを特定するかもしれません。サーバーがPUSH_PROMISEフレームによってまだ言及されていないPush IDのCANCEL_PUSHフレームを受信した場合、これはH3_ID_ERROR型の接続エラーとして扱われなければなりません(MUST)。

7.2.4. SETTINGS

SETTINGSフレーム(type=0x04)は、ピアの動作に関するプリファレンスや制約など、エンドポイントの通信方法に影響を与える設定パラメータを伝えます。個々に、SETTINGSパラメータは「設定」とも呼ばれます。各設定パラメータの識別子と値は、「設定識別子」と「設定値」と呼ばれます。

SETTINGSフレームは、常にHTTP/3接続全体に適用され、決して単一のストリームではありません。SETTINGSフレームは、各ピアによって各制御ストリーム (6.2.1項参照) の最初のフレームとして送信されなければならず (MUST)、それ以降は送信してはなりません (MUST NOT)。エンドポイントが制御ストリーム上で2つ目のSETTINGSフレームを受信した場合、エンドポイントはH3_FRAME_UNEXPECTEDタイプのコネクションエラーで応答しなければなりません (MUST)。

SETTINGSフレームは、制御ストリーム以外のストリームで送信してはなりません (MUST NOT)。エンドポイントが別のストリームで SETTINGS フレームを受信した場合、エンドポイントは H3_FRAME_UNEXPECTED タイプの接続エラーで応答しなければなりません (MUST)。

SETTINGS パラメーターはネゴシエートされることはなく、受信側のピアが使用できる送信側のピアの特性を記述します。しかし、SETTINGSの使用によってネゴシエーションを暗示することができます。各ピアはSETTINGSを使用して、サポートされる値のセットをアドバタイズします。設定の定義は、各ピアが2つのセットをどのように組み合わせて、どちらの選択肢を使用するかを結論づけるかを説明するものです。SETTINGSは、その選択がいつ有効になるかを特定するメカニズムを提供しません。

同じパラメータの異なる値を各ピアがアドバタイズすることができます。例えば、クライアントは非常に大きなレスポンスフィールドセクションを消費しても構わないかもしれませんが、サーバーはリクエストのサイズについてより慎重になります。

同じ設定識別子がSETTINGSフレーム内で2回以上出現してはいけません (MUST NOT)。受信者は、設定識別子の重複を H3_SETTINGS_ERROR タイプのコネクションエラーとして扱ってもよいものとします。

SETTINGS フレームのペイロードは、0個以上のパラメーターで構成されます。各パラメーターは設定識別子と値で構成され、どちらもQUIC可変長整数でエンコードされています。

Setting {
  Identifier (i),
  Value (i),
}
SETTINGS Frame {
  Type (i) = 0x04,
  Length (i),
  Setting (..) ...,
}

図7:SETTINGSフレーム
実装は、理解できない識別子を持つパラメータを無視しなければなりません(MUST)。

7.2.4.1. 定義されたSETTINGSパラメータ

HTTP/3では以下の設定が定義されています。

SETTINGS_MAX_FIELD_SECTION_SIZE (0x06)です。
デフォルト値は無制限です。使用方法はセクション4.1.1.3を参照してください。

0x1f * N + 0x21という形式の識別子をNの非負の整数値に対して設定することは、未知の識別子を無視するという要求を実行するために予約されています。このような設定には定義された意味はありません。エンドポイントは、少なくとも1つのそのような設定をSETTINGSフレームに含めるべきです(SHOULD)。エンドポイントは、このような設定を受け取った時点で意味があると考えてはいけません (MUST NOT)。

設定には定義された意味がないため、設定の値は実装が選択した任意の値になります。

HTTP2]で定義された、対応するHTTP/3の設定がない設定識別子も予約されています (11.2.2項)。これらの予約された設定は送信してはならず、その受信はH3_SETTINGS_ERROR型の接続エラーとして扱われなければなりません(MUST)。

追加の設定は、HTTP/3の拡張機能で定義できます。詳細はセクション9を参照してください。

7.2.4.2. 初期化

HTTP 実装は、相手の設定に関する現在の理解に基づいて、無効なフレームまたはリクエストを送信してはなりません (MUST NOT)。

すべての設定は、初期値から始まります。各エンドポイントは、設定を運ぶパケットが失われたり遅れたりする可能性があるため、相手のSETTINGSフレームが到着する前に、これらの初期値を使用してメッセージを送信すべきです (SHOULD)。SETTINGS フレームが到着すると、すべての設定が新しい値に変更されます。

これにより、メッセージを送信する前にSETTINGSフレームを待つ必要がなくなります。エンドポイントは、SETTINGSフレームを送信する前にピアからデータを受信することを要求してはなりません (MUST NOT)。

サーバーの場合、各クライアント設定の初期値はデフォルト値となります。

1-RTT QUIC接続を使用するクライアントの場合、各サーバー設定の初期値はデフォルト値です。1-RTTキーは、サーバが直ちにSETTINGSを送信した場合でも、SETTINGSを含むパケットがQUICで処理される前に必ず利用可能になる。クライアントは、リクエストを送信する前にSETTINGSが到着するのを無期限に待つべきではなく、最初のリクエストを送信する前にSETTINGSを処理する可能性を高めるために、受信したデータグラムを処理するべきである。

0-RTT QUIC接続を使用している場合、各サーバの設定の初期値は前回のセッションで使用された値です。クライアントは、再開情報が提供されたHTTP/3接続でサーバーが提供した設定を保存すべきですが、特定のケースでは設定を保存しないことを選択してもよいものとします(例:SETTINGSフレームの前にセッションチケットを受信した場合)。クライアントは、0-RTTを試みる際、保存されている設定(値が保存されていない場合はデフォルト値)に従わなければなりません(MUST)。サーバーが新しい設定を提供すると、クライアントはその値に従わなければなりません(MUST)。

サーバは広告した設定を記憶するか、チケットに値の完全性が保護されたコピーを保存し、0-RTTデータを受け入れる際にその情報を回復することができます。サーバーは、0-RTTデータを受け入れるかどうかを決定する際に、HTTP/3の設定値を使用します。クライアントが記憶した設定が現在の設定と互換性があることをサーバーが判断できない場合、0-RTTデータを受け入れてはいけません(MUST NOT)。記憶された設定は、クライアントがその設定に従うことでサーバーの現在の設定に違反しない場合、互換性があります。

サーバーは 0-RTT を受け入れ、その後 SETTINGS フレームで異なる設定を提供してもよい(MAY)。0-RTTデータがサーバーに受け入れられた場合、そのSETTINGSフレームは、0-RTTデータを持つクライアントが違反する可能性のある制限値を減らしたり、値を変更したりしてはなりません (MUST NOT)。サーバーは、デフォルト値と異なるすべての設定を含めなければなりません(MUST)。サーバーが0-RTTを受け入れた後、以前に指定された設定と互換性のない設定を送信した場合、これはH3_SETTINGS_ERROR型の接続エラーとして扱われなければなりません(MUST)。サーバーが0-RTTを受け入れた後、以前にデフォルト以外の値を持つように指定された、クライアントが理解できる設定値(予約済みの設定識別子を除く)を省略したSETTINGSフレームを送信した場合、これはH3_SETTINGS_ERRORタイプのコネクションエラーとして扱われなければなりません(MUST)。

7.2.5. PUSH_PROMISE

PUSH_PROMISE フレーム (type=0x05) は、HTTP/2 のようにリクエストストリーム上でサーバーからクライアントに約束されたリクエストヘッダーセクションを運ぶために使われます。

PUSH_PROMISE Frame {
  Type (i) = 0x05,
  Length (i),
  Push ID (i),
  Encoded Field Section (..),
}

図8:PUSH_PROMISEフレーム
ペイロードは以下の構成となっている。

プッシュID。
サーバーのプッシュ操作を識別する可変長の整数です。プッシュIDはプッシュストリームヘッダー (4.4節) やCANCEL_PUSH フレーム (7.2.3節) で使用されます。

エンコードされたフィールドセクション。
QPACKでエンコードされた、約束された応答のためのリクエストヘッダーフィールドです。詳細は[QPACK]を参照してください。

サーバーは、クライアントがMAX_PUSH_IDフレーム(7.2.7項)で提供したものよりも大きいプッシュIDを使用してはなりません(MUST NOT)。クライアントは、クライアントがアドバタイズしたものよりも大きなPUSH IDを含むPUSH_PROMISEフレームの受信を、H3_ID_ERRORの接続エラーとして扱わなければなりません (MUST)。

サーバーは複数のPUSH_PROMISEフレームで同じPush IDを使用してもよいものとします。その場合、解凍されたリクエストヘッダーセットには、同じフィールドが同じ順番で含まれていなければならず(MUST)、各フィールドの名前と値の両方が完全に一致しなければなりません(MUST)。クライアントは、複数回約束されたリソースのリクエストヘッダーセクションを比較するべきです(SHOULD)。クライアントが、すでにプロミスされたプッシュIDを受信して不一致を検出した場合、H3_GENERAL_PROTOCOL_ERRORタイプのコネクションエラーで応答しなければなりません(MUST)。解凍されたフィールドセクションが完全に一致する場合、クライアントはPUSH_PROMISEフレームを受信した各ストリームにプッシュされたコンテンツを関連付けるべきです(SHOULD)。

同じPush IDへの重複した参照を許可するのは、主に同時リクエストによる重複を減らすためです。サーバーは、1つのPush IDを長期間にわたって再利用することは避けるべきです(SHOULD)。クライアントは、サーバーのプッシュレスポンスを消費し、長期にわたって再利用するためにそれらを保持しない可能性があります。既に消費して破棄したPush IDを使用したPUSH_PROMISEフレームを見たクライアントは、その約束を無視せざるを得ません。

PUSH_PROMISE フレームをコントロールストリーム上で受信した場合、クライアントは H3_FRAME_UNEXPECTED タイプのコネクションエラーで応答しなければなりません (セクション8を参照)。

クライアントは PUSH_PROMISE フレームを送信してはなりません (MUST NOT)。サーバーは、PUSH_PROMISE フレームの受信を H3_FRAME_UNEXPECTED タイプのコネクションエラーとして扱わなければなりません (セクション8参照)。

サーバーのプッシュメカニズム全体については、セクション4.4を参照してください。

7.2.6. GOAWAY

GOAWAY フレーム (type=0x07) は、どちらかのエンドポイントが HTTP/3 接続のグレースフルシャットダウンを開始するために使用されます。GOAWAY は、エンドポイントが新しいリクエストやプッシュの受け入れを停止する一方で、以前に受け取ったリクエストやプッシュの処理を終了することを可能にします。これにより、サーバーのメンテナンスなどの管理作業が可能になります。GOAWAYはそれだけでは接続を閉じません。

GOAWAY Frame {
  Type (i) = 0x07,
  Length (i),
  Stream ID/Push ID (..),
}

図9:GOAWAYフレーム
GOAWAYフレームは常にコントロールストリーム上で送信されます。サーバーからクライアントへの方向では、可変長整数でエンコードされたクライアントが開始する双方向ストリームのQUICストリームIDを運びます。クライアントは、他のタイプのStream IDを含むGOAWAYフレームの受信を、H3_ID_ERRORタイプのコネクションエラーとして扱わなければなりません(MUST)。

クライアントからサーバーへの方向では、GOAWAY フレームは可変長整数としてエンコードされた Push ID を運びます。

GOAWAYフレームは、特定のストリームではなく、接続全体に適用されます。クライアントは、制御ストリーム以外のストリーム上の GOAWAY フレームを、H3_FRAME_UNEXPECTED タイプのコネクションエラーとして扱わなければなりません (MUST) (セクション 8 参照)。

GOAWAYフレームの使用に関する詳細は、セクション5.2を参照してください。

7.2.7. MAX_PUSH_ID

MAX_PUSH_IDフレーム(type=0x0d)は、サーバーが開始できるサーバープッシュの数をコントロールするためにクライアントが使用します。これは、サーバーがPUSH_PROMISEやCANCEL_PUSHフレームで使用できるプッシュIDの最大値を設定します。その結果、QUICトランスポートで維持されている制限に加えて、サーバーが開始できるプッシュストリームの数も制限されます。

MAX_PUSH_IDフレームは、常にコントロールストリーム上で送信されます。他のストリームでのMAX_PUSH_IDフレームの受信は、H3_FRAME_UNEXPECTEDタイプのコネクションエラーとして扱わなければなりません(MUST)。

サーバーは MAX_PUSH_ID フレームを送信してはいけません (MUST NOT)。クライアントは、MAX_PUSH_IDフレームの受信をH3_FRAME_UNEXPECTED型の接続エラーとして扱わなければなりません (MUST)。

最大プッシュIDは、HTTP/3コネクションが作成される際に設定解除されます。つまり、サーバーはMAX_PUSH_IDフレームを受信するまでプッシュできません。約束されたサーバープッシュの数を管理したいクライアントは、サーバーがサーバープッシュを実行またはキャンセルする際にMAX_PUSH_IDフレームを送信することで、最大Push IDを増やすことができます。

MAX_PUSH_ID Frame {
  Type (i) = 0x0d,
  Length (i),
  Push ID (i),
}

図10:MAX_PUSH_IDフレーム
MAX_PUSH_ID フレームは、サーバーが使用できるPush IDの最大値を特定する1つの可変長整数を運びます(4.4項参照)。MAX_PUSH_IDフレームは、最大のPush IDを減らすことはできません。以前に受信した値よりも小さい値を含むMAX_PUSH_IDフレームの受信は、H3_ID_ERROR型の接続エラーとして扱われなければなりません (MUST)。

7.2.8. 予約されたフレームタイプ

0x1f * N + 0x21 形式の非負の整数値 N のフレームタイプは、未知のタイプを無視するという要求を実行するために予約されています (セクション 9)。これらのフレームはセマンティクスを持たず、フレームの送信が許可されているすべてのストリームで送信してもかまいません(MAY)。これにより、アプリケーション層のパディングに使用することができます。エンドポイントは、これらのフレームを受信時に何らかの意味があると考えてはいけません (MUST NOT)。

フレームのペイロードと長さは、実装が選択する任意の方法で選択されます。

HTTP/2 で使用され、対応する HTTP/3 フレームが存在しないフレームタイプも予約されています (11.2.1節)。これらのフレームタイプは送信してはならず (MUST NOT)、受信した場合は H3_FRAME_UNEXPECTED タイプの接続エラーとして扱われなければなりません (MUST)。

voluntasvoluntas

8. エラー処理

ストリームが正常に完了できない場合、QUICではアプリケーションがそのストリームを突然終了(リセット)し、理由を伝えることができます([QUIC-TRANSPORT]のセクション2.4を参照)。これは "ストリームエラー "と呼ばれています。HTTP/3の実装は、QUICストリームを閉じることを決定し、エラーの種類を伝えることができます。エラーコードのワイヤエンコーディングは、セクション8.1で定義されています。ストリームエラーは、エラー状態を示すHTTPステータスコードとは異なります。ストリームエラーは、送信者がリクエストまたはレスポンスを完全に転送または消費しなかったことを示し、一方、HTTPステータスコードは、正常に受信されたリクエストの結果を示します。

コネクション全体を終了する必要がある場合、QUICは同様に理由を伝えるメカニズムを提供する。これは "コネクションエラー "と呼ばれています。ストリームエラーと同様に、HTTP/3の実装はQUICの接続を終了し、セクション8.1のエラーコードを用いて理由を伝えることができます。

ストリームや接続を終了する理由は「エラー」と呼ばれますが、これらのアクションは必ずしも接続やどちらかの実装の問題を示すものではありません。例えば、要求されたリソースが不要になった場合、ストリームをリセットすることができます。

エンドポイントは、特定の状況下で、ストリームのエラーをコネクションのエラーとして扱い、単一のストリームの条件に応じてコネクション全体を閉じることを選択してもよいものとします(MAY)。実装では、この選択をする前に、未処理のリクエストへの影響を考慮する必要があります。

新しいエラーコードはネゴシエーションなしに定義できるため(セクション9参照)、予期しない状況でのエラーコードの使用や、未知のエラーコードの受信は、H3_NO_ERRORと同等に扱われなければなりません(MUST)。しかし、ストリームを閉じることは、エラーコードに関係なく、他の効果があります。

8.1. HTTP/3 エラーコード

以下のエラーコードは、ストリームを突然終了したり、ストリームの読み取りを中止したり、HTTP/3接続を直ちに閉じたりする際に使用するために定義されています。

H3_NO_ERROR (0x0100):
エラーはありません。接続やストリームを閉じる必要があるが、シグナルを送るべきエラーがない場合に使用されます。

H3_GENERAL_PROTOCOL_ERROR(0x0101):エラーです。
ピアが、より具体的なエラーコードに一致しない方法でプロトコルの要件に違反したか、エンドポイントがより具体的なエラーコードの使用を拒否しています。

H3_INTERNAL_ERROR (0x0102):
HTTPスタックで内部エラーが発生しました。

H3_STREAM_CREATION_ERROR(0x0103)です。
エンドポイントは、そのピアが受け入れられないストリームを作成したことを検出しました。

H3_CLOSED_CRITICAL_STREAM (0x0104):
HTTP/3接続で必要なストリームが閉じられたかリセットされました。

H3_FRAME_UNEXPECTED(0x0105):許可されていないフレームを受信しました。
現在の状態または現在のストリームで許可されていないフレームを受信しました。

H3_FRAME_ERROR (0x0106):
レイアウト要件を満たしていないか、無効なサイズのフレームを受信しました。

H3_EXCESSIVE_LOAD (0x0107):
エンドポイントは、そのピアが過剰な負荷を発生させる可能性のある動作を示していることを検出しました。

H3_ID_ERROR(0x0108):ストリームIDまたはプッシュIDが使用されました。
ストリームIDまたはプッシュIDが、制限を超えたり、制限を減らしたり、再使用されたりするなど、不正に使用されました。

H3_SETTINGS_ERROR (0x0109):
エンドポイントがSETTINGSフレームのペイロードにエラーを検出しました。

H3_MISSING_SETTINGS (0x010a):
コントロールストリームの先頭にSETTINGSフレームが受信されませんでした。

H3_REQUEST_REJECTED(0x010b)。
サーバーはアプリケーション処理を実行せずに要求を拒否しました。

H3_REQUEST_CANCELLED(0x010c)。
要求またはその応答(プッシュされた応答を含む)がキャンセルされました。

H3_REQUEST_INCOMPLETE (0x010d):
クライアントのストリームが、完全な形式の要求を含まずに終了しました。

H3_MESSAGE_ERROR (0x010e):
HTTPメッセージが不正な形式で、処理できませんでした。

H3_CONNECT_ERROR(0x010f)です。
CONNECT要求に応答して確立されたTCPコネクションがリセットされたか、異常に閉じられました。

H3_VERSION_FALLBACK (0x0110):
要求された操作はHTTP/3上では提供できません。ピアはHTTP/1.1で再試行する必要があります。

Nの非負の整数値に対する0x1f * N + 0x21の形式のエラーコードは、未知のエラーコードをH3_NO_ERRORと同等に扱うという要求を実行するために予約されています(セクション9)。実装者は、H3_NO_ERRORを送信したであろうときに、ある程度の確率でこのスペースからエラーコードを選択するべきです(SHOULD)。

voluntasvoluntas

9. HTTP/3の拡張機能

HTTP/3 はプロトコルの拡張を許可します。この節で述べた制限の範囲内で、プロトコルの拡張を使用して追加サービスを提供したり、プロトコルのあらゆる側面を変更したりすることができます。拡張は、単一の HTTP/3 接続の範囲内でのみ有効です。

これは、このドキュメントで定義されているプロトコル要素に適用されます。これは、新しいメソッド、ステータスコード、またはフィールドの定義など、HTTPを拡張するための既存のオプションには影響しません。

拡張は、新しいフレームタイプ(7.2項)、新しい設定(7.2.4.1項)、新しいエラーコード(8項)、または新しい一方向ストリームタイプ(6.2項)を使用することが許可されます。フレームタイプ(11.2.1項)、設定(11.2.2項)、エラーコード(11.2.3項)、ストリームタイプ(11.2.4項)の各拡張点を管理するためのレジストリが設けられています。

実装では、すべての拡張可能なプロトコル要素において、未知の値やサポートされていない値を無視しなければなりません(MUST)。実装では、未知または未サポートのタイプを持つ一方向性ストリームのフレームを破棄し、読み取りを中止しなければなりません (MUST)。これは、これらの拡張ポイントのいずれも、事前の取り決めや交渉なしに、拡張機能によって安全に使用できることを意味します。しかし、制御ストリームの最初のフレームとしての SETTINGS フレームのように、既知のフレームタイプが特定の場所にあることが要求される場合 (6.2.1節参照)、未知のフレームタイプはその要求を満たさず、エラーとして扱われるべきです (SHOULD)。

既存のプロトコルコンポーネントのセマンティクスを変更する可能性のある拡張機能は、使用する前にネゴシエートしなければなりません (MUST)。例えば、HEADERSフレームのレイアウトを変更する拡張機能は、ピアが受け入れ可能であるという肯定的なシグナルを与えるまで使用できません。このようなレイアウトの変更がいつ有効になるのかを調整することは、複雑になる可能性があります。そのため、既存のプロトコル要素の新しい定義に新しい識別子を割り当てることがより効果的であると考えられます。

本文書では、拡張機能の使用をネゴシエートするための特定の方法を義務付けてはいませんが、そのために設定(7.2.4.1項)を使用することができることを指摘しています。両方のピアが拡張を使用する意思があることを示す値を設定した場合、その拡張を使用することができます。拡張のネゴシエーションに設定を使用する場合は、設定を省略すると拡張が無効になるようにデフォルト値を定義しなければなりません(MUST)。

voluntasvoluntas

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

HTTP/3 のセキュリティに関する考慮事項は、TLS を使用した HTTP/2 のそれと同等であるべきです。しかし、[HTTP2]のセクション10からの考慮事項の多くは[QUIC-TRANSPORT]に適用され、同文書で議論されています。

10.1. サーバーの権限

HTTP/3 は、HTTP の権限の定義に依存しています。権限を確立するためのセキュリティ上の考慮事項は、[SEMANTICS]のセクション17.1で議論されています。

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

TLS と QUIC のハンドシェイクに ALPN を使用することで、アプリケーション層のバイトが処理される前に、ターゲットとなるアプリケーションのプロトコルが確立されます。これにより、エンドポイントは相手が同じプロトコルを使用していることを確実に保証できます。

これは、すべてのクロスプロトコル攻撃からの保護を保証するものではありません。QUIC-TRANSPORT]のセクション21.5では、認証されたトランスポートを使用していないエンドポイントに対して、QUICパケットの平文を使用してリクエストフォージェリを実行できるいくつかの方法について説明しています。

10.3. 中間エンキャプシュレーション攻撃

HTTP/3のフィールドエンコーディングは、HTTPで使用される構文では有効なフィールド名ではない名前の表現を可能にします([SEMANTICS]のセクション5.1)。無効なフィールド名を含むリクエストまたはレスポンスは、不正なものとして扱われなければなりません(MUST)(セクション4.1.3)。したがって、仲介者は、無効なフィールド名を含むHTTP/3リクエストまたはレスポンスをHTTP/1.1メッセージに変換することはできません。

同様に、HTTP/3 は有効ではないフィールド値を伝送することができます。エンコード可能なほとんどの値はフィールドの解析を変更しませんが、キャリッジリターン(CR, ASCII 0x0d)、ラインフィード(LF, ASCII 0x0d)、ゼロ文字(NUL, ASCII 0x0d)は、そのまま翻訳されると攻撃者に悪用される可能性があります。フィールド値で許可されていない文字を含むリクエストやレスポンスは、不正なものとして扱われなければなりません(セクション4.1.3)。有効な文字は、[SEMANTICS]のセクション5.5の「field-content」ABNFルールで定義される。

10.4. プッシュされた応答のキャッシュ可能性

PUSHされたレスポンスには、クライアントからの明示的なリクエストはなく、リクエストはPUSH_PROMISEフレームの中でサーバーから提供されます。

リクエストはPUSH_PROMISEフレーム内でサーバーから提供されます。プッシュされたレスポンスをキャッシュすることは、オリジンサーバーがCache-Controlヘッダーフィールドで提供するガイダンスに基づいて可能です。しかし、1つのサーバーが複数のテナントをホストしている場合、これは問題を引き起こす可能性があります。例えば、あるサーバーが複数のユーザーにそれぞれのURIスペースのごく一部を提供している場合があります。

複数のテナントが同じサーバー上のスペースを共有する場合、そのサーバーは、テナントが権限を持たないリソースの表現をプッシュできないようにしなければなりません(MUST)。これを実施しないと、権威のあるテナントが提供する実際の表現を上書きして、キャッシュから出される表現をテナントが提供することになります。

クライアントは、オリジンサーバが権限を持たない場合、プッシュされた応答を拒否することが要求されます(セクション4.4参照)。

10.5. サービス拒否の考慮事項

HTTP/3 の接続は、HTTP/1.1 や HTTP/2 の接続に比べて、より多くのリソースを必要とします。フィールド圧縮やフロー制御の使用は、より多くの状態を保存するためのリソースのコミットに依存します。これらの機能の設定では、これらの機能のためのメモリのコミットが厳密に制限されます。

PUSH_PROMISEフレームの数も同様に制限されています。サーバープッシュを受け入れるクライアントは、一度に発行するプッシュIDの数を制限すべきです(SHOULD)。

処理能力は、状態能力のように効果的にガードすることはできません。

相手が無視することを要求される未定義のプロトコル要素を送信する能力は、相手に追加の処理時間を消費させるために悪用することができます。これは、未定義のSETTINGSパラメータを複数設定したり、未知のフレームタイプや未知のストリームタイプを設定することで可能になります。しかし、オプションで理解できる拡張機能や、トラフィック解析への耐性を高めるためのパディングなど、完全に合法的な使用方法もありますのでご注意ください。

フィールドセクションの圧縮は、処理リソースを浪費する可能性もあります。潜在的な悪用の詳細については、[QPACK]のセクション7を参照してください。

これらの機能(サーバープッシュ、未知のプロトコル要素、フィールド圧縮など)には、すべて正当な用途があります。これらの機能が負担になるのは、不必要に使用されたり、過剰に使用された場合だけです。

このような動作を監視していないエンドポイントは、サービス拒否攻撃のリスクにさらされています。実装では、これらの機能の使用を追跡し、その使用に制限を設けるべきです(SHOULD)。エンドポイントは、疑わしい動作をH3_EXCESSIVE_LOAD(セクション8)タイプの接続エラーとして扱ってもよい(MAY)が、誤検知は有効な接続やリクエストを中断させる結果となる。

10.5.1. フィールドセクションのサイズの制限

大きなフィールドセクション(セクション4.1)は、実装が大量のステートをコミットする原因となる。ルーティングに重要なヘッダーフィールドがヘッダーセクションの最後に現れ る可能性があり、最終的なデスティネーションへのヘッダーセクションのストリーミング を妨げる。この順序と、キャッシュの正しさを確保するなどの理由から、エンドポイントはヘッダーセクション全体をバッファリングする必要があると考えられます。フィールド・セクションのサイズには制限がないため、エンドポイントによっては、利用可能なメモリの多くをヘッダー・フィールドのために使わざるを得ない場合があります。

エンドポイントは、SETTINGS_MAX_FIELD_SECTION_SIZE(セクション4.1.1.3)設定を使用して、フィールド・セクションのサイズに適用される可能性のある制限を相手に知らせることができます。この設定は助言に過ぎないため、エンドポイントはこの制限を超えるフィールドセクションを送信することを選択してもかまいませんが、リクエストまたはレスポンスが不正なものとして扱われる危険性があります。この設定は HTTP/3 コネクションに特有のものですので、どのようなリクエストやレスポンスでも、より低い未知の制限値を持つホップに遭遇する可能性があります。仲介者は、異なるピアから提示された値を渡すことでこの問題を回避しようとすることができますが、そうする義務はありません。

処理できる範囲を超えた大きなフィールドセクションを受け取ったサーバーは、HTTP 431 (Request Header Fields Too Large) ステータスコード ([RFC6585])を送信できます。クライアントは、処理できない応答を破棄することができます。

10.5.2. CONNECTの問題

CONNECTメソッドは、プロキシに不均衡な負荷を与えるために使用される可能性があります。なぜなら、TCPコネクションの作成と維持に比べて、ストリームの作成は比較的安価だからです。したがって、CONNECTをサポートするプロキシは、受け入れ る同時リクエストの数をより慎重にするかもしれない。

プロキシは、発信するTCP接続がTIME_WAIT状態のままなので、CONNECTリクエストを運ぶストリームの終了後も、TCP接続のためのいくつかのリソースを維持するかもしれない。これを考慮して、プロキシは、TCP接続が終了した後、しばらくの間、QUICストリームの制限値の増加を遅らせるかもしれない。

10.6. 圧縮の使用

圧縮は、攻撃者のコントロール下にあるデータと同じコンテキストで圧縮された場合、攻撃者が秘密データを回復することを可能にします。HTTP/3はフィールドの圧縮を可能にします(セクション4.1.1)。以下の懸念は、HTTP圧縮コンテンツコーディングの使用にも適用されます。

ウェブの特性を利用した、圧縮に対する実証可能な攻撃があります(例えば、[BREACH])。攻撃者は、様々な平文を含む複数のリクエストを誘導し、それぞれのリクエストで得られる暗号文の長さを観察し、秘密に関する推測が正しければより短い長さであることを明らかにします。

安全なチャネルで通信する実装は、データの各ソースに別々の圧縮コンテキストが使用されない限り、機密データと攻撃者が管理するデータの両方を含むコンテンツを圧縮してはなりません(MUST NOT)。データのソースを確実に特定できない場合は、圧縮を使用してはならない(MUST NOT)。

フィールドセクションの圧縮に関するさらなる検討事項は、[QPACK]に記載されている。

10.7. パディングとトラフィック解析

パディングは、フレームコンテンツの正確なサイズを不明瞭にするために使用され、HTTP の特定の攻撃を緩和するために提供されます。例えば、圧縮されたコンテンツに攻撃者が制御する平文と秘密データの両方が含まれる攻撃 (例: [BREACH]) などです。

HTTP/2 がトラフィック解析に対して接続をより強固にするために、PADDING フレームや他のフレームの Padding フィールドを採用しているのに対し、HTTP/3 はトランスポート層のパディングに頼るか、7.2.8 節と 6.2.3 節で説明した予約済みのフレームやストリームタイプを採用することができます。これらのパディング方法は、パディングの粒度、保護されている情報に対するパディングの配置、パケットロス時にパディングを適用するかどうか、パディングの制御方法などの点で異なる結果をもたらします。

予約済みのストリームタイプを使用すると、接続がアイドル状態でもトラフィックを送信しているように見せることができます。HTTP トラフィックはバースト的に発生することが多いため、見かけ上のトラフィックを使用することで、バーストのタイミングや継続時間を不明瞭にし、一定のデータストリームを送信しているように見せることができます。しかし、このようなトラフィックは受信者によってフロー制御されているため、このようなストリームを速やかに排出し、追加のフロー制御クレジットを提供しないと、送信者が実際のトラフィックを送信する能力が制限されてしまいます。

圧縮に依存した攻撃を軽減するためには、対策としてパディングを行うよりも、圧縮を無効にしたり制限したりする方が望ましい場合があります。

パディングを使用すると、すぐにわかるような防御力が低くなることがあります。冗長なパディングは逆効果になることもあります。パディングは、攻撃者が観測しなければならないフレームの数を増やすことで、攻撃者が長さ情報を推測するのを難しくするだけです。パディングが正しく実装されていないと、簡単に破られてしまいます。同様に、ペイロードを固定サイズにパディングすると、ペイロードのサイズが固定サイズの境界を越えたときに情報が漏洩してしまいます。これは、攻撃者が平文を制御できる場合に可能となります。

10.8. フレームの解析

いくつかのプロトコル要素には、ネストした長さの要素が含まれています。一般的には、可変長の整数を含む明示的な長さのフレームの形をしています。これは、慎重でない実装者にとっては、セキュリティ上のリスクとなる可能性があります。実装では、フレームの長さが、それが含むフィールドの長さと正確に一致することを保証しなければなりません (MUST)。

10.9. 初期データ

HTTP/3 での 0-RTT の使用は、リプレイ攻撃にさらされることになります。HTTP/3 を 0-RTT で使用する場合は、[HTTP-REPLAY] のリプレイ対策を適用しなければなりません (MUST)。HTTP-REPLAY]をHTTP/3に適用する場合、TLS層への参照はQUIC内で実行されるハンドシェイクを参照し、アプリケーションデータへのすべての参照はストリームのコンテンツを参照します。

10.10. マイグレーション

一部のHTTP実装では、ログ記録やアクセス制御の目的でクライアントアドレスを使用しています。QUICクライアントのアドレスは接続中に変更される可能性があるため(将来のバージョンでは複数のアドレスの同時使用がサポートされるかもしれません)、そのような実装では、クライアントの現在のアドレスを関連性があるときに積極的に取得するか、元のアドレスが変更される可能性があることを明示的に受け入れる必要があります。

10.11. プライバシーに関する考察

HTTP/3のいくつかの特徴は、観察者に、単一のクライアントやサーバの時間的な行動を相関させる機会を提供します。これには、設定の値、刺激に対する反応のタイミング、設定によって制御される機能の処理などが含まれます。

これらの行動に観察可能な違いがある限り、特定のクライアントを識別するための基礎として使用することができます。

HTTP/3では、1つのQUICコネクションを使用することで、サイト上でのユーザーの活動を相関させることができます。異なるオリジンに対して接続を再利用することで、それらのオリジン間の活動の相関を取ることができます。

QUICのいくつかの機能は即時の応答を求め、エンドポイントが相手とのレイテンシーを測定するために使用することができますが、これは特定のシナリオにおいてプライバシーに影響を与える可能性があります。

voluntasvoluntas

11. IANAに関する検討事項

この文書では、新しいALPNプロトコルID(11.1項)を登録し、HTTP/3のコードポイントの割り当てを管理する新しいレジストリを作成します。

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

本文書は、[RFC7301]で確立された "Application-Layer Protocol Negotiation (ALPN) Protocol IDs" レジストリに、HTTP/3 の識別のための新しい登録を作成します。

h3 "文字列は、HTTP/3を識別します。

プロトコルです。
HTTP/3

識別シーケンス。
0x68 0x33 ("h3")

仕様です。
このドキュメント

11.2. 新規登録機関

本文書で作成された新規登録は、[QUIC-TRANSPORT]のセクション22.1で文書化されたQUICの登録ポリシーに基づいて動作する。これらのレジストリはすべて、[QUIC-TRANSPORT]のセクション22.1.1に記載されている共通のフィールドセットを含む。これらのレジストリは、「Hypertext Transfer Protocol version 3 (HTTP/3) Parameters」という見出しの下に集められます(SHALL/are)。

本文書で作成されたこれらのレジストリの最初の割り当ては、すべて永続的なステータスが割り当てられ、IETFの変更管理者とHTTPワーキンググループ(ietf-http-wg@w3.org)の連絡先が記載されています。

11.2.1. フレームタイプ

本文書は、HTTP/3 フレームタイプコードのレジストリを確立します。HTTP/3 フレームタイプ」レジストリは、62 ビットの空間を管理します。このレジストリは、QUICのレジストリポリシーに従います(11.2項参照)。ただし、0x00~0x3f(16進数)の値については、[RFC8126]のセクション4.9および4.10で定義されている Standards Action または IESG Approval を使用して割り当てられます。

このレジストリは、[HTTP2] で定義されている "HTTP/2 Frame Type" レジストリとは別のものですが、コードスペースが重なる部分では、互いに並行して割り当てられることが望ましいです。エントリが1つのレジストリにしか存在しない場合、対応する値が無関係な操作に割り当てられることを避けるために、あらゆる努力がなされるべきです。エキスパートレビュアーは、対応するレジストリの同じ値と衝突するような、関係のない登録を拒否してもよい(MAY)。

11.2項に記載されている共通フィールドに加えて、このレジストリの永久登録は以下のフィールドを含まなければならない(MUST)。

フレームタイプ。
フレームタイプ: フレームタイプの名前またはラベル。

フレームタイプの仕様には、条件付きで存在するフレームの部分を含めて、フレームのレイアウトとそのセマンティクスの説明を含めなければなりません(MUST)。

表2のエントリは、このドキュメントによって登録されています。

Frame Type Value Specification
DATA 0x00 Section 7.2.1
HEADERS 0x01 Section 7.2.2
Reserved 0x02 N/A
CANCEL_PUSH 0x03 Section 7.2.3
SETTINGS 0x04 Section 7.2.4
PUSH_PROMISE 0x05 Section 7.2.5
Reserved 0x06 N/A
GOAWAY 0x07 Section 7.2.6
Reserved 0x08 N/A
Reserved 0x09 N/A
MAX_PUSH_ID 0x0d Section 7.2.7

表2:HTTP/3の初期フレームタイプ

0x1f * N + 0x21 という形式で、非負の整数である N (つまり 0x21, 0x40, ..., ~ 0x3ffffffffffe) に対応する各コードは、IANA によって割り当てられてはならず、 割り当てられた値のリストにも掲載してはならない。

11.2.2. 設定パラメータ

本文書は、HTTP/3 設定のレジストリを確立します。HTTP/3 設定」レジストリは、62 ビットの空間を管理します。このレジストリは、QUICのレジストリポリシーに従います(11.2節参照)。ただし、0x00~0x3f(16進数)の値については、[RFC8126]のセクション4.9および4.10で定義されている Standards Action または IESG Approval を使用して割り当てられます。

このレジストリは、[HTTP2] で定義された "HTTP/2 Settings" レジストリとは別個のものですが、これらの割り当ては互いに並行して行われることが望ましいです。エントリが1つのレジストリにしか存在しない場合、対応する値が無関係な操作に割り当てられることを避けるために、あらゆる努力をするべきです(SHOULD)。エキスパートレビュアーは、対応するレジストリの同じ値と衝突するような、無関係な登録を拒否してもよい(MAY)。

セクション11.2に記載されている一般的なフィールドに加えて、このレジストリの永久登録は以下のフィールドを含まなければなりません(MUST)。

設定名。
設定のシンボリックな名前です。設定名の指定はオプションです。

デフォルト。
他に指示がない限り、設定の値です。デフォルトは、可能な限り制限された値であるべきです(SHOULD)。

表3の項目は、本文書で登録されています。

Setting Name Value Specification Default
Reserved 0x00 N/A N/A
Reserved 0x02 N/A N/A
Reserved 0x03 N/A N/A
Reserved 0x04 N/A N/A
Reserved 0x05 N/A N/A
MAX_FIELD_SECTION_SIZE 0x06 Section 7.2.4.1 Unlimited

表3:HTTP/3の初期設定

0x1f * N + 0x21 という形式で、非負の整数である N (つまり 0x21, 0x40, ..., ~ 0x3ffffffffffe) に対応する各コードは、IANA によって割り当てられてはならず、 割り当てられた値のリストにも掲載してはならない。

11.2.3. エラーコード

この文書は、HTTP/3 エラーコードのレジストリを確立します。HTTP/3 エラーコード」レジストリは、62 ビットの空間を管理します。このレジストリは、QUICのレジストリポリシーに従います(セクション11.2参照)。このレジストリの永続的な登録は、Specification Requiredポリシー([RFC8126])に基づいて割り当てられます。ただし、0x00から0x3f(16進数)の間の値は、[RFC8126]のセクション4.9と4.10で定義されているように、Standards ActionまたはIESG Approvalを使用して割り当てられます。

エラーコードの登録には、エラーコードの説明が必要です。既存のエラーコードとの重複の可能性がないか、新しい登録を専門家の審査員が審査することをお勧めします。既存の登録を使用することは推奨されますが、義務ではありません。HTTP/2 Error Code」レジストリに登録されている値の使用は推奨されず、専門家のレビュアーはそのような登録を拒否してもよいものとします。

セクション11.2で説明した共通フィールドに加えて、このレジストリには2つの追加フィールドがあります。このレジストリの永続的な登録は、以下のフィールドを含まなければなりません(MUST)。

名前。
エラーコードの名前。

説明。
エラーコードのセマンティクスを簡単に説明したもの。

表4のエントリは、このドキュメントによって登録されています。これらのエラーコードは、HTTP/2 のエラーコードとの衝突を避けるために、Specification Required のポリシーで動作する範囲から選択されました。

Name Value Description Specification
H3_NO_ERROR 0x0100 No error Section 8.1
H3_GENERAL_PROTOCOL_ERROR 0x0101 General protocol error Section 8.1
H3_INTERNAL_ERROR 0x0102 Internal error Section 8.1
H3_STREAM_CREATION_ERROR 0x0103 Stream creation error Section 8.1
H3_CLOSED_CRITICAL_STREAM 0x0104 Critical stream was closed Section 8.1
H3_FRAME_UNEXPECTED 0x0105 Frame not permitted in the current state Section 8.1
H3_FRAME_ERROR 0x0106 Frame violated layout or size rules Section 8.1
H3_EXCESSIVE_LOAD 0x0107 Peer generating excessive load Section 8.1
H3_ID_ERROR 0x0108 An identifier was used incorrectly Section 8.1
H3_SETTINGS_ERROR 0x0109 SETTINGS frame contained invalid values Section 8.1
H3_MISSING_SETTINGS 0x010a No SETTINGS frame received Section 8.1
H3_REQUEST_REJECTED 0x010b Request not processed Section 8.1
H3_REQUEST_CANCELLED 0x010c Data no longer needed Section 8.1
H3_REQUEST_INCOMPLETE 0x010d Stream terminated early Section 8.1
H3_MESSAGE_ERROR 0x010e Malformed message Section 8.1
H3_CONNECT_ERROR 0x010f TCP reset or error on CONNECT request Section 8.1
H3_VERSION_FALLBACK 0x0110 Retry over HTTP/1.1 Section 8.1

表 4: HTTP/3 の初期エラーコード

0x1f * N + 0x21 という形式で、非負の整数である N (つまり 0x21, 0x40, ..., ~ 0x3ffffffffffe) に対応する各コードは、IANA によって割り当てられてはならず、 割り当てられた値のリストにも掲載してはならない。

11.2.4. ストリームタイプ

本文書では、HTTP/3 の一方向性ストリームタイプのレジストリを確立します。HTTP/3 ストリームタイプ」レジストリは 62 ビットの空間を管理します。このレジストリはQUICのレジストリポリシーに従います(11.2項参照)。このレジストリの恒久的な登録は、Specification Requiredポリシー([RFC8126])に基づいて割り当てられます。ただし、0x00から0x3f(16進数)の間の値は、[RFC8126]のセクション4.9と4.10で定義されているように、Standards ActionまたはIESG Approvalを使用して割り当てられます。

セクション11.2に記載されている共通フィールドに加えて、このレジストリの永久登録は以下のフィールドを含まなければならない(MUST)。

ストリームタイプ。
ストリームタイプ: ストリームタイプの名前またはラベル。

Sender(送信者)。
HTTP/3接続上のどのエンドポイントが、このタイプのストリームを開始できるか。値は「Client」、「Server」、または「Both」です。

永久登録の仕様には、ストリームコンテンツのレイアウトやセマンティクスを含む、ストリームタイプの説明が含まれなければなりません(MUST)。

次の表のエントリは、本文書によって登録されたものである。

Stream Type Value Specification Sender
Control Stream 0x00 Section 6.2.1 Both
Push Stream 0x01 Section 4.4 Server

表5

0x1f * N + 0x21 という形式で、非負の整数である N (0x21, 0x40, ... ~ 0x3ffffffffffe) に対応する各コードは、IANA によって割り当てられてはならない。