rfc-9204

QPACK: Field Compression for HTTP/3

C. Krasic, M. Bishop, A. Frindell (Editor)
date2022-06 streamIETF areawit wgquic statusPROPOSED STANDARD pages41 canonicalhttps://www.rfc-editor.org/rfc/rfc9204 doi10.17487/RFC9204 errataview
This specification defines QPACK: a compression format for efficiently representing HTTP fields that is to be used in HTTP/3. This is a variation of HPACK compression that seeks to reduce head-of-line blocking.

Extracted elements (31)

design-rationale §3.2.6

Post-Base indexing was introduced to allow a single-pass encoder to include references to dynamic table entries added during encoding of the current field section, without requiring a second pass. Without post-Base indexing, an encoder would need to pre-scan a field section before encoding it.

http

design-rationale §1

QPACK was designed as a variation of HPACK specifically to avoid head-of-line blocking in HTTP/3. HPACK assumes a total ordering across frames on all streams, which would block field section processing when used over QUIC's out-of-order delivery. QPACK allows correctness in the presence of out-of-order delivery while flexibly balancing resilience against head-of-line blocking versus compression ratio.

http, quic, http

design-rationale §2.1.1.1

The Duplicate instruction (Section 4.3.4) allows an encoder to reinsert an existing dynamic table entry without retransmitting name or value. This is used to avoid referencing entries close to eviction ('draining entries'), which would block new insertions by creating unacknowledged references that prevent eviction.

http

interoperability-note §3.1

The QPACK static table is indexed from 0, whereas the HPACK static table is indexed from 1. Static and dynamic table entries in QPACK are addressed in separate namespaces (distinguished by the T bit), unlike HPACK's unified index space.

http

normative-requirement §2.2.2.1 MUST

After the decoder finishes decoding a field section encoded using representations containing dynamic table references, it MUST emit a Section Acknowledgment instruction. The encoder interprets each such instruction as acknowledging the earliest unacknowledged field section with dynamic table references on the given stream.

http

normative-requirement §2.1.2 MUST

An encoder MUST limit the number of streams that could become blocked to the value of SETTINGS_QPACK_BLOCKED_STREAMS at all times. If a decoder encounters more blocked streams than it promised to support, it MUST treat this as a connection error of type QPACK_DECOMPRESSION_FAILED.

http, quic

normative-requirement §7.1.3 MUST NOT

An intermediary MUST NOT re-encode a field line value that uses a literal representation with the 'N' (never-indexed) bit set using any representation that would index it. If QPACK is used for re-encoding, a literal with the 'N' bit set MUST be used; if HPACK is used, the never-indexed literal representation MUST be used.

http, security, privacy

normative-requirement §4.2 MUST

Each HTTP/3 endpoint MUST initiate at most one encoder stream and at most one decoder stream. Receipt of a second instance of either stream type MUST be treated as a connection error of type H3_STREAM_CREATION_ERROR.

http, quic

normative-requirement §2.2.3 MUST

If the decoder encounters a reference to a dynamic table entry that has already been evicted or has an absolute index greater than or equal to the declared Required Insert Count, it MUST treat this as a connection error of type QPACK_DECOMPRESSION_FAILED. A reference in an encoder instruction to an evicted entry MUST be treated as QPACK_ENCODER_STREAM_ERROR.

http

normative-requirement §2.2.1 MUST

If the decoder encounters a Required Insert Count smaller than expected in an encoded field section, it MUST treat this as a connection error of type QPACK_DECOMPRESSION_FAILED. If it encounters one larger than expected, it MAY treat this as a connection error of type QPACK_DECOMPRESSION_FAILED.

http

normative-requirement §2.1.1 MUST NOT

If the dynamic table does not contain enough room for a new entry without evicting non-evictable entries, the encoder MUST NOT insert that entry into the dynamic table (including duplicates). An entry is evictable only after its insertion is acknowledged and there are no outstanding references to it in unacknowledged representations.

http

normative-requirement §4.1.1 MUST

QPACK implementations MUST be able to decode integers up to and including 62 bits long, using the prefixed integer encoding from HPACK (RFC 7541 Section 5.1).

http

normative-requirement §3.2.3 MUST NOT

The encoder MUST NOT set a dynamic table capacity that exceeds the maximum specified by the decoder via SETTINGS_QPACK_MAX_TABLE_CAPACITY. For 0-RTT clients using a previously remembered non-zero setting, the server MUST send the same non-zero value in its SETTINGS frame; any other value or omission MUST be treated as a connection error of type QPACK_DECODER_STREAM_ERROR.

http, quic

normative-requirement §4.2 MUST NOT

The sender MUST NOT close either the encoder or decoder stream, and the receiver MUST NOT request that the sender close either stream. Closure of either unidirectional stream MUST be treated as a connection error of type H3_CLOSED_CRITICAL_STREAM.

http, quic

normative-requirement §2.1.3 SHOULD NOT

To avoid flow-control deadlocks, an encoder SHOULD NOT write an instruction unless sufficient stream and connection flow-control credit is available for the entire instruction. A decoder withholding flow-control credit until instructions are complete can produce deadlocks.

http, quic, congestion

protocol-element §3.2.1

Dynamic table entry size equals the sum of the name's byte length, the value's byte length, and 32 additional bytes (computed without Huffman encoding applied). The dynamic table capacity is the encoder-controlled upper limit on total table size; initial capacity is zero.

http

protocol-element §4.2

QPACK defines two unidirectional streams: an encoder stream (type 0x02) carrying encoder instructions from encoder to decoder, and a decoder stream (type 0x03) carrying decoder instructions from decoder to encoder. These streams carry unframed sequences of instructions and must not be closed.

http, quic

protocol-element §3.2.4

QPACK uses three indexing schemes: absolute indexing (fixed for the entry's lifetime, starting at 0), relative indexing (context-sensitive; in encoder instructions, 0 = most recent; in field representations, 0 = Base-1), and post-Base indexing (used in representations for entries with absolute index >= Base, starting at 0 for Base).

http

protocol-element §4.5.1.2

The Base is a reference point for relative and post-Base dynamic table indices in field line representations. It is encoded as a Sign bit and Delta Base relative to the Required Insert Count: if Sign=0, Base = RIC + DeltaBase; if Sign=1, Base = RIC - DeltaBase - 1. The Base value MUST NOT be negative.

http

protocol-element §4.5.1.1

The Required Insert Count (RIC) identifies the minimum dynamic table Insert Count needed to decode an encoded field section. It is encoded with a modular transformation: EncInsertCount = (ReqInsertCount mod (2 * MaxEntries)) + 1, where MaxEntries = floor(MaxTableCapacity / 32), limiting prefix length on long-lived connections.

http

registry §8.3

Three error codes registered in the HTTP/3 Error Codes registry: QPACK_DECOMPRESSION_FAILED (0x0200) for field section decoding failure, QPACK_ENCODER_STREAM_ERROR (0x0201) for encoder instruction decoding failure, and QPACK_DECODER_STREAM_ERROR (0x0202) for decoder instruction decoding failure.

registry, http

registry §8.1

Two entries registered in the HTTP/3 Settings registry: SETTINGS_QPACK_MAX_TABLE_CAPACITY (code 0x01, default 0) controlling the maximum dynamic table capacity the encoder may use, and SETTINGS_QPACK_BLOCKED_STREAMS (code 0x07, default 0) controlling the maximum number of blocked streams.

registry, http

registry §8.2

Two stream types registered in the HTTP/3 Stream Types registry: QPACK Encoder Stream (code 0x02, sender: Both) and QPACK Decoder Stream (code 0x03, sender: Both).

registry, http

security-consideration §7.3

An attacker can attempt memory exhaustion by exploiting the dynamic table and blocked streams. QPACK bounds memory usage via SETTINGS_QPACK_MAX_TABLE_CAPACITY (controlling dynamic table size) and SETTINGS_QPACK_BLOCKED_STREAMS (limiting blocked stream state). Implementations should also limit the size of unsent data on the decoder stream.

security, http

security-consideration §7.4 SHOULD

Implementations MUST treat oversized integers or string literals as errors (QPACK_DECOMPRESSION_FAILED on request streams, or the appropriate stream-type error on encoder/decoder streams). Implementation limits for integer and string literal lengths SHOULD be large enough to accommodate the largest fields the HTTP implementation can accept.

security, http

security-consideration §7.1

QPACK is vulnerable to CRIME-like attacks where an attacker who can both inject field lines and observe encoded lengths can probe the dynamic table state. QPACK mitigates this by requiring a full field line match rather than character-by-character, reducing attacks to brute-force guessing, but low-entropy field values (e.g., Cookie, Authorization) remain at risk.

security, http, privacy

wire-format §4.5.1

Encoded Field Section Prefix: Required Insert Count as 8-bit prefix integer, followed by Sign bit ('S', 1 bit) and Delta Base as 7-bit prefix integer. These two fields precede the encoded field line representations.

http

wire-format §4.3.2

Insert with Name Reference instruction: starts with '1' bit, T bit (static=1, dynamic=0), 6-bit prefix name index, then field value as 8-bit prefix string literal with Huffman flag. Insert with Literal Name starts with '01', 6-bit prefix name string, then 8-bit prefix value string.

http

wire-format §4.5.4

Literal Field Line with Name Reference: starts with '01' 2-bit pattern, N bit (never-index), T bit (static/dynamic), 4-bit prefix name index, then 8-bit prefix string value. The N bit signals intermediaries that this field MUST always be transmitted as a literal and never indexed.

http, security

wire-format §4.4

Section Acknowledgment decoder instruction: starts with '1' bit, followed by stream ID as 7-bit prefix integer. Stream Cancellation: starts with '01' bits, followed by stream ID as 6-bit prefix integer. Insert Count Increment: starts with '00' bits, followed by Increment as 6-bit prefix integer.

http

wire-format §4.3.1

Set Dynamic Table Capacity instruction: starts with '001' 3-bit pattern, followed by new capacity as 5-bit prefix integer. Reducing capacity may cause evictions; capacity MUST NOT exceed the decoder's maximum.

http