Binary Representation of HTTP Messages
Extracted elements (27)
CONNECT and upgrade requests can technically be represented in this format but doing so serves no purpose, since those requests affect protocol behavior that this standalone format cannot replicate without additional mechanisms.
The format is explicitly not designed to capture all encoding details of specific HTTP versions (1.1, 2, 3); it conveys HTTP semantics only, making it unsuitable for applications that require an exact recording of wire-level encoding.
The Name Length field of a Field Line has a minimum value of 1, which is intentional: it allows the zero value of the Content Terminator to unambiguously signal end-of-section in indeterminate-length encoding without a separate sentinel byte.
The response status code is encoded as a variable-length integer (not a decimal string) because this format deals in HTTP semantics rather than in HTTP/1.1 syntax; the numeric value is what matters.
Two encoding modes are provided: known-length (all sections length-prefixed for efficient random access) and indeterminate-length (terminated sections for streaming use cases where lengths are not known at encoding time).
Instances of the Cookie field are combined using a semicolon octet (0x3b) rather than a comma, matching the HTTP/2 behavior defined in Section 8.2.3 of HTTP/2.
The Host header field is not replicated in the ':authority' control data field; Section 8.3.1 of HTTP/2 rules govern how the authority is derived, and the two must not be duplicated.
This format does not preserve reason phrases from HTTP/1.1 responses, chunk extensions or transfer-encoding, header compression (HPACK/QPACK), or response framing that depends on the request method or status code (e.g., HEAD, 204, 304).
Unlike HTTP/2 and HTTP/3 which use pseudo-header fields for control data, this format uses a fixed binary encoding for control data (method/target for requests, status code for responses).
A recipient MUST treat a message that contains field values that would cause an HTTP/2 message to be malformed according to Section 8.2.1 of HTTP/2 as invalid.
Connection-related header fields (HTTP Section 7.6.1) SHOULD be removed when constructing a binary message, though their presence does not make the message invalid.
Decoders MUST treat missing truncated fields (i.e., trailing empty field sections or content that were omitted by the encoder) as equivalent to having been sent with the length field set to zero.
Invalid messages MUST NOT be processed further except to log an error and produce an error response.
Messages are invalid if they contain fields named ':method', ':scheme', ':authority', ':path', or ':status'. Other extension-defined pseudo-fields MAY be included, and a Field Line containing pseudo-fields MUST precede all other Field Line values.
Padding bytes MUST be zero-valued; non-zero padding bytes cause the message to be invalid. A processor MAY decide not to validate padding byte values.
Truncation is only valid at the boundary of trailing empty field sections or empty content; a message truncated at any other point is invalid.
IANA has added the 'message/bhttp' media type to the Media Types registry. Encoding is limited to '8bit' or 'binary'; it is intended for applications conveying HTTP semantics independently of a specific protocol version.
Combining multiple field values (e.g., multiple Cookie field lines) into a single value may require commitment of additional resources and must be handled carefully, especially when translating to HTTP/1.1 or an API that expects a single value.
Strict parsing of the format with no tolerance for errors helps avoid security attacks. Implementations must also guard against resource exhaustion from large messages, particularly those with large numbers of header fields.
A Known-Length Request consists of Framing Indicator (i)=0, Request Control Data, Known-Length Field Section (header), Known-Length Content, Known-Length Field Section (trailer), and Padding. A Known-Length Response uses Framing Indicator (i)=1 and replaces request control data with zero or more Known-Length Informational Responses followed by Final Response Control Data.
All lengths and numeric values are encoded using the variable-length integer encoding from Section 16 of QUIC (RFC 9000). Integer values do not need to be encoded on the minimum number of bytes necessary, and the maximum encodable value is 2^62-1.
An Indeterminate-Length Request uses Framing Indicator (i)=2; field sections are terminated by a zero Content Terminator byte, and content is sent as one or more non-zero-length chunks each preceded by a Chunk Length variable-length integer, followed by a Content Terminator (i)=0. The indeterminate-length response uses Framing Indicator (i)=3.
Each Field Line encodes Name Length (i, minimum 1), Name bytes, Value Length (i), and Value bytes. The Name Length minimum of 1 distinguishes field lines from the Content Terminator value of 0 in indeterminate-length sections.
Final Response Control Data encodes the HTTP status code as a variable-length integer in the range 200–599, not as a length-prefixed decimal string as used in HTTP/1.1.
Informational Response Control Data encodes a status code as a variable-length integer in the range 100–199 and is followed by a header section and another block of control data; this repeats until a final status code (200–599) is encountered.
Request Control Data encodes Method, Scheme, Authority, and Path as an ordered sequence of length-prefixed byte strings. Where HTTP/2 would omit the ':authority' pseudo-header, a zero-length value is encoded instead.
The binary message begins with a Framing Indicator, a single variable-length integer. Values 0–3 are defined: 0 = known-length request, 1 = known-length response, 2 = indeterminate-length request, 3 = indeterminate-length response. Any other value makes the message invalid.