メインコンテンツまでスキップ

RFC 9114 - HTTP/3

  • ステータス: Proposed Standard
  • 発行日: June 2022
  • ストリーム: IETF
  • エラッタ: エラッタなし

概要 (Abstract)​

QUICトランスポートプロトコル (QUIC Transport Protocol) は、ストリーム多重化 (Stream Multiplexing)、ストリームごとのフロー制御 (Per-Stream Flow Control)、低遅延接続確立 (Low-Latency Connection Establishment) など、HTTPトランスポートに望ましい複数の機能を持っています。本文書は、HTTPセマンティクスのQUIC上へのマッピングを記述します。本文書はまた、QUICによって包含されるHTTP/2機能を特定し、HTTP/2拡張をHTTP/3に移植する方法を説明します。


本メモのステータス (Status of This Memo)​

これはインターネット標準トラックドキュメントです。

本文書はインターネット技術タスクフォース (IETF) の成果物です。これはIETFコミュニティの合意を表しています。本文書は公開レビューを受け、インターネット技術運営グループ (IESG) によって発行が承認されました。インターネット標準に関する詳細情報は、RFC 7841のセクション2で入手できます。

本文書の現在のステータス、正誤表、フィードバック方法に関する情報は、https://www.rfc-editor.org/info/rfc9114 で入手できます。


目次 (Table of Contents)​

主要章​

附録​


関連リソース​



1. Introduction (はじめに)​

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

1.1. Prior Versions of HTTP (HTTPの以前のバージョン)​

HTTP/1.1 ([HTTP/1.1]) は、空白で区切られたテキストフィールドを使用してHTTPメッセージを伝達します。これらの交換は人間が読める形式ですが、メッセージのフォーマットに空白を使用すると、解析の複雑さと変異的な動作に対する過度の許容につながります。

HTTP/1.1には多重化レイヤー (Multiplexing Layer) が含まれていないため、複数のTCP接続がリクエストを並列処理するためによく使用されます。しかし、TCPは複数の接続間で輻輳制御 (Congestion Control) を共有しないため、これはネットワーク効率と輻輳制御に悪影響を及ぼします。

HTTP/2 ([HTTP/2]) は、トランスポート層を変更せずに遅延を改善するために、バイナリフレーミング (Binary Framing) と多重化レイヤーを導入しました。しかし、HTTP/2の多重化の並列性がTCPの損失回復メカニズム (Loss Recovery Mechanisms) に見えないため、失われたパケットまたは順序が変更されたパケットは、そのトランザクションがパケット損失によって直接影響を受けたかどうかに関係なく、すべてのアクティブなトランザクションが停止 (Stall) を経験する原因となります。

1.2. Delegation to QUIC (QUICへの委任)​

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

本文書は、HTTP/3を定義します。これは、QUICトランスポートプロトコル上でのHTTPセマンティクスのマッピングであり、HTTP/2の設計に大きく依存しています。HTTP/3は、データの機密性と完全性保護、ピア認証 (Peer Authentication)、および信頼性のある順序付きのストリームごとの配信を提供するためにQUICに依存しています。ストリームのライフタイム (Stream Lifetime) とフロー制御の問題をQUICに委任する一方で、各ストリームでHTTP/2フレーミングに類似したバイナリフレーミングが使用されます。一部のHTTP/2機能はQUICに包含され、他の機能はQUICの上に実装されます。

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



2. HTTP/3 Protocol Overview (HTTP/3プロトコル概要)​

HTTP/3は、QUICトランスポートプロトコル (QUIC Transport Protocol) とHTTP/2に類似した内部フレーミングレイヤー (Framing Layer) を使用して、HTTPセマンティクスのトランスポートを提供します。

クライアントが特定のエンドポイントにHTTP/3サーバーが存在することを知ると、QUIC接続を開きます。QUICは、プロトコルネゴシエーション (Protocol Negotiation)、ストリームベースの多重化 (Stream-Based Multiplexing)、およびフロー制御 (Flow Control) を提供します。HTTP/3エンドポイントの発見については、セクション3.1で説明されています。

各ストリーム内で、HTTP/3通信の基本単位はフレーム (Frame) です(セクション7.2)。各フレームタイプは異なる目的を果たします。たとえば、HEADERSおよびDATAフレームは、HTTPリクエストとレスポンスの基礎を形成します(セクション4.1)。接続全体に適用されるフレームは、専用の制御ストリーム (Control Stream) で伝達されます。

リクエストの多重化は、[QUIC-TRANSPORT] のセクション2で説明されているQUICストリーム抽象化 (Stream Abstraction) を使用して実行されます。各リクエスト-レスポンスペアは、単一のQUICストリームを消費します。ストリームは互いに独立しているため、ブロックされたりパケット損失を被ったりする1つのストリームが、他のストリームの進行を妨げることはありません。

サーバープッシュ (Server Push) は、HTTP/2 ([HTTP/2]) で導入されたインタラクションモードであり、クライアントが指定されたリクエストを行うことを予測して、サーバーがクライアントにリクエスト-レスポンス交換をプッシュすることを許可します。これは、ネットワーク使用量と潜在的なレイテンシ向上とのトレードオフです。PUSH_PROMISE、MAX_PUSH_ID、CANCEL_PUSHなど、複数のHTTP/3フレームがサーバープッシュの管理に使用されます。

HTTP/2と同様に、リクエストおよびレスポンスフィールド (Fields) は送信のために圧縮されます。HPACK ([HPACK]) は圧縮されたフィールドセクション (Field Sections) の順序付き送信に依存しているため(QUICが提供しない保証)、HTTP/3はHPACKをQPACK ([QPACK]) に置き換えます。QPACKは、個別の単方向ストリームを使用してフィールドテーブル状態 (Field Table State) を変更および追跡しますが、エンコードされたフィールドセクションはテーブルの状態を変更せずに参照します。

2.1. Document Organization (文書構成)​

以下のセクションでは、HTTP/3接続のライフサイクルの詳細な概要を提供します:

  • "Connection Setup and Management"(接続のセットアップと管理)(セクション3)は、HTTP/3エンドポイントがどのように発見され、HTTP/3接続がどのように確立されるかをカバーします。

  • "Expressing HTTP Semantics in HTTP/3"(HTTP/3でのHTTPセマンティクスの表現)(セクション4)は、フレームを使用してHTTPセマンティクスがどのように表現されるかを説明します。

  • "Connection Closure"(接続のクローズ)(セクション5)は、HTTP/3接続が正常にまたは突然終了する方法を説明します。

ワイヤプロトコル (Wire Protocol) とトランスポートとのインタラクションの詳細は、後続のセクションで説明されています:

  • "Stream Mapping and Usage"(ストリームマッピングと使用)(セクション6)は、QUICストリームの使用方法を説明します。

  • "HTTP Framing Layer"(HTTPフレーミングレイヤー)(セクション7)は、ほとんどのストリームで使用されるフレームを説明します。

  • "Error Handling"(エラー処理)(セクション8)は、特定のストリームまたは接続全体に対して、エラー条件がどのように処理および表現されるかを説明します。

最後のセクションでは追加のリソースが提供されます:

  • "Extensions to HTTP/3"(HTTP/3の拡張)(セクション9)は、将来の文書で新しい機能を追加する方法を説明します。

  • HTTP/2とHTTP/3のより詳細な比較は、付録Aにあります。

2.2. Conventions and Terminology (規約と用語)​

本文書のキーワード "MUST"(しなければならない)、"MUST NOT"(してはならない)、"REQUIRED"(必須である)、"SHALL"(しなければならない)、"SHALL NOT"(してはならない)、"SHOULD"(すべきである)、"SHOULD NOT"(すべきでない)、"RECOMMENDED"(推奨される)、"NOT RECOMMENDED"(推奨されない)、"MAY"(してもよい)、および "OPTIONAL"(任意である)は、BCP 14 [RFC2119] [RFC8174] に記載されているように解釈されるものとし、ここに示すようにすべて大文字で表示される場合に限ります。

本文書は、[QUIC-TRANSPORT] の可変長整数エンコーディング (Variable-Length Integer Encoding) を使用します。

以下の用語が使用されます:

abort(中止): 接続またはストリームの突然の終了。エラー条件が原因である可能性があります。

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

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

connection error(接続エラー): HTTP/3接続全体に影響を与えるエラー。

endpoint(エンドポイント): 接続のクライアントまたはサーバー。

frame(フレーム): HTTP/3のストリーム上の通信の最小単位。ヘッダーとフレームタイプに従って構造化された可変長バイトシーケンスで構成されます。

"フレーム"と呼ばれるプロトコル要素は、本文書と [QUIC-TRANSPORT] の両方に存在します。[QUIC-TRANSPORT] のフレームが参照される場合、フレーム名には"QUIC"というプレフィックスが付けられます。たとえば、"QUIC CONNECTION_CLOSE frames"。このプレフィックスのない参照は、セクション7.2で定義されたフレームを指します。

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

peer(ピア): エンドポイント。特定のエンドポイントについて議論する場合、"peer"は議論の主題からリモートのエンドポイントを指します。

receiver(受信者): フレームを受信しているエンドポイント。

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

server(サーバー): HTTP/3接続を受け入れるエンドポイント。サーバーはHTTPリクエストを受信し、HTTPレスポンスを送信します。

stream(ストリーム): QUICトランスポートによって提供される双方向または単方向のバイトストリーム (Bytestream)。HTTP/3接続内のすべてのストリームは"HTTP/3ストリーム"と見なすことができますが、HTTP/3内では複数のストリームタイプが定義されています。

stream error(ストリームエラー): 個々のストリームのアプリケーションレベルエラー。

"content"(コンテンツ)という用語は、[HTTP] のセクション6.4で定義されています。

最後に、"resource"(リソース)、"message"(メッセージ)、"user agent"(ユーザーエージェント)、"origin server"(オリジンサーバー)、"gateway"(ゲートウェイ)、"intermediary"(中継者)、"proxy"(プロキシ)、および "tunnel"(トンネル)という用語は、[HTTP] のセクション3で定義されています。

本文書のパケット図 (Packet Diagrams) は、フィールドの順序とサイズを示すために、[QUIC-TRANSPORT] のセクション1.3で定義された形式を使用します。



3. Connection Setup and Management (接続のセットアップと管理)​

3.1. Discovering an HTTP/3 Endpoint (HTTP/3エンドポイントの発見)​

HTTPは、権威的な応答 (Authoritative Response) の概念に依存しています。これは、応答メッセージの発信時に、ターゲットURIで識別されるオリジンサーバー(またはその指示の下で)によって決定されたターゲットリソースの状態に対して、そのリクエストに最も適切な応答であると判断された応答です。HTTP URIの権威サーバーの特定については、[HTTP] のセクション4.3で説明されています。

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

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

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

サーバーは任意のUDPポートでHTTP/3を提供してもよいです (MAY)。代替サービスアドバタイズメント (Alternative Service Advertisement) には常に明示的なポートが含まれ、URIには明示的なポートまたはスキームに関連付けられたデフォルトポートが含まれます。

3.1.1. HTTP Alternative Services (HTTP代替サービス)​

HTTPオリジン (Origin) は、Alt-Svc HTTPレスポンスヘッダーフィールドまたはHTTP/2 ALTSVCフレーム ([ALTSVC]) を使用して、"h3" ALPNトークンを使用することで、同等のHTTP/3エンドポイントの可用性をアドバタイズできます。

たとえば、オリジンは、同じホスト名のUDPポート50781でHTTP/3が利用可能であることを、次のヘッダーフィールドを含めることでHTTPレスポンスで示すことができます:

Alt-Svc: h3=":50781"

HTTP/3サポートを示すAlt-Svcレコードを受信すると、クライアントは指定されたホストとポートへのQUIC接続の確立を試みてもよいです (MAY)。この接続が成功した場合、クライアントは本文書で説明されているマッピングを使用してHTTPリクエストを送信できます。

3.1.2. Other Schemes (その他のスキーム)​

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

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

3.2. Connection Establishment (接続の確立)​

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

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

QUIC接続は、[QUIC-TRANSPORT] で説明されているように確立されます。接続確立中に、TLSハンドシェイクでALPNトークン"h3"を選択することにより、HTTP/3サポートが示されます。同じハンドシェイクで他のアプリケーション層プロトコルのサポートが提供されてもよいです (MAY)。

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

3.3. Connection Reuse (接続の再利用)​

HTTP/3接続は、複数のリクエストにわたって永続的です。最高のパフォーマンスを得るために、クライアントは、サーバーとのさらなる通信が不要であると判断されるまで(例えば、ユーザーが特定のウェブページから移動したとき)、またはサーバーが接続を閉じるまで、接続を閉じないことが期待されます。

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

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

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

サーバーは、可能な限り長くHTTP/3接続を開いたままにすることが推奨されますが、必要に応じてアイドル接続 (Idle Connections) を終了することが許可されています。いずれかのエンドポイントがHTTP/3接続を閉じることを選択した場合、終了するエンドポイントは、まずGOAWAYフレーム(セクション5.2)を送信すべきです (SHOULD)。これにより、両方のエンドポイントが、以前に送信されたフレームが処理されたかどうかを確実に判断し、必要な残りのタスクを正常に完了または終了できます。

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



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メッセージ(リクエストまたは応答)は次の要素で構成されます:

  1. ヘッダーセクション (Header Section)、メッセージ制御データを含み、単一のHEADERSフレームとして送信されます。

  2. オプションで、コンテンツ (Content)(存在する場合)、一連のDATAフレームとして送信されます。および

  3. オプションで、トレーラーセクション (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)。


5. 接続のクローズ (Connection Closure)​

確立されると、HTTP/3接続は、接続が閉じられるまで、時間の経過とともに多くのリクエストとレスポンスに使用できます。接続のクローズは、いくつかの異なる方法で発生する可能性があります。

5.1. アイドル接続 (Idle Connections)​

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

HTTPクライアントは、[QUIC-TRANSPORT]のセクション10.1.2で説明されているように、リクエストまたはサーバープッシュの未処理のレスポンスがある間、トランスポートが接続を開いたままにすることを要求することが期待されます。クライアントがサーバーからのレスポンスを期待していない場合、必要ないかもしれない接続を維持するために労力を費やすよりも、アイドル接続をタイムアウトさせることが望ましいです。ゲートウェイは、サーバーへの接続確立の遅延コストを負担するのではなく、必要性を見越して接続を維持してもかまいません (MAY)。サーバーは積極的に接続を開いたままにすべきではありません (SHOULD NOT)。

5.2. 接続のシャットダウン (Connection Shutdown)​

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

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

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

一部のリクエストまたはプッシュはすでに転送中である可能性があります:

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

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

    これらのリクエストが処理されなかった場合、サーバーは指定されたID以下のストリーム上の個々のリクエストを拒否してもかまいません (MAY)。

  • サーバーが、GOAWAYフレームに含まれる識別子以上のプッシュIDを持つプッシュを約束した後にGOAWAYフレームを受信した場合、それらのプッシュは受け入れられません。

接続のクローズが事前にわかっている場合、サーバーはGOAWAYフレームを送信すべきです (SHOULD)。事前通知が少ない場合でも、リモートピアはリクエストが部分的に処理されたかどうかを知ることができます。たとえば、HTTPクライアントがPOSTを送信すると同時にサーバーがQUIC接続を閉じた場合、サーバーが動作した可能性のあるストリームを示すGOAWAYフレームを送信しない場合、クライアントはサーバーがそのPOSTリクエストの処理を開始したかどうかを知ることができません。

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

グレースフルに接続をシャットダウンしようとしているエンドポイントは、最大可能値(サーバーの場合は2^62-4、クライアントの場合は2^62-1)に設定された値を持つGOAWAYフレームを送信できます。これにより、ピアが新しいリクエストまたはプッシュの作成を停止することが保証されます。転送中のリクエストまたはプッシュが到着する時間を許可した後、エンドポイントは、接続の終了前に受け入れる可能性のあるリクエストまたはプッシュを示す別のGOAWAYフレームを送信できます。これにより、リクエストを失うことなく接続をクリーンにシャットダウンできることが保証されます。

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

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

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

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

5.3. 即時アプリケーションクローズ (Immediate Application Closure)​

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

接続を閉じる前に、クライアントが一部のリクエストを再試行できるようにするために、GOAWAYフレームを送信してもかまいません (MAY)。QUIC CONNECTION_CLOSEフレームと同じパケットにGOAWAYフレームを含めることで、クライアントがフレームを受信する可能性が向上します。

明示的に閉じられていない開いているストリームがある場合、接続が閉じられるときに暗黙的に閉じられます。[QUIC-TRANSPORT]のセクション10.2を参照してください。

5.4. トランスポートクローズ (Transport Closure)​

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

GOAWAYフレームなしで接続が終了した場合、クライアントは、送信されたリクエスト(完全または部分的)が処理された可能性があると想定しなければなりません。


6. ストリームマッピングと使用 (Stream Mapping and Usage)​

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

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

HTTPフィールドとデータがQUICを介して送信される場合、QUIC層はストリーム管理のほとんどを処理します。QUICを使用する場合、HTTPは個別の多重化を行う必要はありません。QUICストリームを介して送信されるデータは、常に特定のHTTPトランザクションまたはHTTP/3接続コンテキスト全体にマップされます。

6.1. 双方向ストリーム (Bidirectional Streams)​

すべてのクライアントが開始した双方向ストリームは、HTTPリクエストとレスポンスに使用されます。双方向ストリームにより、レスポンスをリクエストと容易に関連付けることができます。これらのストリームはリクエストストリーム (Request Streams) と呼ばれます。

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

HTTP/3はサーバーが開始した双方向ストリームを使用しませんが、拡張機能がこれらのストリームの用途を定義する可能性があります。クライアントは、そのような拡張機能がネゴシエートされていない限り、サーバーが開始した双方向ストリームの受信をH3_STREAM_CREATION_ERRORタイプの接続エラー (Connection Error) として扱わなければなりません (MUST)。

6.2. 単方向ストリーム (Unidirectional Streams)​

いずれかの方向の単方向ストリームは、さまざまな目的に使用されます。目的はストリームタイプ (Stream Type) によって示され、ストリームの開始時に可変長整数として送信されます。この整数に続くデータのフォーマットと構造は、ストリームタイプによって決定されます。

Unidirectional Stream Header {
Stream Type (i),
}

図1:単方向ストリームヘッダー

このドキュメントでは2つのストリームタイプが定義されています:コントロールストリーム (Control Streams)(セクション6.2.1)とプッシュストリーム (Push Streams)(セクション6.2.2)。[QPACK]は2つの追加のストリームタイプを定義しています。他のストリームタイプは、HTTP/3の拡張機能によって定義できます。詳細については、セクション9を参照してください。一部のストリームタイプは予約されています(セクション6.2.3)。

HTTP/3接続のライフタイムの初期段階におけるパフォーマンスは、単方向ストリームでのデータの作成と交換に敏感です。これらのストリームの数やフロー制御ウィンドウを過度に制限するエンドポイントは、リモートピアが早期に制限に達してブロックされる可能性を高めます。特に、実装は、リモートピアが使用を許可されている単方向ストリームの一部で予約ストリーム動作(セクション6.2.3)を行使したい場合があることを考慮すべきです。

各エンドポイントは、HTTPコントロールストリーム用に少なくとも1つの単方向ストリームを作成する必要があります。QPACKには2つの追加の単方向ストリームが必要であり、他の拡張機能にはさらにストリームが必要な場合があります。したがって、クライアントとサーバーの両方が送信するトランスポートパラメータは、ピアが少なくとも3つの単方向ストリームを作成できるようにしなければなりません (MUST)。これらのトランスポートパラメータは、各単方向ストリームに少なくとも1,024バイトのフロー制御クレジットを提供すべきです (SHOULD)。

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

ストリームヘッダーが受信者によってサポートされていないストリームタイプを示す場合、セマンティクスが不明であるため、ストリームの残りを消費できません。未知のストリームタイプの受信者は、ストリームの読み取りを中止するか、さらなる処理なしで受信データを破棄しなければなりません (MUST)。読み取りが中止された場合、受信者はH3_STREAM_CREATION_ERRORエラーコードまたは予約エラーコード(セクション8.1)を使用すべきです (SHOULD)。受信者は、未知のストリームタイプをいかなる種類の接続エラーとも見なしてはなりません (MUST NOT)。

特定のストリームタイプは接続状態に影響を与える可能性があるため、受信者は、ストリームタイプを読み取る前に受信単方向ストリームからのデータを破棄すべきではありません (SHOULD NOT)。

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

別段の規定がない限り、送信者は単方向ストリームを閉じるかリセットできます。受信者は、単方向ストリームヘッダーの受信前に単方向ストリームが閉じられたりリセットされたりすることを許容しなければなりません (MUST)。

6.2.1. コントロールストリーム (Control Streams)​

コントロールストリームは、ストリームタイプ0x00によって示されます。このストリーム上のデータは、セクション7.2で定義されているHTTP/3フレームで構成されます。

各側は、接続の開始時に単一のコントロールストリームを開始し、このストリームの最初のフレームとしてSETTINGSフレームを送信しなければなりません (MUST)。コントロールストリームの最初のフレームが他のフレームタイプである場合、これはH3_MISSING_SETTINGSタイプの接続エラーとして扱わなければなりません (MUST)。ピアごとに1つのコントロールストリームのみが許可されます。コントロールストリームであると主張する2番目のストリームを受信することは、H3_STREAM_CREATION_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。送信者はコントロールストリームを閉じてはならず (MUST NOT)、受信者は送信者にコントロールストリームを閉じるよう要求してはなりません (MUST NOT)。いずれかのコントロールストリームが任意の時点で閉じられた場合、これはH3_CLOSED_CRITICAL_STREAMタイプの接続エラーとして扱わなければなりません (MUST)。接続エラーはセクション8で説明されています。

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

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

6.2.2. プッシュストリーム (Push Streams)​

サーバープッシュ (Server Push) は、HTTP/2で導入されたオプション機能で、リクエストが行われる前にサーバーがレスポンスを開始できるようにします。詳細については、セクション4.6を参照してください。

プッシュストリームは、ストリームタイプ0x01によって示され、その後に、可変長整数としてエンコードされた、それが履行する約束のプッシュID (Push ID) が続きます。このストリーム上の残りのデータは、セクション7.2で定義されているHTTP/3フレームで構成され、セクション4.1で定義されているように、0個以上の暫定HTTPレスポンスに続いて単一の最終HTTPレスポンスによって約束されたサーバープッシュを履行します。サーバープッシュとプッシュIDはセクション4.6で説明されています。

サーバーのみがプッシュできます。サーバーがクライアントが開始したプッシュストリームを受信した場合、これはH3_STREAM_CREATION_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。

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

図2:プッシュストリームヘッダー

クライアントは、プッシュストリームヘッダーを読み取る前にプッシュストリームの読み取りを中止すべきではありません (SHOULD NOT)。これにより、どのプッシュIDがすでに消費されたかについて、クライアントとサーバーの間で意見の相違が生じる可能性があるためです。

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

6.2.3. 予約ストリームタイプ (Reserved Stream Types)​

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

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


7. HTTPフレーミング層 (HTTP Framing Layer)​

HTTPフレームは、セクション6で説明されているように、QUICストリーム上で運ばれます。HTTP/3は3つのストリームタイプを定義します:コントロールストリーム、リクエストストリーム、およびプッシュストリーム。このセクションでは、HTTP/3フレーム形式とそれらの許可されたストリームタイプについて説明します。概要については表1を参照してください。

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

フレームコントロールストリームリクエストストリームプッシュストリームセクション
DATA否是是7.2.1
HEADERS否是是7.2.2
CANCEL_PUSH是否否7.2.3
SETTINGS是(1)否否7.2.4
PUSH_PROMISE否是否7.2.5
GOAWAY是否否7.2.6
MAX_PUSH_ID是否否7.2.7
Reserved是是是7.2.8

SETTINGSフレームはコントロールストリームの最初のフレームとしてのみ発生できます。これは表1で(1)で示されています。

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

7.1. フレームレイアウト (Frame Layout)​

すべてのフレームは次の形式を持ちます:

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

フレームには次のフィールドが含まれます:

  • Type(タイプ):フレームタイプを識別する可変長整数
  • Length(長さ):フレームペイロードのバイト長を記述する可変長整数
  • Frame Payload(フレームペイロード):Typeフィールドによって決定されるセマンティクスを持つペイロード

各フレームのペイロードは、その説明で識別されたフィールドを正確に含まなければなりません (MUST)。追加のバイトを含むまたは早期に終了するフレームペイロードは、H3_FRAME_ERRORタイプの接続エラーとして扱わなければなりません (MUST)。

7.2. フレーム定義 (Frame Definitions)​

7.2.1. DATA​

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

DATAフレームはHTTPリクエストまたはレスポンスに関連付けられている必要があります (MUST)。コントロールストリームでDATAフレームを受信した場合、受信者はH3_FRAME_UNEXPECTEDタイプの接続エラーで応答しなければなりません (MUST)。

7.2.2. HEADERS​

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

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

7.2.3. CANCEL_PUSH​

CANCEL_PUSHフレーム(type=0x03)は、プッシュストリームを受信する前にサーバープッシュのキャンセルを要求するために使用されます。

クライアントがCANCEL_PUSHフレームを送信するとき、約束されたリソースを受信したくないことを示しています。サーバーはリソースの送信を中止すべきです (SHOULD)。

CANCEL_PUSHフレームはコントロールストリームで送信されます。リクエストストリームまたはプッシュストリームでCANCEL_PUSHフレームを受信することは、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱わなければなりません (MUST)。

7.2.4. SETTINGS​

SETTINGSフレーム(type=0x04)は、エンドポイントがどのように通信するかに影響を与える設定パラメータを伝達します。

SETTINGSフレームは、各コントロールストリームの最初のフレームとして送信されなければなりません (MUST)。SETTINGSフレームは他のストリームで送信してはなりません (MUST NOT)。

定義された設定識別子:

  • SETTINGS_MAX_FIELD_SECTION_SIZE (0x06):フィールドセクションの最大サイズ
  • SETTINGS_QPACK_MAX_TABLE_CAPACITY (0x01):QPACK関連設定
  • SETTINGS_QPACK_BLOCKED_STREAMS (0x07):QPACK関連設定

7.2.5. PUSH_PROMISE​

PUSH_PROMISEフレーム(type=0x05)は、リクエストストリームでサーバーからクライアントへ約束されたリクエストヘッダーフィールドセクションを運ぶために使用されます。

PUSH_PROMISEフレームはリクエストストリームでのみ送信できます。コントロールストリームまたはプッシュストリームでPUSH_PROMISEフレームを受信することは、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱わなければなりません (MUST)。

7.2.6. GOAWAY​

GOAWAYフレーム(type=0x07)は、接続のグレースフルシャットダウンを開始するために使用されます。

GOAWAYフレームは常にコントロールストリームで送信されます。リクエストストリームまたはプッシュストリームでGOAWAYフレームを受信することは、H3_FRAME_UNEXPECTEDタイプの接続エラーとして扱わなければなりません (MUST)。

7.2.7. MAX_PUSH_ID​

MAX_PUSH_IDフレーム(type=0x0d)は、クライアントがサーバーが開始できるサーバープッシュの数を制御するために使用されます。

MAX_PUSH_IDフレームは常にコントロールストリームで送信されます。サーバーはMAX_PUSH_IDフレームを送信してはなりません (MUST NOT)。

7.2.8. 予約フレームタイプ (Reserved Frame Types)​

形式0x1f * N + 0x21(Nは非負整数)のフレームタイプは、未知のタイプを無視する要件を行使するために予約されています。これらのフレームにはセマンティクスがなく、任意のストリームで送信できます。


8. エラー処理 (Error Handling)​

ストリームが正常に完了できない場合、QUICはアプリケーションがそのストリームを突然終了(リセット)し、理由を伝達することを許可します。これは「ストリームエラー (Stream Error)」と呼ばれます。HTTP/3実装は、QUICストリームを閉じてエラーのタイプを伝達することを決定できます。エラーコードのワイヤエンコーディングはセクション8.1で定義されています。ストリームエラーは、エラー条件を示すHTTPステータスコードとは異なります。ストリームエラーは、送信者が完全なリクエストまたはレスポンスを転送または消費しなかったことを示し、HTTPステータスコードは正常に受信されたリクエストの結果を示します。

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

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

特定の状況下で、エンドポイントはストリームエラーを接続エラーとして扱うことを選択できます (MAY)。この選択を行う前に、実装は未完了のリクエストへの影響を考慮する必要があります。

新しいエラーコードは交渉なしで定義できるため(セクション9参照)、予期しないコンテキストでのエラーコードの使用または未知のエラーコードの受信は、H3_NO_ERRORと同等として扱わなければなりません (MUST)。ただし、ストリームを閉じると、エラーコードに関係なく他の影響が生じる可能性があります。たとえば、セクション4.1を参照してください。

8.1. HTTP/3エラーコード (HTTP/3 Error Codes)​

以下のエラーコードは、ストリームを突然終了する、ストリームの読み取りを中止する、または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が不正に使用されました(制限を超える、制限を減らす、再利用するなど)。

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で再試行する必要があります。

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


9. HTTP/3への拡張 (Extensions to 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)。


10. セキュリティに関する考慮事項​

HTTP/3 のセキュリティに関する考慮事項は、TLS を伴う HTTP/2 のものと同等であるべきである。ただし、[HTTP/2] の 10 節にある考慮事項の多くは [QUIC-TRANSPORT] に適用され、同文書で扱われている。

10.1. サーバの権威​

HTTP/3 は HTTP における権威の定義に依存する。権威を確立する際のセキュリティに関する考慮事項は、[HTTP] の 17.1 節で扱われる。

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

TLS および QUIC のハンドシェイクで ALPN を使用すると、アプリケーション層のバイトを処理する前に、対象のアプリケーションプロトコルが確立される。これにより、エンドポイントはピアが同じプロトコルを使用していることについて強い保証を得る。

これはすべてのクロスプロトコル攻撃を防ぐ保証にはならない。[QUIC-TRANSPORT] の 21.5 節では、QUIC パケットの平文が、認証済みトランスポートを使用しないエンドポイントに対するリクエスト偽造に使用される可能性のある方法を説明している。

10.3. 中継者カプセル化攻撃​

HTTP/3 のフィールド符号化では、HTTP で使用される構文では無効なフィールド名を表現できる。[HTTP] の 5.1 節を参照。無効なフィールド名を含むリクエストまたはレスポンスは、不正な形式として扱わなければならない。

同様に、HTTP/3 は無効なフィールド値を転送できる。符号化可能な値の大半はフィールド解析を変えないが、復帰文字(ASCII 0x0d)、改行文字(ASCII 0x0a)、およびヌル文字(ASCII 0x00)は、逐語的に変換されると攻撃者に悪用される可能性がある。

10.4. プッシュされたレスポンスのキャッシュ可能性​

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

複数のテナントが同じサーバ上で領域を共有する場合、サーバはテナントが権限のないリソースの表現をプッシュできないようにしなければならない。

10.5. サービス拒否に関する考慮事項​

HTTP/3 接続は、HTTP/1.1 または HTTP/2 接続よりも、動作のために大きなリソースの割り当てを必要とする場合がある。

送信側が、ピアが無視する必要のある未定義のプロトコル要素を送信できる機能は悪用され、ピアに追加の処理時間を費やさせる可能性がある。

このような動作を監視しないエンドポイントは、サービス拒否攻撃のリスクにさらされる。実装はこれらの機能の使用を追跡し、その使用に制限を設けるべきである。

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

大きなフィールドセクション(4.1 節)は、実装が大量の状態を保持する原因となる可能性がある。エンドポイントは、フィールドセクションサイズに適用する可能性がある制限をピアに通知するため、SETTINGS_MAX_FIELD_SECTION_SIZE(4.2.2 節)設定を使用できる。

10.5.2. CONNECT の問題​

CONNECT メソッドは、TCP 接続を作成・維持することに比べてストリームの作成が比較的安価なため、プロキシに不釣り合いな負荷を発生させるために使用できる。

10.6. 圧縮の使用​

攻撃者が制御するデータと同じコンテキストで機密データを圧縮すると、圧縮により攻撃者が機密データを復元できる可能性がある。HTTP/3 はフィールド圧縮を有効にする(4.2 節)。

セキュアチャネル上で通信する実装は、データソースごとに別々の圧縮コンテキストを使用しない限り、機密データと攻撃者が制御するデータを含むコンテンツを圧縮してはならない。

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

パディングは、フレーム内容の正確なサイズを曖昧にし、HTTP 内の特定の攻撃を緩和するために使用できる。

10.8. フレーム解析​

複数のプロトコル要素には入れ子になった長さ要素が含まれる。実装は、フレームの長さが含まれるフィールドの長さと正確に一致することを保証しなければならない。

10.9. 早期データ​

HTTP/3 で 0-RTT を使用すると、リプレイ攻撃のリスクが生じる。0-RTT を伴う HTTP/3 を使用する場合は、[HTTP-REPLAY] のリプレイ攻撃緩和策を適用しなければならない。

10.10. マイグレーション​

一部の HTTP 実装は、ロギングまたはアクセス制御にクライアントアドレスを使用する。QUIC クライアントのアドレスは接続中に変わる場合があるため、このような実装はクライアントの現在のアドレスを積極的に取得するか、元のアドレスが変わり得ることを明示的に受け入れる必要がある。

10.11. プライバシーに関する考慮事項​

HTTP/3 の複数の機能は、観測者に対し、単一のクライアントまたはサーバの操作を時系列で関連付ける機会を与える。これには設定値、刺激に対する応答時間、および設定により制御される機能の処理が含まれる。

HTTP/3 が単一の QUIC 接続を優先して使用することにより、ユーザのサイト上での活動を関連付けることができる。


11. IANA に関する考慮事項​

本書は新たな ALPN プロトコル ID を登録し(11.1 節)、HTTP/3 におけるコードポイントの割り当てを管理する新しいレジストリを作成する。

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

本書は、[RFC7301] で作成された「TLS 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)」の見出しの下にまとめられる。

これらのレジストリにおける初期割り当てはすべて permanent 状態に指定され、変更管理者として IETF、連絡先として HTTP ワーキンググループ([email protected])が記載される。

11.2.1. フレームタイプ​

本書は HTTP/3 フレームタイプコード用のレジストリを作成する。「HTTP/3 Frame Types」レジストリは 62 ビットの空間を管理する。

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

フレームタイプ値仕様
DATA0x007.2.1 節
HEADERS0x017.2.2 節
予約済み0x02本書
CANCEL_PUSH0x037.2.3 節
SETTINGS0x047.2.4 節
PUSH_PROMISE0x057.2.5 節
予約済み0x06本書
GOAWAY0x077.2.6 節
MAX_PUSH_ID0x0d7.2.7 節

11.2.2. 設定パラメータ​

本書は HTTP/3 設定用のレジストリを作成する。「HTTP/3 Settings」レジストリは 62 ビットの空間を管理する。

表 3: 初期 HTTP/3 設定

設定名値仕様既定値
MAX_FIELD_SECTION_SIZE0x064.2.2 節無制限

11.2.3. エラーコード​

本書は HTTP/3 エラーコード用のレジストリを作成する。「HTTP/3 Error Codes」レジストリは 62 ビットの空間を管理する。

本書で登録されるエントリは 8.1 節に示される。

11.2.4. ストリームタイプ​

本書は HTTP/3 の単方向ストリームタイプ用のレジストリを作成する。「HTTP/3 Stream Types」レジストリは 62 ビットの空間を管理する。

表 5: 初期 HTTP/3 ストリームタイプ

ストリームタイプ値仕様送信者
制御ストリーム0x006.2.1 節両方
プッシュストリーム0x014.6 節サーバ

付録A. HTTP/2からの移行に関する考慮事項 (Considerations for Transitioning from HTTP/2)​

HTTP/3はHTTP/2の設計に基づいており、コアセマンティクスを共有しています。この付録は、HTTP/2からHTTP/3への主な違いを要約し、実装者が2つのプロトコル間の関係を理解するのに役立ちます。

A.1. ストリーム (Streams)​

HTTP/3はQUICストリームを使用しますが、HTTP/2はTCP上のストリーム抽象化を使用します。主な違い:

  • ストリーム識別子:HTTP/3のストリームIDはQUICによって割り当てられ、HTTP/3によっては割り当てられません
  • ストリーム優先順位:HTTP/3はHTTP/2のストリーム優先順位スキームを含みません
  • フロー制御:HTTP/3はQUICのフロー制御メカニズムを使用します

A.2. HTTPフレームタイプ (HTTP Frame Types)​

多くのHTTP/2フレームタイプはHTTP/3で保持または変更されています:

保持されたフレームタイプ:

  • DATA(0x00)- 機能は類似
  • HEADERS(0x01)- 機能は類似
  • SETTINGS(0x04)- 機能は類似だがコントロールストリームのみ
  • PUSH_PROMISE(0x05)- 機能は類似
  • GOAWAY(0x07)- 機能は類似

削除または置換されたHTTP/2フレームタイプ:

  • PRIORITY(0x02)- HTTP/3で削除
  • RST_STREAM(0x03)- QUICのRESET_STREAMで置換
  • PING(0x06)- QUICのPINGフレームで置換
  • WINDOW_UPDATE(0x08)- QUICのフロー制御で置換
  • CONTINUATION(0x09)- HTTP/3では不要

HTTP/3で新しいフレームタイプ:

  • CANCEL_PUSH(0x03)- サーバープッシュをキャンセル
  • MAX_PUSH_ID(0x0d)- プッシュIDスペースを制御

A.3. HTTP/2設定パラメータ (HTTP/2 SETTINGS Parameters)​

HTTP/3の設定はHTTP/2とは異なります:

削除された設定:

  • SETTINGS_HEADER_TABLE_SIZE - QPACK設定で置換
  • SETTINGS_ENABLE_PUSH - MAX_PUSH_IDで制御
  • SETTINGS_MAX_CONCURRENT_STREAMS - QUICトランスポートパラメータで制御
  • SETTINGS_INITIAL_WINDOW_SIZE - QUICフロー制御で置換
  • SETTINGS_MAX_FRAME_SIZE - HTTP/3では不要
  • SETTINGS_MAX_HEADER_LIST_SIZE - SETTINGS_MAX_FIELD_SECTION_SIZEで置換

保持された設定:

  • SETTINGS_MAX_FIELD_SECTION_SIZE(0x06)- HTTP/2のSETTINGS_MAX_HEADER_LIST_SIZEに類似

A.4. HTTP/2エラーコード (HTTP/2 Error Codes)​

HTTP/3は、HTTP/2のエラーコードとは異なる独自のエラーコードセットを定義しています。実装者はマッピング関係に注意する必要がありますが、直接的な1対1の対応があると仮定すべきではありません。

A.5. その他の違い (Other Differences)​

接続管理:

  • HTTP/3は、接続マイグレーションやマルチパスサポートを含むQUICの接続管理を使用します
  • HTTP/2の接続プリアンブルは不要です

サーバープッシュ:

  • HTTP/3のサーバープッシュメカニズムはHTTP/2と類似していますが、異なるフレームとストリームタイプを使用します
  • プッシュIDはHTTP/3で明示的です

フィールド圧縮:

  • HTTP/3はHPACKではなくQPACKを使用します
  • QPACKは順序なし配信を処理するように設計されています

拡張性:

  • HTTP/3はより柔軟な拡張メカニズムを提供します
  • 新しいフレームタイプ、設定、ストリームタイプは交渉なしで使用できます