diff options
Diffstat (limited to 'doc/rfc/rfc8941.txt')
-rw-r--r-- | doc/rfc/rfc8941.txt | 1677 |
1 files changed, 1677 insertions, 0 deletions
diff --git a/doc/rfc/rfc8941.txt b/doc/rfc/rfc8941.txt new file mode 100644 index 0000000..f96e457 --- /dev/null +++ b/doc/rfc/rfc8941.txt @@ -0,0 +1,1677 @@ + + + + +Internet Engineering Task Force (IETF) M. Nottingham +Request for Comments: 8941 Fastly +Category: Standards Track P-H. Kamp +ISSN: 2070-1721 The Varnish Cache Project + February 2021 + + + Structured Field Values for HTTP + +Abstract + + This document describes a set of data types and associated algorithms + that are intended to make it easier and safer to define and handle + HTTP header and trailer fields, known as "Structured Fields", + "Structured Headers", or "Structured Trailers". It is intended for + use by specifications of new HTTP fields that wish to use a common + syntax that is more restrictive than traditional HTTP field values. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 7841. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc8941. + +Copyright Notice + + Copyright (c) 2021 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) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + +Table of Contents + + 1. Introduction + 1.1. Intentionally Strict Processing + 1.2. Notational Conventions + 2. Defining New Structured Fields + 3. Structured Data Types + 3.1. Lists + 3.1.1. Inner Lists + 3.1.2. Parameters + 3.2. Dictionaries + 3.3. Items + 3.3.1. Integers + 3.3.2. Decimals + 3.3.3. Strings + 3.3.4. Tokens + 3.3.5. Byte Sequences + 3.3.6. Booleans + 4. Working with Structured Fields in HTTP + 4.1. Serializing Structured Fields + 4.1.1. Serializing a List + 4.1.2. Serializing a Dictionary + 4.1.3. Serializing an Item + 4.1.4. Serializing an Integer + 4.1.5. Serializing a Decimal + 4.1.6. Serializing a String + 4.1.7. Serializing a Token + 4.1.8. Serializing a Byte Sequence + 4.1.9. Serializing a Boolean + 4.2. Parsing Structured Fields + 4.2.1. Parsing a List + 4.2.2. Parsing a Dictionary + 4.2.3. Parsing an Item + 4.2.4. Parsing an Integer or Decimal + 4.2.5. Parsing a String + 4.2.6. Parsing a Token + 4.2.7. Parsing a Byte Sequence + 4.2.8. Parsing a Boolean + 5. IANA Considerations + 6. Security Considerations + 7. References + 7.1. Normative References + 7.2. Informative References + Appendix A. Frequently Asked Questions + A.1. Why Not JSON? + Appendix B. Implementation Notes + Acknowledgements + Authors' Addresses + +1. Introduction + + Specifying the syntax of new HTTP header (and trailer) fields is an + onerous task; even with the guidance in Section 8.3.1 of [RFC7231], + there are many decisions -- and pitfalls -- for a prospective HTTP + field author. + + Once a field is defined, bespoke parsers and serializers often need + to be written, because each field value has a slightly different + handling of what looks like common syntax. + + This document introduces a set of common data structures for use in + definitions of new HTTP field values to address these problems. In + particular, it defines a generic, abstract model for them, along with + a concrete serialization for expressing that model in HTTP [RFC7230] + header and trailer fields. + + An HTTP field that is defined as a "Structured Header" or "Structured + Trailer" (if the field can be either, it is a "Structured Field") + uses the types defined in this specification to define its syntax and + basic handling rules, thereby simplifying both its definition by + specification writers and handling by implementations. + + Additionally, future versions of HTTP can define alternative + serializations of the abstract model of these structures, allowing + fields that use that model to be transmitted more efficiently without + being redefined. + + Note that it is not a goal of this document to redefine the syntax of + existing HTTP fields; the mechanisms described herein are only + intended to be used with fields that explicitly opt into them. + + Section 2 describes how to specify a Structured Field. + + Section 3 defines a number of abstract data types that can be used in + Structured Fields. + + Those abstract types can be serialized into and parsed from HTTP + field values using the algorithms described in Section 4. + +1.1. Intentionally Strict Processing + + This specification intentionally defines strict parsing and + serialization behaviors using step-by-step algorithms; the only error + handling defined is to fail the operation altogether. + + It is designed to encourage faithful implementation and good + interoperability. Therefore, an implementation that tried to be + helpful by being more tolerant of input would make interoperability + worse, since that would create pressure on other implementations to + implement similar (but likely subtly different) workarounds. + + In other words, strict processing is an intentional feature of this + specification; it allows non-conformant input to be discovered and + corrected by the producer early and avoids both interoperability and + security issues that might otherwise result. + + Note that as a result of this strictness, if a field is appended to + by multiple parties (e.g., intermediaries or different components in + the sender), an error in one party's value is likely to cause the + entire field value to fail parsing. + +1.2. Notational Conventions + + 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 algorithms to specify parsing and serialization + behaviors and the Augmented Backus-Naur Form (ABNF) notation of + [RFC5234] to illustrate expected syntax in HTTP header fields. In + doing so, it uses the VCHAR, SP, DIGIT, ALPHA, and DQUOTE rules from + [RFC5234]. It also includes the tchar and OWS rules from [RFC7230]. + + When parsing from HTTP fields, implementations MUST have behavior + that is indistinguishable from following the algorithms. If there is + disagreement between the parsing algorithms and ABNF, the specified + algorithms take precedence. + + For serialization to HTTP fields, the ABNF illustrates their expected + wire representations, and the algorithms define the recommended way + to produce them. Implementations MAY vary from the specified + behavior so long as the output is still correctly handled by the + parsing algorithm described in Section 4.2. + +2. Defining New Structured Fields + + To specify an HTTP field as a Structured Field, its authors need to: + + * Normatively reference this specification. Recipients and + generators of the field need to know that the requirements of this + document are in effect. + + * Identify whether the field is a Structured Header (i.e., it can + only be used in the header section -- the common case), a + Structured Trailer (only in the trailer section), or a Structured + Field (both). + + * Specify the type of the field value; either List (Section 3.1), + Dictionary (Section 3.2), or Item (Section 3.3). + + * Define the semantics of the field value. + + * Specify any additional constraints upon the field value, as well + as the consequences when those constraints are violated. + + Typically, this means that a field definition will specify the top- + level type -- List, Dictionary, or Item -- and then define its + allowable types and constraints upon them. For example, a header + defined as a List might have all Integer members, or a mix of types; + a header defined as an Item might allow only Strings, and + additionally only strings beginning with the letter "Q", or strings + in lowercase. Likewise, Inner Lists (Section 3.1.1) are only valid + when a field definition explicitly allows them. + + When parsing fails, the entire field is ignored (see Section 4.2); in + most situations, violating field-specific constraints should have the + same effect. Thus, if a header is defined as an Item and required to + be an Integer, but a String is received, the field will by default be + ignored. If the field requires different error handling, this should + be explicitly specified. + + Both Items and Inner Lists allow parameters as an extensibility + mechanism; this means that values can later be extended to + accommodate more information, if need be. To preserve forward + compatibility, field specifications are discouraged from defining the + presence of an unrecognized parameter as an error condition. + + To further assure that this extensibility is available in the future, + and to encourage consumers to use a complete parser implementation, a + field definition can specify that "grease" parameters be added by + senders. A specification could stipulate that all parameters that + fit a defined pattern are reserved for this use and then encourage + them to be sent on some portion of requests. This helps to + discourage recipients from writing a parser that does not account for + Parameters. + + Specifications that use Dictionaries can also allow for forward + compatibility by requiring that the presence of -- as well as value + and type associated with -- unknown members be ignored. Subsequent + specifications can then add additional members, specifying + constraints on them as appropriate. + + An extension to a Structured Field can then require that an entire + field value be ignored by a recipient that understands the extension + if constraints on the value it defines are not met. + + A field definition cannot relax the requirements of this + specification because doing so would preclude handling by generic + software; they can only add additional constraints (for example, on + the numeric range of Integers and Decimals, the format of Strings and + Tokens, the types allowed in a Dictionary's values, or the number of + Items in a List). Likewise, field definitions can only use this + specification for the entire field value, not a portion thereof. + + This specification defines minimums for the length or number of + various structures supported by implementations. It does not specify + maximum sizes in most cases, but authors should be aware that HTTP + implementations do impose various limits on the size of individual + fields, the total number of fields, and/or the size of the entire + header or trailer section. + + Specifications can refer to a field name as a "structured header + name", "structured trailer name", or "structured field name" as + appropriate. Likewise, they can refer its field value as a + "structured header value", "structured trailer value", or "structured + field value" as necessary. Field definitions are encouraged to use + the ABNF rules beginning with "sf-" defined in this specification; + other rules in this specification are not intended to be used in + field definitions. + + For example, a fictitious Foo-Example header field might be specified + as: + + | 42. Foo-Example Header + | + | The Foo-Example HTTP header field conveys information about how + | much Foo the message has. + | + | Foo-Example is an Item Structured Header [RFC8941]. Its value + | MUST be an Integer (Section 3.3.1 of [RFC8941]). Its ABNF is: + | + | Foo-Example = sf-integer + | + | Its value indicates the amount of Foo in the message, and it MUST + | be between 0 and 10, inclusive; other values MUST cause the entire + | header field to be ignored. + | + | The following parameter is defined: + | * A parameter whose key is "foourl", and whose value is a String + | (Section 3.3.3 of [RFC8941]), conveying the Foo URL for the + | message. See below for processing requirements. + | + | "foourl" contains a URI-reference (Section 4.1 of [RFC3986]). If + | its value is not a valid URI-reference, the entire header field + | MUST be ignored. If its value is a relative reference + | (Section 4.2 of [RFC3986]), it MUST be resolved (Section 5 of + | [RFC3986]) before being used. + | + | For example: + | + | Foo-Example: 2; foourl="https://foo.example.com/" + +3. Structured Data Types + + This section defines the abstract types for Structured Fields. The + ABNF provided represents the on-wire format in HTTP field values. + + In summary: + + * There are three top-level types that an HTTP field can be defined + as: Lists, Dictionaries, and Items. + + * Lists and Dictionaries are containers; their members can be Items + or Inner Lists (which are themselves arrays of Items). + + * Both Items and Inner Lists can be Parameterized with key/value + pairs. + +3.1. Lists + + Lists are arrays of zero or more members, each of which can be an + Item (Section 3.3) or an Inner List (Section 3.1.1), both of which + can be Parameterized (Section 3.1.2). + + The ABNF for Lists in HTTP fields is: + + sf-list = list-member *( OWS "," OWS list-member ) + list-member = sf-item / inner-list + + Each member is separated by a comma and optional whitespace. For + example, a field whose value is defined as a List of Tokens could + look like: + + Example-List: sugar, tea, rum + + An empty List is denoted by not serializing the field at all. This + implies that fields defined as Lists have a default empty value. + + Note that Lists can have their members split across multiple lines of + the same header or trailer section, as per Section 3.2.2 of + [RFC7230]; for example, the following are equivalent: + + Example-List: sugar, tea, rum + + and + + Example-List: sugar, tea + Example-List: rum + + However, individual members of a List cannot be safely split between + lines; see Section 4.2 for details. + + Parsers MUST support Lists containing at least 1024 members. Field + specifications can constrain the types and cardinality of individual + List values as they require. + +3.1.1. Inner Lists + + An Inner List is an array of zero or more Items (Section 3.3). Both + the individual Items and the Inner List itself can be Parameterized + (Section 3.1.2). + + The ABNF for Inner Lists is: + + inner-list = "(" *SP [ sf-item *( 1*SP sf-item ) *SP ] ")" + parameters + + Inner Lists are denoted by surrounding parenthesis, and their values + are delimited by one or more spaces. A field whose value is defined + as a List of Inner Lists of Strings could look like: + + Example-List: ("foo" "bar"), ("baz"), ("bat" "one"), () + + Note that the last member in this example is an empty Inner List. + + A header field whose value is defined as a List of Inner Lists with + Parameters at both levels could look like: + + Example-List: ("foo"; a=1;b=2);lvl=5, ("bar" "baz");lvl=1 + + Parsers MUST support Inner Lists containing at least 256 members. + Field specifications can constrain the types and cardinality of + individual Inner List members as they require. + +3.1.2. Parameters + + Parameters are an ordered map of key-value pairs that are associated + with an Item (Section 3.3) or Inner List (Section 3.1.1). The keys + are unique within the scope of the Parameters they occur within, and + the values are bare items (i.e., they themselves cannot be + parameterized; see Section 3.3). + + Implementations MUST provide access to Parameters both by index and + by key. Specifications MAY use either means of accessing them. + + The ABNF for Parameters is: + + parameters = *( ";" *SP parameter ) + parameter = param-key [ "=" param-value ] + param-key = key + key = ( lcalpha / "*" ) + *( lcalpha / DIGIT / "_" / "-" / "." / "*" ) + lcalpha = %x61-7A ; a-z + param-value = bare-item + + Note that parameters are ordered as serialized, and parameter keys + cannot contain uppercase letters. A parameter is separated from its + Item or Inner List and other parameters by a semicolon. For example: + + Example-List: abc;a=1;b=2; cde_456, (ghi;jk=4 l);q="9";r=w + + Parameters whose value is Boolean (see Section 3.3.6) true MUST omit + that value when serialized. For example, the "a" parameter here is + true, while the "b" parameter is false: + + Example-Integer: 1; a; b=?0 + + Note that this requirement is only on serialization; parsers are + still required to correctly handle the true value when it appears in + a parameter. + + Parsers MUST support at least 256 parameters on an Item or Inner + List, and support parameter keys with at least 64 characters. Field + specifications can constrain the order of individual parameters, as + well as their values' types as required. + +3.2. Dictionaries + + Dictionaries are ordered maps of key-value pairs, where the keys are + short textual strings and the values are Items (Section 3.3) or + arrays of Items, both of which can be Parameterized (Section 3.1.2). + There can be zero or more members, and their keys are unique in the + scope of the Dictionary they occur within. + + Implementations MUST provide access to Dictionaries both by index and + by key. Specifications MAY use either means of accessing the + members. + + The ABNF for Dictionaries is: + + sf-dictionary = dict-member *( OWS "," OWS dict-member ) + dict-member = member-key ( parameters / ( "=" member-value )) + member-key = key + member-value = sf-item / inner-list + + Members are ordered as serialized and separated by a comma with + optional whitespace. Member keys cannot contain uppercase + characters. Keys and values are separated by "=" (without + whitespace). For example: + + Example-Dict: en="Applepie", da=:w4ZibGV0w6ZydGU=: + + Note that in this example, the final "=" is due to the inclusion of a + Byte Sequence; see Section 3.3.5. + + Members whose value is Boolean (see Section 3.3.6) true MUST omit + that value when serialized. For example, here both "b" and "c" are + true: + + Example-Dict: a=?0, b, c; foo=bar + + Note that this requirement is only on serialization; parsers are + still required to correctly handle the true Boolean value when it + appears in Dictionary values. + + A Dictionary with a member whose value is an Inner List of Tokens: + + Example-Dict: rating=1.5, feelings=(joy sadness) + + A Dictionary with a mix of Items and Inner Lists, some with + parameters: + + Example-Dict: a=(1 2), b=3, c=4;aa=bb, d=(5 6);valid + + As with Lists, an empty Dictionary is represented by omitting the + entire field. This implies that fields defined as Dictionaries have + a default empty value. + + Typically, a field specification will define the semantics of + Dictionaries by specifying the allowed type(s) for individual members + by their keys, as well as whether their presence is required or + optional. Recipients MUST ignore members whose keys that are + undefined or unknown, unless the field's specification specifically + disallows them. + + Note that Dictionaries can have their members split across multiple + lines of the same header or trailer section; for example, the + following are equivalent: + + Example-Dict: foo=1, bar=2 + + and + + Example-Dict: foo=1 + Example-Dict: bar=2 + + However, individual members of a Dictionary cannot be safely split + between lines; see Section 4.2 for details. + + Parsers MUST support Dictionaries containing at least 1024 key/value + pairs and keys with at least 64 characters. Field specifications can + constrain the order of individual Dictionary members, as well as + their values' types as required. + +3.3. Items + + An Item can be an Integer (Section 3.3.1), a Decimal (Section 3.3.2), + a String (Section 3.3.3), a Token (Section 3.3.4), a Byte Sequence + (Section 3.3.5), or a Boolean (Section 3.3.6). It can have + associated parameters (Section 3.1.2). + + The ABNF for Items is: + + sf-item = bare-item parameters + bare-item = sf-integer / sf-decimal / sf-string / sf-token + / sf-binary / sf-boolean + + For example, a header field that is defined to be an Item that is an + Integer might look like: + + Example-Integer: 5 + + or with parameters: + + Example-Integer: 5; foo=bar + +3.3.1. Integers + + Integers have a range of -999,999,999,999,999 to 999,999,999,999,999 + inclusive (i.e., up to fifteen digits, signed), for IEEE 754 + compatibility [IEEE754]. + + The ABNF for Integers is: + + sf-integer = ["-"] 1*15DIGIT + + For example: + + Example-Integer: 42 + + Integers larger than 15 digits can be supported in a variety of ways; + for example, by using a String (Section 3.3.3), a Byte Sequence + (Section 3.3.5), or a parameter on an Integer that acts as a scaling + factor. + + While it is possible to serialize Integers with leading zeros (e.g., + "0002", "-01") and signed zero ("-0"), these distinctions may not be + preserved by implementations. + + Note that commas in Integers are used in this section's prose only + for readability; they are not valid in the wire format. + +3.3.2. Decimals + + Decimals are numbers with an integer and a fractional component. The + integer component has at most 12 digits; the fractional component has + at most three digits. + + The ABNF for decimals is: + + sf-decimal = ["-"] 1*12DIGIT "." 1*3DIGIT + + For example, a header whose value is defined as a Decimal could look + like: + + Example-Decimal: 4.5 + + While it is possible to serialize Decimals with leading zeros (e.g., + "0002.5", "-01.334"), trailing zeros (e.g., "5.230", "-0.40"), and + signed zero (e.g., "-0.0"), these distinctions may not be preserved + by implementations. + + Note that the serialization algorithm (Section 4.1.5) rounds input + with more than three digits of precision in the fractional component. + If an alternative rounding strategy is desired, this should be + specified by the header definition to occur before serialization. + +3.3.3. Strings + + Strings are zero or more printable ASCII [RFC0020] characters (i.e., + the range %x20 to %x7E). Note that this excludes tabs, newlines, + carriage returns, etc. + + The ABNF for Strings is: + + sf-string = DQUOTE *chr DQUOTE + chr = unescaped / escaped + unescaped = %x20-21 / %x23-5B / %x5D-7E + escaped = "\" ( DQUOTE / "\" ) + + Strings are delimited with double quotes, using a backslash ("\") to + escape double quotes and backslashes. For example: + + Example-String: "hello world" + + Note that Strings only use DQUOTE as a delimiter; single quotes do + not delimit Strings. Furthermore, only DQUOTE and "\" can be + escaped; other characters after "\" MUST cause parsing to fail. + + Unicode is not directly supported in Strings, because it causes a + number of interoperability issues, and -- with few exceptions -- + field values do not require it. + + When it is necessary for a field value to convey non-ASCII content, a + Byte Sequence (Section 3.3.5) can be specified, along with a + character encoding (preferably UTF-8 [STD63]). + + Parsers MUST support Strings (after any decoding) with at least 1024 + characters. + +3.3.4. Tokens + + Tokens are short textual words; their abstract model is identical to + their expression in the HTTP field value serialization. + + The ABNF for Tokens is: + + sf-token = ( ALPHA / "*" ) *( tchar / ":" / "/" ) + + For example: + + Example-Token: foo123/456 + + Parsers MUST support Tokens with at least 512 characters. + + Note that Token allows the same characters as the "token" ABNF rule + defined in [RFC7230], with the exceptions that the first character is + required to be either ALPHA or "*", and ":" and "/" are also allowed + in subsequent characters. + +3.3.5. Byte Sequences + + Byte Sequences can be conveyed in Structured Fields. + + The ABNF for a Byte Sequence is: + + sf-binary = ":" *(base64) ":" + base64 = ALPHA / DIGIT / "+" / "/" / "=" + + A Byte Sequence is delimited with colons and encoded using base64 + ([RFC4648], Section 4). For example: + + Example-ByteSequence: :cHJldGVuZCB0aGlzIGlzIGJpbmFyeSBjb250ZW50Lg==: + + Parsers MUST support Byte Sequences with at least 16384 octets after + decoding. + +3.3.6. Booleans + + Boolean values can be conveyed in Structured Fields. + + The ABNF for a Boolean is: + + sf-boolean = "?" boolean + boolean = "0" / "1" + + A Boolean is indicated with a leading "?" character followed by a "1" + for a true value or "0" for false. For example: + + Example-Boolean: ?1 + + Note that in Dictionary (Section 3.2) and Parameter (Section 3.1.2) + values, Boolean true is indicated by omitting the value. + +4. Working with Structured Fields in HTTP + + This section defines how to serialize and parse Structured Fields in + textual HTTP field values and other encodings compatible with them + (e.g., in HTTP/2 [RFC7540] before compression with HPACK [RFC7541]). + +4.1. Serializing Structured Fields + + Given a structure defined in this specification, return an ASCII + string suitable for use in an HTTP field value. + + 1. If the structure is a Dictionary or List and its value is empty + (i.e., it has no members), do not serialize the field at all + (i.e., omit both the field-name and field-value). + + 2. If the structure is a List, let output_string be the result of + running Serializing a List (Section 4.1.1) with the structure. + + 3. Else, if the structure is a Dictionary, let output_string be the + result of running Serializing a Dictionary (Section 4.1.2) with + the structure. + + 4. Else, if the structure is an Item, let output_string be the + result of running Serializing an Item (Section 4.1.3) with the + structure. + + 5. Else, fail serialization. + + 6. Return output_string converted into an array of bytes, using + ASCII encoding [RFC0020]. + +4.1.1. Serializing a List + + Given an array of (member_value, parameters) tuples as input_list, + return an ASCII string suitable for use in an HTTP field value. + + 1. Let output be an empty string. + + 2. For each (member_value, parameters) of input_list: + + 1. If member_value is an array, append the result of running + Serializing an Inner List (Section 4.1.1.1) with + (member_value, parameters) to output. + + 2. Otherwise, append the result of running Serializing an Item + (Section 4.1.3) with (member_value, parameters) to output. + + 3. If more member_values remain in input_list: + + 1. Append "," to output. + + 2. Append a single SP to output. + + 3. Return output. + +4.1.1.1. Serializing an Inner List + + Given an array of (member_value, parameters) tuples as inner_list, + and parameters as list_parameters, return an ASCII string suitable + for use in an HTTP field value. + + 1. Let output be the string "(". + + 2. For each (member_value, parameters) of inner_list: + + 1. Append the result of running Serializing an Item + (Section 4.1.3) with (member_value, parameters) to output. + + 2. If more values remain in inner_list, append a single SP to + output. + + 3. Append ")" to output. + + 4. Append the result of running Serializing Parameters + (Section 4.1.1.2) with list_parameters to output. + + 5. Return output. + +4.1.1.2. Serializing Parameters + + Given an ordered Dictionary as input_parameters (each member having a + param_key and a param_value), return an ASCII string suitable for use + in an HTTP field value. + + 1. Let output be an empty string. + + 2. For each param_key with a value of param_value in + input_parameters: + + 1. Append ";" to output. + + 2. Append the result of running Serializing a Key + (Section 4.1.1.3) with param_key to output. + + 3. If param_value is not Boolean true: + + 1. Append "=" to output. + + 2. Append the result of running Serializing a bare Item + (Section 4.1.3.1) with param_value to output. + + 3. Return output. + +4.1.1.3. Serializing a Key + + Given a key as input_key, return an ASCII string suitable for use in + an HTTP field value. + + 1. Convert input_key into a sequence of ASCII characters; if + conversion fails, fail serialization. + + 2. If input_key contains characters not in lcalpha, DIGIT, "_", "-", + ".", or "*", fail serialization. + + 3. If the first character of input_key is not lcalpha or "*", fail + serialization. + + 4. Let output be an empty string. + + 5. Append input_key to output. + + 6. Return output. + +4.1.2. Serializing a Dictionary + + Given an ordered Dictionary as input_dictionary (each member having a + member_key and a tuple value of (member_value, parameters)), return + an ASCII string suitable for use in an HTTP field value. + + 1. Let output be an empty string. + + 2. For each member_key with a value of (member_value, parameters) in + input_dictionary: + + 1. Append the result of running Serializing a Key + (Section 4.1.1.3) with member's member_key to output. + + 2. If member_value is Boolean true: + + 1. Append the result of running Serializing Parameters + (Section 4.1.1.2) with parameters to output. + + 3. Otherwise: + + 1. Append "=" to output. + + 2. If member_value is an array, append the result of running + Serializing an Inner List (Section 4.1.1.1) with + (member_value, parameters) to output. + + 3. Otherwise, append the result of running Serializing an + Item (Section 4.1.3) with (member_value, parameters) to + output. + + 4. If more members remain in input_dictionary: + + 1. Append "," to output. + + 2. Append a single SP to output. + + 3. Return output. + +4.1.3. Serializing an Item + + Given an Item as bare_item and Parameters as item_parameters, return + an ASCII string suitable for use in an HTTP field value. + + 1. Let output be an empty string. + + 2. Append the result of running Serializing a Bare Item + (Section 4.1.3.1) with bare_item to output. + + 3. Append the result of running Serializing Parameters + (Section 4.1.1.2) with item_parameters to output. + + 4. Return output. + +4.1.3.1. Serializing a Bare Item + + Given an Item as input_item, return an ASCII string suitable for use + in an HTTP field value. + + 1. If input_item is an Integer, return the result of running + Serializing an Integer (Section 4.1.4) with input_item. + + 2. If input_item is a Decimal, return the result of running + Serializing a Decimal (Section 4.1.5) with input_item. + + 3. If input_item is a String, return the result of running + Serializing a String (Section 4.1.6) with input_item. + + 4. If input_item is a Token, return the result of running + Serializing a Token (Section 4.1.7) with input_item. + + 5. If input_item is a Byte Sequence, return the result of running + Serializing a Byte Sequence (Section 4.1.8) with input_item. + + 6. If input_item is a Boolean, return the result of running + Serializing a Boolean (Section 4.1.9) with input_item. + + 7. Otherwise, fail serialization. + +4.1.4. Serializing an Integer + + Given an Integer as input_integer, return an ASCII string suitable + for use in an HTTP field value. + + 1. If input_integer is not an integer in the range of + -999,999,999,999,999 to 999,999,999,999,999 inclusive, fail + serialization. + + 2. Let output be an empty string. + + 3. If input_integer is less than (but not equal to) 0, append "-" to + output. + + 4. Append input_integer's numeric value represented in base 10 using + only decimal digits to output. + + 5. Return output. + +4.1.5. Serializing a Decimal + + Given a decimal number as input_decimal, return an ASCII string + suitable for use in an HTTP field value. + + 1. If input_decimal is not a decimal number, fail serialization. + + 2. If input_decimal has more than three significant digits to the + right of the decimal point, round it to three decimal places, + rounding the final digit to the nearest value, or to the even + value if it is equidistant. + + 3. If input_decimal has more than 12 significant digits to the left + of the decimal point after rounding, fail serialization. + + 4. Let output be an empty string. + + 5. If input_decimal is less than (but not equal to) 0, append "-" + to output. + + 6. Append input_decimal's integer component represented in base 10 + (using only decimal digits) to output; if it is zero, append + "0". + + 7. Append "." to output. + + 8. If input_decimal's fractional component is zero, append "0" to + output. + + 9. Otherwise, append the significant digits of input_decimal's + fractional component represented in base 10 (using only decimal + digits) to output. + + 10. Return output. + +4.1.6. Serializing a String + + Given a String as input_string, return an ASCII string suitable for + use in an HTTP field value. + + 1. Convert input_string into a sequence of ASCII characters; if + conversion fails, fail serialization. + + 2. If input_string contains characters in the range %x00-1f or %x7f- + ff (i.e., not in VCHAR or SP), fail serialization. + + 3. Let output be the string DQUOTE. + + 4. For each character char in input_string: + + 1. If char is "\" or DQUOTE: + + 1. Append "\" to output. + + 2. Append char to output. + + 5. Append DQUOTE to output. + + 6. Return output. + +4.1.7. Serializing a Token + + Given a Token as input_token, return an ASCII string suitable for use + in an HTTP field value. + + 1. Convert input_token into a sequence of ASCII characters; if + conversion fails, fail serialization. + + 2. If the first character of input_token is not ALPHA or "*", or the + remaining portion contains a character not in tchar, ":", or "/", + fail serialization. + + 3. Let output be an empty string. + + 4. Append input_token to output. + + 5. Return output. + +4.1.8. Serializing a Byte Sequence + + Given a Byte Sequence as input_bytes, return an ASCII string suitable + for use in an HTTP field value. + + 1. If input_bytes is not a sequence of bytes, fail serialization. + + 2. Let output be an empty string. + + 3. Append ":" to output. + + 4. Append the result of base64-encoding input_bytes as per + [RFC4648], Section 4, taking account of the requirements below. + + 5. Append ":" to output. + + 6. Return output. + + The encoded data is required to be padded with "=", as per [RFC4648], + Section 3.2. + + Likewise, encoded data SHOULD have pad bits set to zero, as per + [RFC4648], Section 3.5, unless it is not possible to do so due to + implementation constraints. + +4.1.9. Serializing a Boolean + + Given a Boolean as input_boolean, return an ASCII string suitable for + use in an HTTP field value. + + 1. If input_boolean is not a boolean, fail serialization. + + 2. Let output be an empty string. + + 3. Append "?" to output. + + 4. If input_boolean is true, append "1" to output. + + 5. If input_boolean is false, append "0" to output. + + 6. Return output. + +4.2. Parsing Structured Fields + + When a receiving implementation parses HTTP fields that are known to + be Structured Fields, it is important that care be taken, as there + are a number of edge cases that can cause interoperability or even + security problems. This section specifies the algorithm for doing + so. + + Given an array of bytes as input_bytes that represent the chosen + field's field-value (which is empty if that field is not present) and + field_type (one of "dictionary", "list", or "item"), return the + parsed header value. + + 1. Convert input_bytes into an ASCII string input_string; if + conversion fails, fail parsing. + + 2. Discard any leading SP characters from input_string. + + 3. If field_type is "list", let output be the result of running + Parsing a List (Section 4.2.1) with input_string. + + 4. If field_type is "dictionary", let output be the result of + running Parsing a Dictionary (Section 4.2.2) with input_string. + + 5. If field_type is "item", let output be the result of running + Parsing an Item (Section 4.2.3) with input_string. + + 6. Discard any leading SP characters from input_string. + + 7. If input_string is not empty, fail parsing. + + 8. Otherwise, return output. + + When generating input_bytes, parsers MUST combine all field lines in + the same section (header or trailer) that case-insensitively match + the field name into one comma-separated field-value, as per + [RFC7230], Section 3.2.2; this assures that the entire field value is + processed correctly. + + For Lists and Dictionaries, this has the effect of correctly + concatenating all of the field's lines, as long as individual members + of the top-level data structure are not split across multiple header + instances. The parsing algorithms for both types allow tab + characters, since these might be used to combine field lines by some + implementations. + + Strings split across multiple field lines will have unpredictable + results, because one or more commas (with optional whitespace) will + become part of the string output by the parser. Since concatenation + might be done by an upstream intermediary, the results are not under + the control of the serializer or the parser, even when they are both + under the control of the same party. + + Tokens, Integers, Decimals, and Byte Sequences cannot be split across + multiple field lines because the inserted commas will cause parsing + to fail. + + Parsers MAY fail when processing a field value spread across multiple + field lines, when one of those lines does not parse as that field. + For example, a parsing handling an Example-String field that's + defined as an sf-string is allowed to fail when processing this field + section: + + Example-String: "foo + Example-String: bar" + + If parsing fails -- including when calling another algorithm -- the + entire field value MUST be ignored (i.e., treated as if the field + were not present in the section). This is intentionally strict, to + improve interoperability and safety, and specifications referencing + this document are not allowed to loosen this requirement. + + Note that this requirement does not apply to an implementation that + is not parsing the field; for example, an intermediary is not + required to strip a failing field from a message before forwarding + it. + +4.2.1. Parsing a List + + Given an ASCII string as input_string, return an array of + (item_or_inner_list, parameters) tuples. input_string is modified to + remove the parsed value. + + 1. Let members be an empty array. + + 2. While input_string is not empty: + + 1. Append the result of running Parsing an Item or Inner List + (Section 4.2.1.1) with input_string to members. + + 2. Discard any leading OWS characters from input_string. + + 3. If input_string is empty, return members. + + 4. Consume the first character of input_string; if it is not + ",", fail parsing. + + 5. Discard any leading OWS characters from input_string. + + 6. If input_string is empty, there is a trailing comma; fail + parsing. + + 3. No structured data has been found; return members (which is + empty). + +4.2.1.1. Parsing an Item or Inner List + + Given an ASCII string as input_string, return the tuple + (item_or_inner_list, parameters), where item_or_inner_list can be + either a single bare item or an array of (bare_item, parameters) + tuples. input_string is modified to remove the parsed value. + + 1. If the first character of input_string is "(", return the result + of running Parsing an Inner List (Section 4.2.1.2) with + input_string. + + 2. Return the result of running Parsing an Item (Section 4.2.3) with + input_string. + +4.2.1.2. Parsing an Inner List + + Given an ASCII string as input_string, return the tuple (inner_list, + parameters), where inner_list is an array of (bare_item, parameters) + tuples. input_string is modified to remove the parsed value. + + 1. Consume the first character of input_string; if it is not "(", + fail parsing. + + 2. Let inner_list be an empty array. + + 3. While input_string is not empty: + + 1. Discard any leading SP characters from input_string. + + 2. If the first character of input_string is ")": + + 1. Consume the first character of input_string. + + 2. Let parameters be the result of running Parsing + Parameters (Section 4.2.3.2) with input_string. + + 3. Return the tuple (inner_list, parameters). + + 3. Let item be the result of running Parsing an Item + (Section 4.2.3) with input_string. + + 4. Append item to inner_list. + + 5. If the first character of input_string is not SP or ")", fail + parsing. + + 4. The end of the Inner List was not found; fail parsing. + +4.2.2. Parsing a Dictionary + + Given an ASCII string as input_string, return an ordered map whose + values are (item_or_inner_list, parameters) tuples. input_string is + modified to remove the parsed value. + + 1. Let dictionary be an empty, ordered map. + + 2. While input_string is not empty: + + 1. Let this_key be the result of running Parsing a Key + (Section 4.2.3.3) with input_string. + + 2. If the first character of input_string is "=": + + 1. Consume the first character of input_string. + + 2. Let member be the result of running Parsing an Item or + Inner List (Section 4.2.1.1) with input_string. + + 3. Otherwise: + + 1. Let value be Boolean true. + + 2. Let parameters be the result of running Parsing + Parameters (Section 4.2.3.2) with input_string. + + 3. Let member be the tuple (value, parameters). + + 4. If dictionary already contains a key this_key (comparing + character for character), overwrite its value with member. + + 5. Otherwise, append key this_key with value member to + dictionary. + + 6. Discard any leading OWS characters from input_string. + + 7. If input_string is empty, return dictionary. + + 8. Consume the first character of input_string; if it is not + ",", fail parsing. + + 9. Discard any leading OWS characters from input_string. + + 10. If input_string is empty, there is a trailing comma; fail + parsing. + + 3. No structured data has been found; return dictionary (which is + empty). + + Note that when duplicate Dictionary keys are encountered, all but the + last instance are ignored. + +4.2.3. Parsing an Item + + Given an ASCII string as input_string, return a (bare_item, + parameters) tuple. input_string is modified to remove the parsed + value. + + 1. Let bare_item be the result of running Parsing a Bare Item + (Section 4.2.3.1) with input_string. + + 2. Let parameters be the result of running Parsing Parameters + (Section 4.2.3.2) with input_string. + + 3. Return the tuple (bare_item, parameters). + +4.2.3.1. Parsing a Bare Item + + Given an ASCII string as input_string, return a bare Item. + input_string is modified to remove the parsed value. + + 1. If the first character of input_string is a "-" or a DIGIT, + return the result of running Parsing an Integer or Decimal + (Section 4.2.4) with input_string. + + 2. If the first character of input_string is a DQUOTE, return the + result of running Parsing a String (Section 4.2.5) with + input_string. + + 3. If the first character of input_string is an ALPHA or "*", return + the result of running Parsing a Token (Section 4.2.6) with + input_string. + + 4. If the first character of input_string is ":", return the result + of running Parsing a Byte Sequence (Section 4.2.7) with + input_string. + + 5. If the first character of input_string is "?", return the result + of running Parsing a Boolean (Section 4.2.8) with input_string. + + 6. Otherwise, the item type is unrecognized; fail parsing. + +4.2.3.2. Parsing Parameters + + Given an ASCII string as input_string, return an ordered map whose + values are bare Items. input_string is modified to remove the parsed + value. + + 1. Let parameters be an empty, ordered map. + + 2. While input_string is not empty: + + 1. If the first character of input_string is not ";", exit the + loop. + + 2. Consume the ";" character from the beginning of input_string. + + 3. Discard any leading SP characters from input_string. + + 4. Let param_key be the result of running Parsing a Key + (Section 4.2.3.3) with input_string. + + 5. Let param_value be Boolean true. + + 6. If the first character of input_string is "=": + + 1. Consume the "=" character at the beginning of + input_string. + + 2. Let param_value be the result of running Parsing a Bare + Item (Section 4.2.3.1) with input_string. + + 7. If parameters already contains a key param_key (comparing + character for character), overwrite its value with + param_value. + + 8. Otherwise, append key param_key with value param_value to + parameters. + + 3. Return parameters. + + Note that when duplicate parameter keys are encountered, all but the + last instance are ignored. + +4.2.3.3. Parsing a Key + + Given an ASCII string as input_string, return a key. input_string is + modified to remove the parsed value. + + 1. If the first character of input_string is not lcalpha or "*", + fail parsing. + + 2. Let output_string be an empty string. + + 3. While input_string is not empty: + + 1. If the first character of input_string is not one of lcalpha, + DIGIT, "_", "-", ".", or "*", return output_string. + + 2. Let char be the result of consuming the first character of + input_string. + + 3. Append char to output_string. + + 4. Return output_string. + +4.2.4. Parsing an Integer or Decimal + + Given an ASCII string as input_string, return an Integer or Decimal. + input_string is modified to remove the parsed value. + + NOTE: This algorithm parses both Integers (Section 3.3.1) and + Decimals (Section 3.3.2), and returns the corresponding structure. + + 1. Let type be "integer". + + 2. Let sign be 1. + + 3. Let input_number be an empty string. + + 4. If the first character of input_string is "-", consume it and + set sign to -1. + + 5. If input_string is empty, there is an empty integer; fail + parsing. + + 6. If the first character of input_string is not a DIGIT, fail + parsing. + + 7. While input_string is not empty: + + 1. Let char be the result of consuming the first character of + input_string. + + 2. If char is a DIGIT, append it to input_number. + + 3. Else, if type is "integer" and char is ".": + + 1. If input_number contains more than 12 characters, fail + parsing. + + 2. Otherwise, append char to input_number and set type to + "decimal". + + 4. Otherwise, prepend char to input_string, and exit the loop. + + 5. If type is "integer" and input_number contains more than 15 + characters, fail parsing. + + 6. If type is "decimal" and input_number contains more than 16 + characters, fail parsing. + + 8. If type is "integer": + + 1. Parse input_number as an integer and let output_number be + the product of the result and sign. + + 9. Otherwise: + + 1. If the final character of input_number is ".", fail parsing. + + 2. If the number of characters after "." in input_number is + greater than three, fail parsing. + + 3. Parse input_number as a decimal number and let output_number + be the product of the result and sign. + + 10. Return output_number. + +4.2.5. Parsing a String + + Given an ASCII string as input_string, return an unquoted String. + input_string is modified to remove the parsed value. + + 1. Let output_string be an empty string. + + 2. If the first character of input_string is not DQUOTE, fail + parsing. + + 3. Discard the first character of input_string. + + 4. While input_string is not empty: + + 1. Let char be the result of consuming the first character of + input_string. + + 2. If char is a backslash ("\"): + + 1. If input_string is now empty, fail parsing. + + 2. Let next_char be the result of consuming the first + character of input_string. + + 3. If next_char is not DQUOTE or "\", fail parsing. + + 4. Append next_char to output_string. + + 3. Else, if char is DQUOTE, return output_string. + + 4. Else, if char is in the range %x00-1f or %x7f-ff (i.e., it is + not in VCHAR or SP), fail parsing. + + 5. Else, append char to output_string. + + 5. Reached the end of input_string without finding a closing DQUOTE; + fail parsing. + +4.2.6. Parsing a Token + + Given an ASCII string as input_string, return a Token. input_string + is modified to remove the parsed value. + + 1. If the first character of input_string is not ALPHA or "*", fail + parsing. + + 2. Let output_string be an empty string. + + 3. While input_string is not empty: + + 1. If the first character of input_string is not in tchar, ":", + or "/", return output_string. + + 2. Let char be the result of consuming the first character of + input_string. + + 3. Append char to output_string. + + 4. Return output_string. + +4.2.7. Parsing a Byte Sequence + + Given an ASCII string as input_string, return a Byte Sequence. + input_string is modified to remove the parsed value. + + 1. If the first character of input_string is not ":", fail parsing. + + 2. Discard the first character of input_string. + + 3. If there is not a ":" character before the end of input_string, + fail parsing. + + 4. Let b64_content be the result of consuming content of + input_string up to but not including the first instance of the + character ":". + + 5. Consume the ":" character at the beginning of input_string. + + 6. If b64_content contains a character not included in ALPHA, DIGIT, + "+", "/", and "=", fail parsing. + + 7. Let binary_content be the result of base64-decoding [RFC4648] + b64_content, synthesizing padding if necessary (note the + requirements about recipient behavior below). If base64 decoding + fails, parsing fails. + + 8. Return binary_content. + + Because some implementations of base64 do not allow rejection of + encoded data that is not properly "=" padded (see [RFC4648], + Section 3.2), parsers SHOULD NOT fail when "=" padding is not + present, unless they cannot be configured to do so. + + Because some implementations of base64 do not allow rejection of + encoded data that has non-zero pad bits (see [RFC4648], Section 3.5), + parsers SHOULD NOT fail when non-zero pad bits are present, unless + they cannot be configured to do so. + + This specification does not relax the requirements in [RFC4648], + Sections 3.1 and 3.3; therefore, parsers MUST fail on characters + outside the base64 alphabet and on line feeds in encoded data. + +4.2.8. Parsing a Boolean + + Given an ASCII string as input_string, return a Boolean. input_string + is modified to remove the parsed value. + + 1. If the first character of input_string is not "?", fail parsing. + + 2. Discard the first character of input_string. + + 3. If the first character of input_string matches "1", discard the + first character, and return true. + + 4. If the first character of input_string matches "0", discard the + first character, and return false. + + 5. No value has matched; fail parsing. + +5. IANA Considerations + + This document has no IANA actions. + +6. Security Considerations + + The size of most types defined by Structured Fields is not limited; + as a result, extremely large fields could be an attack vector (e.g., + for resource consumption). Most HTTP implementations limit the sizes + of individual fields as well as the overall header or trailer section + size to mitigate such attacks. + + It is possible for parties with the ability to inject new HTTP fields + to change the meaning of a Structured Field. In some circumstances, + this will cause parsing to fail, but it is not possible to reliably + fail in all such circumstances. + +7. References + +7.1. Normative References + + [RFC0020] Cerf, V., "ASCII format for network interchange", STD 80, + RFC 20, DOI 10.17487/RFC0020, October 1969, + <https://www.rfc-editor.org/info/rfc20>. + + [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>. + + [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data + Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, + <https://www.rfc-editor.org/info/rfc4648>. + + [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", STD 68, RFC 5234, + DOI 10.17487/RFC5234, January 2008, + <https://www.rfc-editor.org/info/rfc5234>. + + [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer + Protocol (HTTP/1.1): Message Syntax and Routing", + RFC 7230, DOI 10.17487/RFC7230, June 2014, + <https://www.rfc-editor.org/info/rfc7230>. + + [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>. + +7.2. Informative References + + [IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic", + DOI 10.1109/IEEESTD.2019.8766229, IEEE 754-2019, July + 2019, <https://ieeexplore.ieee.org/document/8766229>. + + [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer + Protocol (HTTP/1.1): Semantics and Content", RFC 7231, + DOI 10.17487/RFC7231, June 2014, + <https://www.rfc-editor.org/info/rfc7231>. + + [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, + DOI 10.17487/RFC7493, March 2015, + <https://www.rfc-editor.org/info/rfc7493>. + + [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext + Transfer Protocol Version 2 (HTTP/2)", RFC 7540, + DOI 10.17487/RFC7540, May 2015, + <https://www.rfc-editor.org/info/rfc7540>. + + [RFC7541] 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>. + + [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data + Interchange Format", STD 90, RFC 8259, + DOI 10.17487/RFC8259, December 2017, + <https://www.rfc-editor.org/info/rfc8259>. + + [STD63] Yergeau, F., "UTF-8, a transformation format of ISO + 10646", STD 63, RFC 3629, November 2003, + <https://www.rfc-editor.org/info/std63>. + +Appendix A. Frequently Asked Questions + +A.1. Why Not JSON? + + Earlier proposals for Structured Fields were based upon JSON + [RFC8259]. However, constraining its use to make it suitable for + HTTP header fields required senders and recipients to implement + specific additional handling. + + For example, JSON has specification issues around large numbers and + objects with duplicate members. Although advice for avoiding these + issues is available (e.g., [RFC7493]), it cannot be relied upon. + + Likewise, JSON strings are by default Unicode strings, which have a + number of potential interoperability issues (e.g., in comparison). + Although implementers can be advised to avoid non-ASCII content where + unnecessary, this is difficult to enforce. + + Another example is JSON's ability to nest content to arbitrary + depths. Since the resulting memory commitment might be unsuitable + (e.g., in embedded and other limited server deployments), it's + necessary to limit it in some fashion; however, existing JSON + implementations have no such limits, and even if a limit is + specified, it's likely that some field definition will find a need to + violate it. + + Because of JSON's broad adoption and implementation, it is difficult + to impose such additional constraints across all implementations; + some deployments would fail to enforce them, thereby harming + interoperability. In short, if it looks like JSON, people will be + tempted to use a JSON parser/serializer on field values. + + Since a major goal for Structured Fields is to improve + interoperability and simplify implementation, these concerns led to a + format that requires a dedicated parser and serializer. + + Additionally, there were widely shared feelings that JSON doesn't + "look right" in HTTP fields. + +Appendix B. Implementation Notes + + A generic implementation of this specification should expose the top- + level serialize (Section 4.1) and parse (Section 4.2) functions. + They need not be functions; for example, it could be implemented as + an object, with methods for each of the different top-level types. + + For interoperability, it's important that generic implementations be + complete and follow the algorithms closely; see Section 1.1. To aid + this, a common test suite is being maintained by the community at + <https://github.com/httpwg/structured-field-tests>. + + Implementers should note that Dictionaries and Parameters are order- + preserving maps. Some fields may not convey meaning in the ordering + of these data types, but it should still be exposed so that it will + be available to applications that need to use it. + + Likewise, implementations should note that it's important to preserve + the distinction between Tokens and Strings. While most programming + languages have native types that map to the other types well, it may + be necessary to create a wrapper "token" object or use a parameter on + functions to assure that these types remain separate. + + The serialization algorithm is defined in a way that it is not + strictly limited to the data types defined in Section 3 in every + case. For example, Decimals are designed to take broader input and + round to allowed values. + + Implementations are allowed to limit the size of different + structures, subject to the minimums defined for each type. When a + structure exceeds an implementation limit, that structure fails + parsing or serialization. + +Acknowledgements + + Many thanks to Matthew Kerwin for his detailed feedback and careful + consideration during the development of this specification. + + Thanks also to Ian Clelland, Roy Fielding, Anne van Kesteren, Kazuho + Oku, Evert Pot, Julian Reschke, Martin Thomson, Mike West, and + Jeffrey Yasskin for their contributions. + +Authors' Addresses + + Mark Nottingham + Fastly + Prahran VIC + Australia + + Email: mnot@mnot.net + URI: https://www.mnot.net/ + + + Poul-Henning Kamp + The Varnish Cache Project + + Email: phk@varnish-cache.org |