RFC 9292

Binary Representation of HTTP Messages

πŸ“… published August 2022, from ietf

πŸ“– Binary Representation of HTTP Messages πŸŽ€

Okay bestie, let's start with the basics πŸ’– This is RFC 9292, called Binary Representation of HTTP Messages, published in August 2022. The authors are M. Thomson (Mozilla) and C. A. Wood (Cloudflare). It's a Standards Track document with ISSN 2070-1721. Its title block has no Obsoletes or Updates lines, so it doesn't list any RFCs it replaces or changes 🧚

Abstract πŸ¦‹

This document defines a binary format for representing HTTP messages. ✨

Status of This Memo πŸ“œ

This is an Internet Standards Track document, and it's a product of the Internet Engineering Task Force (IETF) πŸ’… It represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check out Section 2 of RFC 7841.

For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc9292 🌸

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ’œ

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they were in effect on the publication date. Please read those carefully, because they describe your rights and restrictions for this document. Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Revised BSD License πŸ“

Table of Contents πŸ—‚οΈ

1.  Introduction
2.  Conventions and Definitions
3.  Format
  3.1.  Known-Length Messages
  3.2.  Indeterminate-Length Messages
  3.3.  Framing Indicator
  3.4.  Request Control Data
  3.5.  Response Control Data
    3.5.1.  Informational Status Codes
  3.6.  Header and Trailer Field Lines
  3.7.  Content
  3.8.  Padding and Truncation
4.  Invalid Messages
5.  Examples
  5.1.  Request Example
  5.2.  Response Example
6.  Notable Differences with HTTP Protocol Messages
7.  "message/bhttp" Media Type
8.  Security Considerations
9.  IANA Considerations
10. References
  10.1.  Normative References
  10.2.  Informative References
Acknowledgments
Authors' Addresses

1. Introduction πŸ’–

Okay so this document defines a simple format for representing an HTTP message [HTTP], either a request or a response. It lets you encode HTTP messages so they can travel outside of an HTTP protocol πŸ¦‹ That means you can transform whole messages, including applying authenticated encryption, and it's giving main character energy ✨

The design is inspired by the framing structure of HTTP/2 [HTTP/2] and HTTP/3 [HTTP/3]. The rules for building messages lean on the rules from HTTP/2, but the format itself is its own thing. See Section 6 for the differences 🧚

This format defines "message/bhttp", a binary alternative to the "message/http" content type defined in [HTTP/1.1]. Binary is more efficient to encode and process, and it also cuts down on exposure to security problems when handling HTTP messages πŸ”₯

There are two encoding modes:

  • a known-length encoding includes length prefixes for all major message components, and
  • an indeterminate-length encoding enables efficient generation of messages where lengths are not known when encoding starts.

This format is built to carry the meaning of valid HTTP messages as simply and efficiently as possible. It is not built to capture every detail of how messages are encoded in specific HTTP versions [HTTP/1.1] [HTTP/2] [HTTP/3]. So this format probably isn't a good fit for apps that need an exact record of how a message was encoded πŸ™ˆ

2. Conventions and Definitions πŸŽ€

Here's the important bit, so pay attention πŸ‘‘ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

This document uses terminology from HTTP [HTTP] and notation from QUIC (Section 1.3 of [QUIC]) πŸ’…

3. Format 🌸

Section 6 of [HTTP] defines the general structure of HTTP messages and splits those messages into distinct parts. This format describes how those parts get packed into a sequence of bytes. At a high level, a binary message is made of:

  1. Framing indicator 🧚 This format uses a single integer to describe framing. It tells you whether the message is a request or a response, and how the sections after it are formatted. See Section 3.3.
  2. For a response, zero or more informational responses. Each informational response is made of an informational status code and a header section.
  3. Control data. For a request, this has the request method and target. For a response, this has the status code.
  4. Header section. This has zero or more header fields.
  5. Content. This is a sequence of zero or more bytes.
  6. Trailer section. This has zero or more trailer fields.
  7. Optional padding. Any amount of zero-valued bytes.

All lengths and numeric values are encoded with the variable-length integer encoding from Section 16 of [QUIC]. Integer values don't have to be encoded in the minimum number of bytes needed, which is a nice little freedom πŸ¦‹

3.1. Known-Length Messages πŸ’–

A request or response that has a known length when it's built uses the format in Figure 1 ✨

Known-Length Request {
  Framing Indicator (i) = 0,
  Request Control Data (..),
  Known-Length Field Section (..),
  Known-Length Content (..),
  Known-Length Field Section (..),
  Padding (..),
}

Known-Length Response {
  Framing Indicator (i) = 1,
  Known-Length Informational Response (..) ...,
  Final Response Control Data (..),
  Known-Length Field Section (..),
  Known-Length Content (..),
  Known-Length Field Section (..),
  Padding (..),
}

Known-Length Field Section {
  Length (i),
  Field Line (..) ...,
}

Known-Length Content {
  Content Length (i),
  Content (..),
}

Known-Length Informational Response {
  Informational Response Control Data (..),
  Known-Length Field Section (..),
}

                     Figure 1: Known-Length Message

A known-length request is a framing indicator (Section 3.3), request control data (Section 3.4), a header section with a length prefix, binary content with a length prefix, a trailer section with a length prefix, and padding πŸŽ€

A known-length response has the same fields, except the request control data gets swapped out for zero or more informational responses (Section 3.5.1), followed by response control data (Section 3.5) 🌈

For a known-length encoding, the length prefix on field sections and content is a variable-length integer. That integer is the number of bytes in the field section or content, not counting the length field itself 🧚

Fields in the header and trailer sections are each a length-prefixed name and a length-prefixed value. See Section 3.6 πŸ’œ

The format lets a message get truncated before any of the length prefixes that come before the field sections or content. See Section 3.8 πŸ™ˆ

Because of the variable-length integer encoding, each field section and the message content is limited to 2^62-1 bytes πŸ”₯

3.2. Indeterminate-Length Messages πŸ¦‹

A request or response that's built without a known length for each section uses the format in Figure 2:

Indeterminate-Length Request  {
  Framing Indicator (i) = 2,
  Request Control Data (..),
  Indeterminate-Length Field Section (..),
  Indeterminate-Length Content (..),
  Indeterminate-Length Field Section (..),
  Padding (..),
}

Indeterminate-Length Response  {
  Framing Indicator (i) = 3,
  Indeterminate-Length Informational Response (..) ...,
  Final Response Control Data (..),
  Indeterminate-Length Field Section (..),
  Indeterminate-Length Content (..),
  Indeterminate-Length Field Section (..),
  Padding (..),
}

Indeterminate-Length Content {
  Indeterminate-Length Content Chunk (..) ...,
  Content Terminator (i) = 0,
}

Indeterminate-Length Content Chunk {
  Chunk Length (i) = 1..,
  Chunk (..),
}

Indeterminate-Length Field Section {
  Field Line (..) ...,
  Content Terminator (i) = 0,
}

Indeterminate-Length Informational Response {
  Informational Response Control Data (..),
  Indeterminate-Length Field Section (..),
}

                 Figure 2: Indeterminate-Length Message

An indeterminate-length request is a framing indicator (Section 3.3), request control data (Section 3.4), a header section ended by a zero value, any number of non-zero-length chunks of binary content, a zero value, a trailer section ended by a zero value, and padding πŸ’…

An indeterminate-length response has the same fields, except the request control data gets replaced by zero or more informational responses (Section 3.5.1) and response control data (Section 3.5) 🌸

The indeterminate-length encoding only uses length prefixes for content blocks. You can include several length-prefixed portions of content, and each one starts with a non-zero Chunk Length integer that gives the number of bytes in that block. The Chunk Length is a variable-length integer πŸŽ€

Each Field Line in an Indeterminate-Length Field Section starts with a Name Length field. An Indeterminate-Length Field Section ends with a Content Terminator field. The zero value of the Content Terminator is how you tell it apart from the Name Length field, which can't hold a value of 0 πŸ‘‘

Indeterminate-length messages can be truncated in a similar way to known-length messages. See Section 3.8 πŸ™ˆ

Indeterminate-length messages use the same encoding for Field Line as known-length messages. See Section 3.6 🧚

3.3. Framing Indicator 🌈

Every binary message starts with a framing indicator. It's a single integer that describes the structure of the sections that follow. The framing indicator can only take four values πŸ’–

  • A value of 0 describes a request of known length.
  • A value of 1 describes a response of known length.
  • A value of 2 describes a request of indeterminate length.
  • A value of 3 describes a response of indeterminate length.

Any other values make the message invalid. See Section 4 πŸ’œ


Part 1 wraps here, bestie 🧚 Part 2 is next, so stay tuned ✨

3.4. Request Control Data ✨

okay so the control data for a request is where the method and request target live πŸ“¦ It's an ordered sequence of fields: Method, Scheme, Authority, Path. Every single one gets a length prefix in front of it, so the decoder always knows exactly where each piece starts and ends πŸŽ€

The values follow the HTTP/2 rules (Section 8.3.1 of [HTTP/2]) for the ":method", ":scheme", ":authority", and ":path" pseudo-header fields, one for one. The only twist: where ":authority" could be left out in HTTP/2, you encode a zero-length value instead 🧚

Here's the layout:

Request Control Data {
  Method Length (i),
  Method (..),
  Scheme Length (i),
  Scheme (..),
  Authority Length (i),
  Authority (..),
  Path Length (i),
  Path (..),
}

Figure 3: Format of Request Control Data


3.5. Response Control Data πŸ’Œ

the control data for a response is just the status code 🌸 It's encoded as a variable-length integer, NOT a length-prefixed decimal string. (Section 15 of [HTTP] is where the status code itself is defined, btw.) So no digits-as-text vibes here, just a clean integer πŸ”’

Final response control data looks like this:

Final Response Control Data {
  Status Code (i) = 200..599,
}

Figure 4: Format of Final Response Control Data

3.5.1. Informational Status Codes πŸ¦‹

okay this part is giving "multiple texts before the real reply" energy πŸ’¬ Responses with informational status codes (see Section 15.2 of [HTTP]) get encoded by repeating the response control data and the header section over and over until you finally hit a final status code. A final status code is anything from 200 to 599, inclusive. The status code is what tells you whether a response is informational or final ✨

Informational response control data looks like this:

Informational Response Control Data {
  Status Code (i) = 100..199,
}

Figure 5: Format of Informational Response Control Data

A response message can have any number of informational responses before the final status code 🌈 Each one carries an informational status code plus a header block.

So if the control data has an informational status code (anything from 100 to 199, inclusive), it gets followed by a header section (known length or indeterminate length, depending on the framing indicator) and then another block of control data. That whole pattern repeats until the control data finally has a final status code (200 to 599, inclusive) πŸ’…


3.6. Header and Trailer Field Lines πŸŽ€

header and trailer sections are made of zero or more field lines (see Section 5 of [HTTP]) πŸ’– How the section is formatted depends on whether the message is known length or indeterminate length.

Each Field Line has a name and a value. Both are length-prefixed sequences of bytes, and the Name field has to be at least one byte long 🫢 A Field Line looks like this:

Field Line {
  Name Length (i) = 1..,
  Name (..),
  Value Length (i),
  Value (..),
}

Figure 6: Format of a Field Line

Now for the field names: if a field name has byte values that aren't allowed in an HTTP field name, the message is invalid. Section 5.1 of [HTTP] has the definition of what's valid, and Section 4 covers what happens with invalid messages πŸ™ˆ Also, a recipient MUST treat a message whose field values would make an HTTP/2 message malformed (per Section 8.2.1 of [HTTP/2]) as invalid. See Section 4 for that too.

The same field name can show up on more than one field line. Section 5.2 of [HTTP] explains how repeated names work and how their values get combined 🌸

Messages are invalid (see Section 4) if they contain fields named ":method", ":scheme", ":authority", ":path", or ":status". Other pseudo-fields defined by protocol extensions MAY be included. But pseudo-fields can't go in trailers (see Section 8.1 of [HTTP/2]) πŸ™…β€β™€οΈ A Field Line with pseudo-fields MUST come before any other Field Line values. If a message has a pseudo-field after any other field, it's invalid. See Section 4 πŸ“

Fields that relate to connections (Section 7.6.1 of [HTTP]) can't be used to create the effect they'd have on a connection in this context πŸ”Œ These fields SHOULD be removed when you build a binary message. The good news is they don't make the message invalid (see Section 4). Letting them stay means a binary message can still capture messages that get exchanged in a protocol context πŸ¦‹

Like HTTP/2 or HTTP/3, this format has one exception for multiple instances of the Cookie field πŸͺ Instances of fields with the ASCII-encoded value of "cookie" get combined using a semicolon octet (0x3b) instead of a comma. See Section 8.2.3 of [HTTP/2] πŸ’œ


3.7. Content 🌷

content is just a sequence of bytes, and it can be any length 🧁 A known-length message does have a limit, but it's big enough that you probably won't ever hit it in real life. Indeterminate-length messages have no limit on content size at all ✨


3.8. Padding and Truncation 🫧

messages can get padded with any number of zero-valued bytes πŸ› Non-zero padding bytes make the message invalid (see Section 4). The difference from the rest of the message: a processor MAY decide not to validate the value of padding bytes πŸ™ƒ

Truncation shrinks messages that have no data in their trailing field sections or content βœ‚οΈ If the trailers are empty, the encoder MAY leave them out instead of adding a length field set to zero. An encoder MAY also leave out empty content the same way, as long as the trailers are empty too. A message that gets truncated anywhere else is invalid (see Section 4) πŸ’€

Decoders MUST treat missing truncated fields as if they'd been sent with the length field set to zero 🧚

Padding works fine alongside truncating empty parts of a message. Zero-valued bytes get read as a zero-length part, which means exactly the same thing as that part just not being there πŸ’–


4. Invalid Messages 🚫

this section is the "uh oh, the message is broken" section 😭 It describes a bunch of ways a message can be invalid. Invalid messages MUST NOT be processed any further, except to log an error and send back an error response πŸ™…β€β™€οΈ

The format is built for incremental processing, so implementations need to know that an error might only show up after they've already done some incremental processing πŸ‘€


5. Examples πŸŽ€

this section has example requests and responses, in both the known-length and indeterminate-length forms πŸ’… Let's go!

5.1. Request Example 🌈

the example HTTP/1.1 message in Figure 7 shows the content in the "message/http" format πŸ¦‹

Valid HTTP/1.1 messages need lines that end in CRLF (the two bytes 0x0d and 0x0a) πŸ’Œ To keep things simple and consistent, the content in these examples is limited to text, which also uses CRLF for line endings ✨

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

Figure 7: Sample HTTP Request

This can be expressed as a binary message (type "message/bhttp") using a known-length encoding, shown in hexadecimal in Figure 8 🧚 Figure 8 has text alongside it too, so you can see that most of the content doesn't get changed πŸ“

00034745 54056874 74707300 0a2f6865  ..GET.https../he
6c6c6f2e 74787440 6c0a7573 65722d61  llo.txt@l.user-a
67656e74 34637572 6c2f372e 31362e33  gent4curl/7.16.3
206c6962 6375726c 2f372e31 362e3320   libcurl/7.16.3
4f70656e 53534c2f 302e392e 376c207a  OpenSSL/0.9.7l z
6c69622f 312e322e 3304686f 73740f77  lib/1.2.3.host.w
77772e65 78616d70 6c652e63 6f6d0f61  ww.example.com.a
63636570 742d6c61 6e677561 67650665  ccept-language.e
6e2c206d 690000                      n, mi..

Figure 8: Known-Length Binary Encoding of Request

This example shows that the Host header field does NOT get copied into the ":authority" field. That's required so the request can be reproduced accurately (see Section 8.3.1 of [HTTP/2]) 🫢

The same message can be truncated without changing how it's interpreted 🌸 In this case, the last two bytes (which correspond to content and a trailer section) can each be removed without changing the message's meaning πŸ’œ

The same message, encoded with an indeterminate-length encoding, is shown in Figure 9 πŸ¦‹ Since the content of this message is empty, the difference between the formats is pretty negligible πŸ™ˆ

02034745 54056874 74707300 0a2f6865  ..GET.https../he
6c6c6f2e 7478740a 75736572 2d616765  llo.txt.user-age
6e743463 75726c2f 372e3136 2e33206c  nt4curl/7.16.3 l
69626375 726c2f37 2e31362e 33204f70  ibcurl/7.16.3 Op
656e5353 4c2f302e 392e376c 207a6c69  enSSL/0.9.7l zli
622f312e 322e3304 686f7374 0f777777  b/1.2.3.host.www
2e657861 6d706c65 2e636f6d 0f616363  .example.com.acc
6570742d 6c616e67 75616765 06656e2c  ept-language.en,
206d6900 00000000 00000000 00000000   mi.............

Figure 9: Indeterminate-Length Binary Encoding of Request

This indeterminate-length encoding has 10 bytes of padding 🧁 Two additional bytes can be truncated the same way as in the known-length example, so up to 12 bytes can be removed from this message without changing its meaning πŸ‘‘

5.2. Response Example ✨

okay so responses can totally carry interim (1xx) status codes too πŸ¦‹ Figure 10 shows that off. It has examples of informational status codes 102 and 103. 102 comes from [RFC2518], which is now obsolete but still defines that code, and 103 comes from [RFC8297].

HTTP/1.1 102 Processing
Running: "sleep 15"

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

Hello World! My content includes a trailing CRLF.

Figure 10: Sample HTTP Response

This one is a longer example, so we only get the indeterminate-length encoding in Figure 11 🌸 Heads up: the reason phrase text (that Processing bit) is NOT kept by this encoding. Not me being dramatic, just how it works πŸ’…

03406607 72756e6e 696e670a 22736c65  .@f.running."sle
65702031 35220040 67046c69 6e6b233c  ep 15".@g.link#<
2f737479 6c652e63 73733e3b 2072656c  /style.css>; rel
3d707265 6c6f6164 3b206173 3d737479  =preload; as=sty
6c65046c 696e6b24 3c2f7363 72697074  le.link$</script
2e6a733e 3b207265 6c3d7072 656c6f61  .js>; rel=preloa
643b2061 733d7363 72697074 0040c804  d; as=script.@..
64617465 1d4d6f6e 2c203237 204a756c  date.Mon, 27 Jul
20323030 39203132 3a32383a 35332047   2009 12:28:53 G
4d540673 65727665 72064170 61636865  MT.server.Apache
0d6c6173 742d6d6f 64696669 65641d57  .last-modified.W
65642c20 3232204a 756c2032 30303920  ed, 22 Jul 2009
31393a31 353a3536 20474d54 04657461  19:15:56 GMT.eta
67142233 34616133 38372d64 2d313536  g."34aa387-d-156
38656230 30220d61 63636570 742d7261  8eb00".accept-ra
6e676573 05627974 65730e63 6f6e7465  nges.bytes.conte
6e742d6c 656e6774 68023531 04766172  nt-length.51.var
790f4163 63657074 2d456e63 6f64696e  y.Accept-Encodin
670c636f 6e74656e 742d7479 70650a74  g.content-type.t
6578742f 706c6169 6e003348 656c6c6f  ext/plain.3Hello
20576f72 6c642120 4d792063 6f6e7465   World! My conte
6e742069 6e636c75 64657320 61207472  nt includes a tr
61696c69 6e672043 524c462e 0d0a0000  ailing CRLF.....

Figure 11: Binary Response, including Informational Responses

Now chunked encoding (see Section 7.1 of [HTTP/1.1]) πŸŽ€ A response like the one in Figure 12 can use indeterminate-length encoding, which keeps buffering to a minimum when translating into the binary format. BUT chunk boundaries don't have to be kept, and chunk extensions can't be carried in the binary format at all. Spill the tea on that in Section 6 πŸ«–

HTTP/1.1 200 OK
Transfer-Encoding: chunked

4
This
6
 conte
13;chunk-extension=foo
nt contains CRLF.

0
Trailer: text

Figure 12: Chunked Encoding Example

And the known-length version is Figure 13 🧚 The Transfer-Encoding header field is gone here, which is giving clean vibes ✨

0140c800 1d546869 7320636f 6e74656e  .@...This conten
7420636f 6e746169 6e732043 524c462e  t contains CRLF.
0d0a0d07 74726169 6c657204 74657874  ....trailer.text

Figure 13: Known-Length Encoding of Response


6. Notable Differences with HTTP Protocol Messages πŸ’œ

This format is built to carry HTTP semantics, just like HTTP/1.1 [HTTP/1.1], HTTP/2 [HTTP/2], or HTTP/3 [HTTP/3] do 🫢 But there are some notable differences between this format and the format used in those interactive protocol versions, so let's get into it.

As a standalone representation, this format is missing the following features from those other formats:

  • chunk extensions (Section 7.1.1 of [HTTP/1.1]) and transfer encoding (Section 6.1 of [HTTP/1.1])
  • generic framing and extensibility capabilities
  • field blocks other than a single header and trailer field block
  • carrying reason phrases in responses (Section 4 of [HTTP/1.1])
  • header compression [HPACK] [QPACK]
  • response framing that depends on the corresponding request (such as HEAD) or the value of the status code (such as 204 or 304); these responses use the same framing as all other messages

Some of these features are also missing in HTTP/2 and HTTP/3, so it's not just this format being the odd one out πŸ€·β€β™€οΈ

Unlike HTTP/2 and HTTP/3, this format uses a fixed format for control data instead of pseudo-fields. Iconic structure, no cap πŸ‘‘

Also, some messages can be represented in this format, like CONNECT or upgrade requests, but doing that serves no purpose. Those requests exist to change protocol behavior, and this format can't do that without extra mechanisms πŸ™ˆ


7. "message/bhttp" Media Type πŸ¦‹

The "message/bhttp" media type can be used to enclose a single HTTP request or response message, as long as it follows the MIME restrictions for all "message" types about line length and encodings πŸ’…

Type name:  message
Subtype name:  bhttp
Required parameters:  N/A
Optional parameters:  N/A
Encoding considerations:  Only "8bit" or "binary" is permitted.
Security considerations:  See Section 8.
Interoperability considerations:  N/A
Published specification:  RFC 9292
Applications that use this media type:  Applications seeking to
   convey HTTP semantics that are independent of a specific protocol.
Fragment identifier considerations:  N/A
Additional information:  Deprecated alias names for this type:  N/A
                         Magic number(s):  N/A
                         File extension(s):  N/A
                         Macintosh file type code(s):  N/A
Person & email address to contact for further information:  See the
   Authors' Addresses section.
Intended usage:  COMMON
Restrictions on usage:  N/A
Author:  See the Authors' Addresses section.
Change controller:  IESG

8. Security Considerations πŸ”₯

Okay, bestie, this part is SERIOUS 😭 Lots of the things that apply to HTTP message handling also apply to this format. Check out Section 17 of [HTTP] and Section 11 of [HTTP/1.1] for the common issues people run into when handling HTTP messages.

Strict parsing with zero tolerance for errors can help dodge a bunch of attacks πŸ›‘οΈ But implementations still need to watch out for resource exhaustion attacks that can come from receiving large messages, especially ones with huge numbers of fields. Yikes πŸ’€

Implementations need to make sure they aren't open to resource exhaustion attacks from maliciously crafted messages. Overall, the format is designed so that processing messages takes minimal state 🧚 However, producing a combined field value (Section 5.2 of [HTTP]) for fields might require committing resources. In particular, combining might be needed for the Cookie field when translating this format for use in other contexts, like an API or translation to HTTP/1.1 [HTTP/1.1], where the recipient of the field might not expect multiple values. Careful with those cookies, friend πŸͺ


9. IANA Considerations 🌈

IANA has added the media type "message/bhttp" to the "Media Types" registry at https://www.iana.org/assignments/media-types. Check Section 7 for the registration info ✨


10. References 🧚

10.1. Normative References

[HTTP]     Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
           Ed., "HTTP Semantics", STD 97, RFC 9110,
           DOI 10.17487/RFC9110, June 2022,
           <https://www.rfc-editor.org/info/rfc9110>.

[HTTP/2]   Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113,
           DOI 10.17487/RFC9113, June 2022,
           <https://www.rfc-editor.org/info/rfc9113>.

[QUIC]     Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based
           Multiplexed and Secure Transport", RFC 9000,
           DOI 10.17487/RFC9000, May 2021,
           <https://www.rfc-editor.org/info/rfc9000>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

10.2. Informative References

[HPACK]    Peon, R. and H. Ruellan, "HPACK: Header Compression for
           HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015,
           <https://www.rfc-editor.org/info/rfc7541>.

[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
           Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112,
           June 2022, <https://www.rfc-editor.org/info/rfc9112>.

[HTTP/3]   Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114,
           June 2022, <https://www.rfc-editor.org/info/rfc9114>.

[QPACK]    Krasic, C., Bishop, M., and A. Frindell, Ed., "QPACK:
           Field Compression for HTTP/3", RFC 9204,
           DOI 10.17487/RFC9204, June 2022,
           <https://www.rfc-editor.org/info/rfc9204>.

[RFC2518]  Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
           Jensen, "HTTP Extensions for Distributed Authoring --
           WEBDAV", RFC 2518, DOI 10.17487/RFC2518, February 1999,
           <https://www.rfc-editor.org/info/rfc2518>.

[RFC8297]  Oku, K., "An HTTP Status Code for Indicating Hints",
           RFC 8297, DOI 10.17487/RFC8297, December 2017,
           <https://www.rfc-editor.org/info/rfc8297>.

Acknowledgments πŸ’–

Huge shoutout to Julian Reschke, David Schinazi, Lucas Pardue, and Tommy Pauly 🫢 They gave excellent feedback on both the design and its documentation, and honestly the whole thing is better because of them ✨

Authors' Addresses πŸŽ€

Martin Thomson
Mozilla
Email: mt@lowentropy.net

Christopher A. Wood
Cloudflare
Email: caw@heapingbits.net
πŸ“¦ where this page comes from