HTTP/3
Extracted elements (32)
A pair of unidirectional streams is used for the control channel rather than a single bidirectional stream, allowing either peer to send data as soon as it is able. Depending on whether 0-RTT is available, either client or server might be able to send stream data first.
HTTP/3 uses QUIC stream multiplexing directly rather than adding its own multiplexing layer. Because QUIC provides per-stream reliability and connection-wide congestion control, head-of-line blocking across streams caused by TCP packet loss in HTTP/2 is eliminated.
HTTP/3 does not support the HTTP Upgrade mechanism or the 101 (Switching Protocols) status code. The CONNECT method is supported but operates over a single QUIC stream rather than converting an entire connection into a tunnel as in HTTP/1.x.
HTTP/3 replaces HPACK with QPACK for header compression because HPACK requires in-order delivery of compressed field sections, a guarantee QUIC does not provide. QPACK uses separate unidirectional streams to modify and track field table state while encoded field sections only reference, not modify, the table.
A client MUST treat receipt of a server-initiated bidirectional stream as a connection error of type H3_STREAM_CREATION_ERROR unless an extension has been negotiated. Only servers can push; a server receiving a client-initiated push stream MUST treat it as a connection error of type H3_STREAM_CREATION_ERROR.
After the QUIC connection is established, a SETTINGS frame MUST be sent by each endpoint as the initial frame of their respective HTTP control stream. Each side MUST initiate a single control stream; receipt of a second control stream MUST be treated as a connection error of type H3_STREAM_CREATION_ERROR.
All HTTP/3 requests MUST include exactly one value for the :method, :scheme, and :path pseudo-header fields unless the request is a CONNECT request. The :status pseudo-header field MUST be included in all responses; otherwise the response is malformed.
Each push ID MUST only be used once in a push stream header. A client detecting that a push stream header includes a push ID used in another push stream header MUST treat this as a connection error of type H3_ID_ERROR. A MAX_PUSH_ID frame cannot reduce the maximum push ID.
Endpoints MUST NOT initiate new requests or promise new pushes on the connection after receipt of a GOAWAY frame from the peer. The identifier in each successive GOAWAY frame MUST NOT be greater than any previously sent identifier; a larger identifier MUST be treated as a connection error of type H3_ID_ERROR.
Malformed requests or responses detected by intermediaries MUST NOT be forwarded; they MUST be treated as a stream error of type H3_MESSAGE_ERROR. Clients MUST NOT accept a malformed response.
Receipt of an invalid sequence of HTTP/3 frames MUST be treated as a connection error of type H3_FRAME_UNEXPECTED. In particular, a DATA frame before any HEADERS frame, or a HEADERS or DATA frame after the trailing HEADERS frame, is considered invalid.
The sender MUST NOT close the control stream, and the receiver MUST NOT request that the sender close the control stream. If either control stream is closed at any point, this MUST be treated as a connection error of type H3_CLOSED_CRITICAL_STREAM.
The Transfer-Encoding header field MUST NOT be used in HTTP/3. Connection-specific header fields MUST NOT be generated; any message containing them MUST be treated as malformed. Field names MUST be converted to lowercase prior to encoding; uppercase field names MUST be treated as malformed.
Transport parameters sent by both clients and servers MUST allow the peer to create at least three unidirectional streams, and SHOULD also provide at least 1,024 bytes of flow-control credit to each unidirectional stream to accommodate the control stream and QPACK encoder/decoder streams.
Unless some other mechanism is used to select HTTP/3, the token 'h3' MUST be used in the ALPN extension during the TLS handshake. HTTP/3 clients MUST support a mechanism to indicate the target host; if the server is identified by a domain name, clients MUST send the SNI TLS extension.
When using 0-RTT QUIC, a client MUST comply with stored server settings (or default values if none stored). If a server accepts 0-RTT but then sends a SETTINGS frame that reduces limits or omits previously non-default values, this MUST be treated as a connection error of type H3_SETTINGS_ERROR.
Padding (via reserved frame types and reserved stream types) can be used to obscure the length of HTTP messages and mitigate traffic analysis. However, padding alone does not fully protect against traffic analysis; implementations SHOULD consider its limitations.
DATA frames (type=0x00) convey arbitrary byte sequences for HTTP request or response content. They MUST be associated with a request or response stream; receipt on a control stream is a connection error of type H3_FRAME_UNEXPECTED.
HEADERS frames (type=0x01) carry QPACK-encoded HTTP field sections. They can only be sent on request streams or push streams; receipt on a control stream is a connection error of type H3_FRAME_UNEXPECTED.
HTTP/3 error codes are defined for use when resetting streams or closing connections. Key codes include H3_NO_ERROR (0x0100), H3_GENERAL_PROTOCOL_ERROR (0x0101), H3_FRAME_UNEXPECTED (0x0105), H3_ID_ERROR (0x0108), H3_SETTINGS_ERROR (0x0109), H3_REQUEST_REJECTED (0x010b), H3_REQUEST_CANCELLED (0x010c), and H3_MESSAGE_ERROR (0x010e).
MAX_PUSH_ID frame (type=0x0d) is sent by clients on the control stream to set the maximum push ID the server may use in PUSH_PROMISE and CANCEL_PUSH frames. The server cannot push until it receives this frame; a server MUST NOT send MAX_PUSH_ID.
Server push assigns each pushed response a unique push ID. The push ID space starts at zero and is bounded by MAX_PUSH_ID. PUSH_PROMISE frames carry the promised request headers; a push stream with the matching push ID fulfills the promise. CANCEL_PUSH allows either side to cancel a push.
This document creates an IANA registry for HTTP/3 Frame Types, with an initial entry for the 'h3' identification string (0x68 0x33) under TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs.
This document creates four new IANA registries: HTTP/3 Frame Types (initial entries: DATA=0x00, HEADERS=0x01, CANCEL_PUSH=0x03, SETTINGS=0x04, PUSH_PROMISE=0x05, GOAWAY=0x07, MAX_PUSH_ID=0x0d), Settings Parameters (initial entry: SETTINGS_MAX_FIELD_SECTION_SIZE=0x06), Error Codes (H3_NO_ERROR through H3_MESSAGE_ERROR), and Stream Types (Control Stream=0x00, Push Stream=0x01).
Clients MUST verify that the server certificate is an acceptable match for the URI's origin using the process in Section 4.3.4 of [HTTP]. If verification fails, the client MUST NOT consider the server authoritative for that origin. For connection reuse with a new origin, the same certificate validation process applies.
Compression of HTTP fields using QPACK can enable attacks similar to CRIME/BREACH against TLS-protected connections when secrets and attacker-controlled data share the same compression context. Implementations SHOULD be cautious about compressing content that includes secret data alongside user-controlled data.
HTTP/3 implementations should limit the maximum size of field sections they accept. Large or unbounded field sections can be used as a denial-of-service vector. The SETTINGS_MAX_FIELD_SECTION_SIZE parameter communicates this limit; servers may send HTTP 431 when exceeded.
HTTP/3 is vulnerable to cross-protocol attacks if an attacker can cause a non-HTTP/3 server to respond to HTTP/3 frames. The use of TLS with ALPN negotiation of 'h3' mitigates this by ensuring the peer has selected HTTP/3 explicitly.
All HTTP/3 frames share a common layout: Type (variable-length integer), Length (variable-length integer describing payload length in bytes), and Frame Payload (variable-length bytes). A frame payload that contains extra bytes or terminates early MUST be treated as a connection error of type H3_FRAME_ERROR.
The GOAWAY frame (type=0x07) carries a single variable-length integer: a QUIC stream ID in the server-to-client direction (for a client-initiated bidirectional stream), or a push ID in the client-to-server direction.
The SETTINGS frame (type=0x04) payload consists of zero or more Setting records, each containing an Identifier (variable-length integer) and a Value (variable-length integer). The same setting identifier MUST NOT appear more than once.
Unidirectional streams begin with a Stream Type encoded as a variable-length integer. A push stream is indicated by Stream Type 0x01 followed by the Push ID (variable-length integer); a control stream is indicated by Stream Type 0x00.