| draft-ietf-httpbis-header-structure-10.txt | draft-ietf-httpbis-header-structure-11.txt | |||
|---|---|---|---|---|
| HTTP M. Nottingham | HTTP M. Nottingham | |||
| Internet-Draft Fastly | Internet-Draft Fastly | |||
| Intended status: Standards Track P-H. Kamp | Intended status: Standards Track P-H. Kamp | |||
| Expires: October 19, 2019 The Varnish Cache Project | Expires: January 9, 2020 The Varnish Cache Project | |||
| April 17, 2019 | July 8, 2019 | |||
| Structured Headers for HTTP | Structured Headers for HTTP | |||
| draft-ietf-httpbis-header-structure-10 | draft-ietf-httpbis-header-structure-11 | |||
| Abstract | Abstract | |||
| This document describes a set of data types and algorithms associated | This document describes a set of data types and associated algorithms | |||
| with them that are intended to make it easier and safer to define and | that are intended to make it easier and safer to define and handle | |||
| handle HTTP header fields. It is intended for use by new | HTTP header fields. It is intended for use by specifications of new | |||
| specifications of HTTP header fields as well as revisions of existing | HTTP header fields that wish to use a common syntax that is more | |||
| header field specifications when doing so does not cause | restrictive than traditional HTTP field values. | |||
| interoperability issues. | ||||
| Note to Readers | Note to Readers | |||
| _RFC EDITOR: please remove this section before publication_ | _RFC EDITOR: please remove this section before publication_ | |||
| Discussion of this draft takes place on the HTTP working group | Discussion of this draft takes place on the HTTP working group | |||
| mailing list (ietf-http-wg@w3.org), which is archived at | mailing list (ietf-http-wg@w3.org), which is archived at | |||
| https://lists.w3.org/Archives/Public/ietf-http-wg/ [1]. | https://lists.w3.org/Archives/Public/ietf-http-wg/ [1]. | |||
| Working Group information can be found at https://httpwg.github.io/ | Working Group information can be found at https://httpwg.github.io/ | |||
| skipping to change at page 2, line 10 ¶ | skipping to change at page 2, line 10 ¶ | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on October 19, 2019. | This Internet-Draft will expire on January 9, 2020. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2019 IETF Trust and the persons identified as the | Copyright (c) 2019 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
| (https://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| publication of this document. Please review these documents | publication of this document. Please review these documents | |||
| skipping to change at page 2, line 33 ¶ | skipping to change at page 2, line 33 ¶ | |||
| include Simplified BSD License text as described in Section 4.e of | include Simplified BSD License text as described in Section 4.e of | |||
| the Trust Legal Provisions and are provided without warranty as | the Trust Legal Provisions and are provided without warranty as | |||
| described in the Simplified BSD License. | described in the Simplified BSD License. | |||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 1.1. Intentionally Strict Processing . . . . . . . . . . . . . 4 | 1.1. Intentionally Strict Processing . . . . . . . . . . . . . 4 | |||
| 1.2. Notational Conventions . . . . . . . . . . . . . . . . . 4 | 1.2. Notational Conventions . . . . . . . . . . . . . . . . . 4 | |||
| 2. Defining New Structured Headers . . . . . . . . . . . . . . . 5 | 2. Defining New Structured Headers . . . . . . . . . . . . . . . 5 | |||
| 3. Structured Header Data Types . . . . . . . . . . . . . . . . 7 | 3. Structured Header Data Types . . . . . . . . . . . . . . . . 6 | |||
| 3.1. Dictionaries . . . . . . . . . . . . . . . . . . . . . . 7 | 3.1. Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 3.2. Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 7 | 3.2. Dictionaries . . . . . . . . . . . . . . . . . . . . . . 7 | |||
| 3.3. Lists of Lists . . . . . . . . . . . . . . . . . . . . . 8 | 3.3. Items . . . . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 3.4. Parameterised Lists . . . . . . . . . . . . . . . . . . . 8 | 3.4. Integers . . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 3.5. Items . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 3.5. Floats . . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 3.6. Integers . . . . . . . . . . . . . . . . . . . . . . . . 9 | 3.6. Strings . . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 3.7. Floats . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 3.7. Tokens . . . . . . . . . . . . . . . . . . . . . . . . . 10 | |||
| 3.8. Strings . . . . . . . . . . . . . . . . . . . . . . . . . 10 | 3.8. Byte Sequences . . . . . . . . . . . . . . . . . . . . . 10 | |||
| 3.9. Tokens . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 3.9. Booleans . . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 3.10. Byte Sequences . . . . . . . . . . . . . . . . . . . . . 11 | 4. Working With Structured Headers in Textual HTTP Headers . . . 11 | |||
| 3.11. Booleans . . . . . . . . . . . . . . . . . . . . . . . . 11 | 4.1. Serializing Structured Headers . . . . . . . . . . . . . 11 | |||
| 4. Structured Headers in HTTP/1 . . . . . . . . . . . . . . . . 12 | 4.2. Parsing Header Fields into Structured Headers . . . . . . 17 | |||
| 4.1. Serialising Structured Headers into HTTP/1 . . . . . . . 12 | 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 26 | |||
| 4.2. Parsing HTTP/1 Header Fields into Structured Headers . . 18 | 6. Security Considerations . . . . . . . . . . . . . . . . . . . 26 | |||
| 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 27 | 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 26 | |||
| 6. Security Considerations . . . . . . . . . . . . . . . . . . . 28 | 7.1. Normative References . . . . . . . . . . . . . . . . . . 26 | |||
| 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 28 | 7.2. Informative References . . . . . . . . . . . . . . . . . 27 | |||
| 7.1. Normative References . . . . . . . . . . . . . . . . . . 28 | 7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 28 | |||
| 7.2. Informative References . . . . . . . . . . . . . . . . . 29 | Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 28 | |||
| 7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 29 | Appendix B. Frequently Asked Questions . . . . . . . . . . . . . 28 | |||
| Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 30 | B.1. Why not JSON? . . . . . . . . . . . . . . . . . . . . . . 28 | |||
| Appendix B. Frequently Asked Questions . . . . . . . . . . . . . 30 | B.2. Structured Headers don't "fit" my data. . . . . . . . . . 29 | |||
| B.1. Why not JSON? . . . . . . . . . . . . . . . . . . . . . . 30 | Appendix C. Implementation Notes . . . . . . . . . . . . . . . . 29 | |||
| B.2. Structured Headers don't "fit" my data. . . . . . . . . . 30 | Appendix D. Changes . . . . . . . . . . . . . . . . . . . . . . 30 | |||
| B.3. What should generic Structured Headers implementations | D.1. Since draft-ietf-httpbis-header-structure-10 . . . . . . 30 | |||
| expose? . . . . . . . . . . . . . . . . . . . . . . . . . 31 | D.2. Since draft-ietf-httpbis-header-structure-09 . . . . . . 30 | |||
| Appendix C. Changes . . . . . . . . . . . . . . . . . . . . . . 31 | D.3. Since draft-ietf-httpbis-header-structure-08 . . . . . . 31 | |||
| C.1. Since draft-ietf-httpbis-header-structure-09 . . . . . . 31 | D.4. Since draft-ietf-httpbis-header-structure-07 . . . . . . 31 | |||
| C.2. Since draft-ietf-httpbis-header-structure-08 . . . . . . 32 | D.5. Since draft-ietf-httpbis-header-structure-06 . . . . . . 32 | |||
| C.3. Since draft-ietf-httpbis-header-structure-07 . . . . . . 32 | D.6. Since draft-ietf-httpbis-header-structure-05 . . . . . . 32 | |||
| C.4. Since draft-ietf-httpbis-header-structure-06 . . . . . . 33 | D.7. Since draft-ietf-httpbis-header-structure-04 . . . . . . 32 | |||
| C.5. Since draft-ietf-httpbis-header-structure-05 . . . . . . 33 | D.8. Since draft-ietf-httpbis-header-structure-03 . . . . . . 32 | |||
| C.6. Since draft-ietf-httpbis-header-structure-04 . . . . . . 33 | D.9. Since draft-ietf-httpbis-header-structure-02 . . . . . . 32 | |||
| C.7. Since draft-ietf-httpbis-header-structure-03 . . . . . . 33 | D.10. Since draft-ietf-httpbis-header-structure-01 . . . . . . 33 | |||
| C.8. Since draft-ietf-httpbis-header-structure-02 . . . . . . 33 | D.11. Since draft-ietf-httpbis-header-structure-00 . . . . . . 33 | |||
| C.9. Since draft-ietf-httpbis-header-structure-01 . . . . . . 34 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 33 | |||
| C.10. Since draft-ietf-httpbis-header-structure-00 . . . . . . 34 | ||||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 34 | ||||
| 1. Introduction | 1. Introduction | |||
| Specifying the syntax of new HTTP header fields is an onerous task; | Specifying the syntax of new HTTP header fields is an onerous task; | |||
| even with the guidance in [RFC7231], Section 8.3.1, there are many | even with the guidance in [RFC7231], Section 8.3.1, there are many | |||
| decisions - and pitfalls - for a prospective HTTP header field | decisions - and pitfalls - for a prospective HTTP header field | |||
| author. | author. | |||
| Once a header field is defined, bespoke parsers and serialisers often | Once a header field is defined, bespoke parsers and serializers often | |||
| need to be written, because each header has slightly different | need to be written, because each header has slightly different | |||
| handling of what looks like common syntax. | handling of what looks like common syntax. | |||
| This document introduces a set of common data structures for use in | This document introduces a set of common data structures for use in | |||
| HTTP header field values to address these problems. In particular, | definitions of new HTTP header field values to address these | |||
| it defines a generic, abstract model for header field values, along | problems. In particular, it defines a generic, abstract model for | |||
| with a concrete serialisation for expressing that model in HTTP/1 | header field values, along with a concrete serialisation for | |||
| [RFC7230] header fields. | expressing that model in textual HTTP [RFC7230] header fields. | |||
| HTTP headers that are defined as "Structured Headers" use the types | HTTP headers that are defined as "Structured Headers" use the types | |||
| defined in this specification to define their syntax and basic | defined in this specification to define their syntax and basic | |||
| handling rules, thereby simplifying both their definition by | handling rules, thereby simplifying both their definition by | |||
| specification writers and handling by implementations. | specification writers and handling by implementations. | |||
| Additionally, future versions of HTTP can define alternative | Additionally, future versions of HTTP can define alternative | |||
| serialisations of the abstract model of these structures, allowing | serialisations of the abstract model of these structures, allowing | |||
| headers that use it to be transmitted more efficiently without being | headers that use it to be transmitted more efficiently without being | |||
| redefined. | redefined. | |||
| Note that it is not a goal of this document to redefine the syntax of | Note that it is not a goal of this document to redefine the syntax of | |||
| existing HTTP headers; the mechanisms described herein are only | existing HTTP headers; the mechanisms described herein are only | |||
| intended to be used with headers that explicitly opt into them. | intended to be used with headers that explicitly opt into them. | |||
| To specify a header field that is a Structured Header, see Section 2. | Section 2 describes how to specify a Structured Header. | |||
| Section 3 defines a number of abstract data types that can be used in | Section 3 defines a number of abstract data types that can be used in | |||
| Structured Headers. | Structured Headers. Those abstract types can be serialized into and | |||
| parsed from textual HTTP headers using the algorithms described in | ||||
| Those abstract types can be serialised into and parsed from textual | Section 4. | |||
| headers - such as those used in HTTP/1 - using the algorithms | ||||
| described in Section 4. | ||||
| 1.1. Intentionally Strict Processing | 1.1. Intentionally Strict Processing | |||
| This specification intentionally defines strict parsing and | This specification intentionally defines strict parsing and | |||
| serialisation behaviours using step-by-step algorithms; the only | serialisation behaviours using step-by-step algorithms; the only | |||
| error handling defined is to fail the operation altogether. | error handling defined is to fail the operation altogether. | |||
| This is designed to encourage faithful implementation and therefore | It is designed to encourage faithful implementation and therefore | |||
| good interoperability. Therefore, implementations that try to be | good interoperability. Therefore, an implementation that tried to be | |||
| "helpful" by being more tolerant of input are doing a disservice to | "helpful" by being more tolerant of input would make interoperability | |||
| the overall community, since it will encourage other implementations | worse, since that would create pressure on other implementations to | |||
| to implement similar (but likely subtly different) workarounds. | implement similar (but likely subtly different) workarounds. | |||
| In other words, strict processing is an intentional feature of this | In other words, strict processing is an intentional feature of this | |||
| specification; it allows non-conformant input to be discovered and | specification; it allows non-conformant input to be discovered and | |||
| corrected early, and avoids both interoperability and security issues | corrected by the producer early, and avoids both interoperability and | |||
| that might otherwise result. | security issues that might otherwise result. | |||
| Note that as a result of this strictness, if a header field is | Note that as a result of this strictness, if a header field is | |||
| appended to by multiple parties (e.g., intermediaries, or different | appended to by multiple parties (e.g., intermediaries, or different | |||
| components in the sender), it could be that an error in one party's | components in the sender), an error in one party's value is likely to | |||
| value causes the entire header field to fail parsing. | cause the entire header field to fail parsing. | |||
| 1.2. Notational Conventions | 1.2. Notational Conventions | |||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
| "OPTIONAL" in this document are to be interpreted as described in BCP | "OPTIONAL" in this document are to be interpreted as described in BCP | |||
| 14 [RFC2119] [RFC8174] when, and only when, they appear in all | 14 [RFC2119] [RFC8174] when, and only when, they appear in all | |||
| capitals, as shown here. | capitals, as shown here. | |||
| This document uses the Augmented Backus-Naur Form (ABNF) notation of | ||||
| [RFC5234], including the VCHAR, SP, DIGIT, ALPHA and DQUOTE rules | ||||
| from that document. It also includes the OWS rule from [RFC7230]. | ||||
| This document uses algorithms to specify parsing and serialisation | This document uses algorithms to specify parsing and serialisation | |||
| behaviours, and ABNF to illustrate expected syntax in HTTP/1-style | behaviours, and the Augmented Backus-Naur Form (ABNF) notation of | |||
| header fields. | [RFC5234] to illustrate expected syntax in textual HTTP header | |||
| fields. In doing so, uses the VCHAR, SP, DIGIT, ALPHA and DQUOTE | ||||
| rules from [RFC5234]. It also includes the OWS rule from [RFC7230]. | ||||
| For parsing from HTTP/1 header fields, implementations MUST follow | When parsing from textual HTTP header fields, implementations MUST | |||
| the algorithms, but MAY vary in implementation so as the behaviours | follow the algorithms, but MAY vary in implementation so as the | |||
| are indistinguishable from specified behaviour. If there is | behaviours are indistinguishable from specified behaviour. If there | |||
| disagreement between the parsing algorithms and ABNF, the specified | is disagreement between the parsing algorithms and ABNF, the | |||
| algorithms take precedence. In some places, the algorithms are | specified algorithms take precedence. In some places, the algorithms | |||
| "greedy" with whitespace, but this should not affect conformance. | are "greedy" with whitespace, but this should not affect conformance. | |||
| For serialisation to HTTP/1 header fields, the ABNF illustrates the | For serialisation to textual header fields, the ABNF illustrates the | |||
| range of acceptable wire representations with as much fidelity as | range of acceptable wire representations with as much fidelity as | |||
| possible, and the algorithms define the recommended way to produce | possible, and the algorithms define the recommended way to produce | |||
| them. Implementations MAY vary from the specified behaviour so long | them. Implementations MAY vary from the specified behaviour so long | |||
| as the output still matches the ABNF. | as the output still matches the ABNF. | |||
| 2. Defining New Structured Headers | 2. Defining New Structured Headers | |||
| To define a HTTP header as a structured header, its specification | To define a HTTP header as a structured header, its specification | |||
| needs to: | needs to: | |||
| skipping to change at page 5, line 43 ¶ | skipping to change at page 5, line 34 ¶ | |||
| semantics. Syntax definitions are encouraged to use the ABNF | semantics. Syntax definitions are encouraged to use the ABNF | |||
| rules beginning with "sh-" defined in this specification. | rules beginning with "sh-" defined in this specification. | |||
| o Specify any additional constraints upon the syntax of the | o Specify any additional constraints upon the syntax of the | |||
| structured used, as well as the consequences when those | structured used, as well as the consequences when those | |||
| constraints are violated. When Structured Headers parsing fails, | constraints are violated. When Structured Headers parsing fails, | |||
| the header is discarded (see Section 4.2); in most situations, | the header is discarded (see Section 4.2); in most situations, | |||
| header-specific constraints should do likewise. | header-specific constraints should do likewise. | |||
| Note that a header field definition cannot relax the requirements of | Note that a header field definition cannot relax the requirements of | |||
| a structure or its processing because doing so would preclude | this specification because doing so would preclude handling by | |||
| handling by generic software; they can only add additional | generic software; they can only add additional constraints (for | |||
| constraints. Likewise, header field definitions should use | example, on the numeric range of integers and floats, the format of | |||
| Structured Headers for the entire header field value, not a portion | strings and tokens, or the number of items in a list). Likewise, | |||
| thereof. | header field definitions should use Structured Headers for the entire | |||
| header field value, not a portion thereof. | ||||
| For example: | This specification defines minimums for the length or number of | |||
| various structures supported by Structured Headers implementations. | ||||
| It does not specify maximum sizes in most cases, but header authors | ||||
| should be aware that HTTP implementations do impose various limits on | ||||
| the size of individual header fields, the total number of fields, | ||||
| and/or the size of the entire header block. | ||||
| # Foo-Example Header | For example, | |||
| 42. Foo-Example Header | ||||
| The Foo-Example HTTP header field conveys information about how | The Foo-Example HTTP header field conveys information about how | |||
| much Foo the message has. | much Foo the message has. | |||
| Foo-Example is a Structured Header [RFCxxxx]. Its value MUST be a | Foo-Example is a Structured Header [RFCxxxx]. Its value MUST be a | |||
| dictionary ([RFCxxxx], Section Y.Y). Its ABNF is: | dictionary ([RFCxxxx], Section Y.Y). Its ABNF is: | |||
| Foo-Example = sh-dictionary | Foo-Example = sh-dictionary | |||
| The dictionary MUST contain: | The dictionary MUST contain: | |||
| * Exactly one member whose key is "foo", and whose value is an | * Exactly one member whose name is "foo", and whose value is an | |||
| integer ([RFCxxxx], Section Y.Y), indicating the number of foos | integer ([RFCxxxx], Section Y.Y), indicating the number of foos | |||
| in the message. | in the message. | |||
| * Exactly one member whose key is "barUrls", and whose value is a | * Exactly one member whose name is "barUrl", and whose value is a | |||
| string ([RFCxxxx], Section Y.Y), conveying the Bar URLs for the | string ([RFCxxxx], Section Y.Y), conveying the Bar URL for the | |||
| message. See below for processing requirements. | message. See below for processing requirements. | |||
| If the parsed header field does not contain both, it MUST be | If the parsed header field does not contain both, it MUST be | |||
| ignored. | ignored. | |||
| "foo" MUST be between 0 and 10, inclusive; other values MUST cause | "foo" MUST be between 0 and 10, inclusive; other values MUST cause | |||
| the header to be ignored. | the header to be ignored. | |||
| "barUrls" contains a space-separated list of URI-references | "barUrl" contains a URI-reference ([RFC3986], Section 4.1). | |||
| ([RFC3986], Section 4.1): | ||||
| barURLs = URI-reference *( 1*SP URI-reference ) | ||||
| If a member of barURLs is not a valid URI-reference, it MUST cause | ||||
| that value to be ignored. | ||||
| If a member of barURLs is a relative reference ([RFC3986], | ||||
| Section 4.2), it MUST be resolved ([RFC3986], Section 5) before | ||||
| being used. | ||||
| This specification defines minimums for the length or number of | If barURL is not a valid URI-reference, it MUST be ignored. | |||
| various structures supported by Structured Headers implementations. | If barURL is a relative reference ([RFC3986], Section 4.2), | |||
| It does not specify maximum sizes in most cases, but header authors | it MUST be resolved ([RFC3986], Section 5) before being used. | |||
| should be aware that HTTP implementations do impose various limits on | ||||
| the size of individual header fields, the total number of fields, | ||||
| and/or the size of the entire header block. | ||||
| 3. Structured Header Data Types | 3. Structured Header Data Types | |||
| This section defines the abstract value types that can be composed | This section defines the abstract value types that can be composed | |||
| into Structured Headers. The ABNF provided represents the on-wire | into Structured Headers. The ABNF provided represents the on-wire | |||
| format in HTTP/1. | format in HTTP. | |||
| 3.1. Dictionaries | ||||
| Dictionaries are ordered maps of key-value pairs, where the keys are | ||||
| short, textual strings and the values are items (Section 3.5). There | ||||
| can be one or more members, and keys are required to be unique. | ||||
| 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 in HTTP/1 headers is: | ||||
| sh-dictionary = dict-member *( OWS "," OWS dict-member ) | ||||
| dict-member = member-name "=" member-value | ||||
| member-name = key | ||||
| member-value = sh-item | ||||
| key = lcalpha *( lcalpha / DIGIT / "_" / "-" ) | ||||
| lcalpha = %x61-7A ; a-z | ||||
| In HTTP/1, keys and values are separated by "=" (without whitespace), | ||||
| and key/value pairs are separated by a comma with optional | ||||
| whitespace. For example: | ||||
| Example-DictHeader: en="Applepie", da=*w4ZibGV0w6ZydGU=* | ||||
| Typically, a header field specification will define the semantics of | 3.1. Lists | |||
| individual keys, as well as whether their presence is required or | ||||
| optional. Recipients MUST ignore keys that are undefined or unknown, | ||||
| unless the header field's specification specifically disallows them. | ||||
| Parsers MUST support dictionaries containing at least 1024 key/value | Lists are arrays of zero or more members, each of which can be an | |||
| pairs, and dictionary keys with at least 64 characters. | item (Section 3.3) or an inner list (an array of zero or more items). | |||
| 3.2. Lists | Each member of the top-level list can also have associated parameters | |||
| - an ordered map of key-value pairs where the keys are short, textual | ||||
| strings and the values are items (Section 3.3). There can be zero or | ||||
| more parameters on a member, and their keys are required to be unique | ||||
| within that scope. | ||||
| Lists are arrays of items (Section 3.5) with one or more members. | The ABNF for lists is: | |||
| The ABNF for lists in HTTP/1 headers is: | sh-list = list-member *( OWS "," OWS list-member ) | |||
| list-member = ( sh-item / inner-list ) *parameter | ||||
| inner-list = "(" OWS [ sh-item *( SP sh-item ) OWS ] ")" | ||||
| parameter = OWS ";" OWS param-name [ "=" param-value ] | ||||
| param-name = key | ||||
| key = lcalpha *( lcalpha / DIGIT / "_" / "-" ) | ||||
| lcalpha = %x61-7A ; a-z | ||||
| param-value = sh-item | ||||
| sh-list = list-member *( OWS "," OWS list-member ) | In textual HTTP headers, each member is separated by a comma and | |||
| list-member = sh-item | optional whitespace. For example, a header field whose value is | |||
| In HTTP/1, each member is separated by a comma and optional | defined as a list of strings could look like: | |||
| whitespace. For example, a header field whose value is defined as a | ||||
| list of strings could look like: | ||||
| Example-StrListHeader: "foo", "bar", "It was the best of times." | Example-StrListHeader: "foo", "bar", "It was the best of times." | |||
| Header specifications can constrain the types of individual values if | In textual HTTP headers, inner lists are denoted by surrounding | |||
| necessary. | parenthesis, and have their values delimited by a single space. A | |||
| header field whose value is defined as a list of lists of strings | ||||
| could look like: | ||||
| Parsers MUST support lists containing at least 1024 members. | Example-StrListListHeader: ("foo" "bar"), ("baz"), ("bat" "one"), () | |||
| 3.3. Lists of Lists | Note that the last member in this example is an empty inner list. | |||
| Lists of Lists are arrays of arrays containing items (Section 3.5). | In textual HTTP headers, members' parameters are separated from the | |||
| member and each other by semicolons. For example: | ||||
| The ABNF for lists of lists in HTTP/1 headers is: | Example-ParamListHeader: abc_123;a=1;b=2; cdef_456, (ghi jkl);q="9";r="w" | |||
| sh-listlist = inner-list *( OWS "," OWS inner-list ) | Parsers MUST support lists containing at least 1024 members, support | |||
| inner-list = list-member *( OWS ";" OWS list-member ) | members with at least 256 parameters, support inner-lists containing | |||
| at least 256 members, and support parameter keys with at least 64 | ||||
| characters. | ||||
| In HTTP/1, each inner-list is separated by a comma and optional | Header specifications can constrain the types of individual list | |||
| whitespace, and members of the inner-list are separated by semicolons | values (including that of individual inner-list members and | |||
| and optional whitespace. For example, a header field whose value is | parameters) if necessary. | |||
| defined as a list of lists of strings could look like: | ||||
| Example-StrListListHeader: "foo";"bar", "baz", "bat"; "one" | 3.2. Dictionaries | |||
| Header specifications can constrain the types of individual inner- | Dictionaries are ordered maps of name-value pairs, where the names | |||
| list values if necessary. | are short, textual strings and the values are items (Section 3.3) or | |||
| arrays of items. There can be zero or more members, and their names | ||||
| are required to be unique within the scope of the dictionary they | ||||
| occur within. | ||||
| Parsers MUST support lists of lists containing at least 1024 members, | Implementations MUST provide access to dictionaries both by index and | |||
| and inner-lists containing at least 256 members. | by name. Specifications MAY use either means of accessing the | |||
| members. | ||||
| 3.4. Parameterised Lists | The ABNF for dictionaries in textual HTTP headers is: | |||
| Parameterised Lists are arrays of parameterised identifiers, with one | sh-dictionary = dict-member *( OWS "," OWS dict-member ) | |||
| or more members. | dict-member = member-name "=" member-value | |||
| member-name = key | ||||
| member-value = sh-item / inner-list | ||||
| A parameterised identifier is a primary identifier (a Section 3.9}) | In textual HTTP headers, members are separated by a comma with | |||
| with associated parameters, an ordered map of key-value pairs where | optional whitespace, while names and values are separated by "=" | |||
| the keys are short, textual strings and the values are items | (without whitespace). For example: | |||
| (Section 3.5). There can be zero or more parameters, and keys are | ||||
| required to be unique. | ||||
| The ABNF for parameterised lists in HTTP/1 headers is: | Example-DictHeader: en="Applepie", da=*w4ZibGV0w6ZydGU=* | |||
| sh-param-list = param-item *( OWS "," OWS param-item ) | A dictionary with a member whose value is an inner-list of tokens: | |||
| param-item = primary-id *parameter | ||||
| primary-id = sh-token | ||||
| parameter = OWS ";" OWS param-name [ "=" param-value ] | ||||
| param-name = key | ||||
| param-value = sh-item | ||||
| In HTTP/1, each param-id is separated by a comma and optional | Example-DictListHeader: rating=1.5, feelings=(joy sadness) | |||
| whitespace (as in Lists), and the parameters are separated by | ||||
| semicolons. For example: | ||||
| Example-ParamListHeader: abc_123;a=1;b=2; cdef_456, ghi;q="9";r="w" | Typically, a header field specification will define the semantics of | |||
| individual member names, as well as whether their presence is | ||||
| required or optional. Recipients MUST ignore names that are | ||||
| undefined or unknown, unless the header field's specification | ||||
| specifically disallows them. | ||||
| Parsers MUST support parameterised lists containing at least 1024 | Parsers MUST support dictionaries containing at least 1024 name/value | |||
| members, support members with at least 256 parameters, and support | pairs, and names with at least 64 characters. | |||
| parameter keys with at least 64 characters. | ||||
| 3.5. Items | 3.3. Items | |||
| An item is can be a integer (Section 3.6), float (Section 3.7), | An item is can be a integer (Section 3.4), float (Section 3.5), | |||
| string (Section 3.8), token (Section 3.9), byte sequence | string (Section 3.6), token (Section 3.7), byte sequence | |||
| (Section 3.10), or Boolean (Section 3.11). | (Section 3.8), or Boolean (Section 3.9). | |||
| The ABNF for items in HTTP/1 headers is: | The ABNF for items in textual HTTP headers is: | |||
| sh-item = sh-integer / sh-float / sh-string / sh-token / sh-binary | sh-item = sh-integer / sh-float / sh-string / sh-token / sh-binary | |||
| / sh-boolean | / sh-boolean | |||
| 3.6. Integers | 3.4. Integers | |||
| Integers have a range of -999,999,999,999,999 to 999,999,999,999,999 | Integers have a range of -999,999,999,999,999 to 999,999,999,999,999 | |||
| inclusive (i.e., up to fifteen digits, signed). | inclusive (i.e., up to fifteen digits, signed), for IEEE 754 | |||
| compatibility ([IEEE754]). | ||||
| The ABNF for integers in HTTP/1 headers is: | The ABNF for integers in textual HTTP headers is: | |||
| sh-integer = ["-"] 1*15DIGIT | sh-integer = ["-"] 1*15DIGIT | |||
| For example: | For example: | |||
| Example-IntegerHeader: 42 | Example-IntegerHeader: 42 | |||
| 3.7. Floats | Note that commas in integers are used in this section's prose only | |||
| for readability; they are not valid in the wire format. | ||||
| 3.5. Floats | ||||
| Floats are integers with a fractional part, that can be stored as | Floats are integers with a fractional part, that can be stored as | |||
| IEEE 754 double precision numbers (binary64) ([IEEE754]). | IEEE 754 double precision numbers (binary64) ([IEEE754]). | |||
| The ABNF for floats in HTTP/1 headers is: | The ABNF for floats in textual HTTP headers is: | |||
| sh-float = ["-"] ( | sh-float = ["-"] ( | |||
| DIGIT "." 1*14DIGIT / | DIGIT "." 1*14DIGIT / | |||
| 2DIGIT "." 1*13DIGIT / | 2DIGIT "." 1*13DIGIT / | |||
| 3DIGIT "." 1*12DIGIT / | 3DIGIT "." 1*12DIGIT / | |||
| 4DIGIT "." 1*11DIGIT / | 4DIGIT "." 1*11DIGIT / | |||
| 5DIGIT "." 1*10DIGIT / | 5DIGIT "." 1*10DIGIT / | |||
| 6DIGIT "." 1*9DIGIT / | 6DIGIT "." 1*9DIGIT / | |||
| 7DIGIT "." 1*8DIGIT / | 7DIGIT "." 1*8DIGIT / | |||
| 8DIGIT "." 1*7DIGIT / | 8DIGIT "." 1*7DIGIT / | |||
| skipping to change at page 10, line 26 ¶ | skipping to change at page 9, line 42 ¶ | |||
| 11DIGIT "." 1*4DIGIT / | 11DIGIT "." 1*4DIGIT / | |||
| 12DIGIT "." 1*3DIGIT / | 12DIGIT "." 1*3DIGIT / | |||
| 13DIGIT "." 1*2DIGIT / | 13DIGIT "." 1*2DIGIT / | |||
| 14DIGIT "." 1DIGIT ) | 14DIGIT "." 1DIGIT ) | |||
| For example, a header whose value is defined as a float could look | For example, a header whose value is defined as a float could look | |||
| like: | like: | |||
| Example-FloatHeader: 4.5 | Example-FloatHeader: 4.5 | |||
| 3.8. Strings | 3.6. Strings | |||
| Strings are zero or more printable ASCII [RFC0020] characters (i.e., | Strings are zero or more printable ASCII [RFC0020] characters (i.e., | |||
| the range 0x20 to 0x7E). Note that this excludes tabs, newlines, | the range 0x20 to 0x7E). Note that this excludes tabs, newlines, | |||
| carriage returns, etc. | carriage returns, etc. | |||
| The ABNF for strings in HTTP/1 headers is: | The ABNF for strings in textual HTTP headers is: | |||
| sh-string = DQUOTE *(chr) DQUOTE | sh-string = DQUOTE *(chr) DQUOTE | |||
| chr = unescaped / escaped | chr = unescaped / escaped | |||
| unescaped = %x20-21 / %x23-5B / %x5D-7E | unescaped = %x20-21 / %x23-5B / %x5D-7E | |||
| escaped = "\" ( DQUOTE / "\" ) | escaped = "\" ( DQUOTE / "\" ) | |||
| In HTTP/1 headers, strings are delimited with double quotes, using a | In textual HTTP headers, strings are delimited with double quotes, | |||
| backslash ("\") to escape double quotes and backslashes. For | using a backslash ("\") to escape double quotes and backslashes. For | |||
| example: | example: | |||
| Example-StringHeader: "hello world" | Example-StringHeader: "hello world" | |||
| Note that strings only use DQUOTE as a delimiter; single quotes do | Note that strings only use DQUOTE as a delimiter; single quotes do | |||
| not delimit strings. Furthermore, only DQUOTE and "\" can be | not delimit strings. Furthermore, only DQUOTE and "\" can be | |||
| escaped; other sequences MUST cause parsing to fail. | escaped; other sequences MUST cause parsing to fail. | |||
| Unicode is not directly supported in this document, because it causes | Unicode is not directly supported in this document, because it causes | |||
| a number of interoperability issues, and - with few exceptions - | a number of interoperability issues, and - with few exceptions - | |||
| header values do not require it. | header values do not require it. | |||
| When it is necessary for a field value to convey non-ASCII string | When it is necessary for a field value to convey non-ASCII string | |||
| content, a byte sequence (Section 3.10) SHOULD be specified, along | content, a byte sequence (Section 3.8) SHOULD be specified, along | |||
| with a character encoding (preferably UTF-8). | with a character encoding (preferably UTF-8). | |||
| Parsers MUST support strings with at least 1024 characters. | Parsers MUST support strings with at least 1024 characters. | |||
| 3.9. Tokens | 3.7. Tokens | |||
| Tokens are short textual words; their abstract model is identical to | Tokens are short textual words; their abstract model is identical to | |||
| their expression in the textual HTTP serialisation. | their expression in the textual HTTP serialisation. | |||
| The ABNF for tokens in HTTP/1 headers is: | The ABNF for tokens in textual HTTP headers is: | |||
| sh-token = ALPHA *( ALPHA / DIGIT / "_" / "-" / "." / ":" / "%" / "*" / "/" ) | sh-token = ALPHA | |||
| *( ALPHA / DIGIT / "_" / "-" / "." / ":" / "%" | ||||
| / "*" / "/" ) | ||||
| Parsers MUST support tokens with at least 512 characters. | Parsers MUST support tokens with at least 512 characters. | |||
| Note that a Structured Header token is not the same as the "token" | Note that a Structured Header token is not the same as the "token" | |||
| ABNF rule defined in [RFC7230]. | ABNF rule defined in [RFC7230]. | |||
| 3.10. Byte Sequences | 3.8. Byte Sequences | |||
| Byte sequences can be conveyed in Structured Headers. | Byte sequences can be conveyed in Structured Headers. | |||
| The ABNF for a byte sequence in HTTP/1 headers is: | The ABNF for a byte sequence in textual HTTP headers is: | |||
| sh-binary = "*" *(base64) "*" | sh-binary = "*" *(base64) "*" | |||
| base64 = ALPHA / DIGIT / "+" / "/" / "=" | base64 = ALPHA / DIGIT / "+" / "/" / "=" | |||
| In HTTP/1 headers, a byte sequence is delimited with asterisks and | In textual HTTP headers, a byte sequence is delimited with asterisks | |||
| encoded using base64 ([RFC4648], Section 4). For example: | and encoded using base64 ([RFC4648], Section 4). For example: | |||
| Example-BinaryHdr: *cHJldGVuZCB0aGlzIGlzIGJpbmFyeSBjb250ZW50Lg==* | Example-BinaryHdr: *cHJldGVuZCB0aGlzIGlzIGJpbmFyeSBjb250ZW50Lg==* | |||
| Parsers MUST support byte sequences with at least 16384 octets after | Parsers MUST support byte sequences with at least 16384 octets after | |||
| decoding. | decoding. | |||
| 3.11. Booleans | 3.9. Booleans | |||
| Boolean values can be conveyed in Structured Headers. | Boolean values can be conveyed in Structured Headers. | |||
| The ABNF for a Boolean in HTTP/1 headers is: | The ABNF for a Boolean in textual HTTP headers is: | |||
| sh-boolean = "?" boolean | sh-boolean = "?" boolean | |||
| boolean = "0" / "1" | boolean = "0" / "1" | |||
| In HTTP/1 headers, a boolean is indicated with a leading "?" | In textual HTTP headers, a boolean is indicated with a leading "?" | |||
| character. For example: | character. For example: | |||
| Example-BoolHdr: ?1 | Example-BoolHdr: ?1 | |||
| 4. Structured Headers in HTTP/1 | 4. Working With Structured Headers in Textual HTTP Headers | |||
| This section defines how to serialise and parse Structured Headers in | This section defines how to serialize and parse Structured Headers in | |||
| HTTP/1 textual header fields, and protocols compatible with them | textual header fields, and protocols compatible with them (e.g., in | |||
| (e.g., in HTTP/2 [RFC7540] before HPACK [RFC7541] is applied). | HTTP/2 [RFC7540] before HPACK [RFC7541] is applied). | |||
| 4.1. Serialising Structured Headers into HTTP/1 | 4.1. Serializing Structured Headers | |||
| Given a structured defined in this specification: | Given a structure defined in this specification: | |||
| 1. If the structure is a dictionary, return the result of | 1. If the structure is a dictionary or list and its value is empty | |||
| Serialising a Dictionary (Section 4.1.1). | (i.e., it has no members), do not send the serialize field at all | |||
| (i.e., omit both the field-name and field-value). | ||||
| 2. If the structure is a parameterised list, return the result of | 2. If the structure is a dictionary, let output_string be the result | |||
| Serialising a Parameterised List (Section 4.1.4). | of Serializing a Dictionary (Section 4.1.2). | |||
| 3. If the structure is a list of lists, return the result of | 3. Else if the structure is a list, let output_string be the result | |||
| Serialising a List of Lists ({ser-listlist}). | of Serializing a List Section 4.1.1. | |||
| 4. If the structure is a list, return the result of Serialising a | 4. Else if the structure is an item, let output_string be the result | |||
| List Section 4.1.2. | of Serializing an Item (Section 4.1.3). | |||
| 5. If the structure is an item, return the result of Serialising an | 5. Else, fail serialisation. | |||
| Item (Section 4.1.5). | ||||
| 6. Otherwise, fail serialisation. | 6. Return output_string converted into an array of bytes, using | |||
| ASCII encoding [RFC0020]. | ||||
| 4.1.1. Serialising a Dictionary | 4.1.1. Serializing a List | |||
| Given a dictionary as input_dictionary: | Given a list of (member, parameters) as input_list: | |||
| 1. Let output be an empty string. | 1. Let output be an empty string. | |||
| 2. For each member mem of input_dictionary: | 2. For each (member, parameters) of input_list: | |||
| 1. Let name be the result of applying Serialising an Key | ||||
| (Section 4.1.1.1) to mem's member-name. | ||||
| 2. Append name to output. | ||||
| 3. Append "=" to output. | ||||
| 4. Let value be the result of applying Serialising an Item | ||||
| (Section 4.1.5) to mem's member-value. | ||||
| 5. Append value to output. | ||||
| 6. If more members remain in input_dictionary: | ||||
| 1. Append a COMMA to output. | ||||
| 2. Append a single WS to output. | ||||
| 3. Return output. | ||||
| 4.1.1.1. Serialising a Key | ||||
| Given a key as input_key: | 1. If member is an array, let mem_value be the result of | |||
| applying Serialising an Inner List (Section 4.1.1.1) to | ||||
| member. | ||||
| 1. If input_key is not a sequence of characters, or contains | 2. Otherwise, let mem_value be the result of applying | |||
| characters not allowed in the ABNF for key, fail serialisation. | Serializing an Item (Section 4.1.3) to member. | |||
| 2. Let output be an empty string. | 3. Append mem_value to output. | |||
| 3. Append input_key to output, using ASCII encoding [RFC0020]. | 4. For each parameter in parameters: | |||
| 4. Return output. | 1. Append ";" to output. | |||
| 4.1.2. Serialising a List | 2. Let name be the result of applying Serializing a Key | |||
| (Section 4.1.1.2) to parameter's param-name. | ||||
| Given a list as input_list: | 3. Append name to output. | |||
| 1. Let output be an empty string. | 4. If parameter has a param-value: | |||
| 2. For each member mem of input_list: | 1. Let value be the result of applying Serializing an | |||
| Item (Section 4.1.3) to parameter's param-value. | ||||
| 1. Let value be the result of applying Serialising an Item | 2. Append "=" to output. | |||
| (Section 4.1.5) to mem. | ||||
| 2. Append value to output. | 3. Append value to output. | |||
| 3. If more members remain in input_list: | 5. If more members remain in input_plist: | |||
| 1. Append a COMMA to output. | 1. Append a COMMA to output. | |||
| 2. Append a single WS to output. | 2. Append a single WS to output. | |||
| 3. Return output. | 3. Return output. | |||
| 4.1.3. Serialising a List of Lists | 4.1.1.1. Serialising an Inner List | |||
| Given a list of lists of items as input_list: | ||||
| 1. Let output be an empty string. | Given an array inner_list: | |||
| 2. For each member inner_list of input_list: | 1. Let output be the string "(". | |||
| 1. If inner_list is not a list, fail serialisation. | 2. For each member mem of inner_list: | |||
| 2. If inner_list is empty, fail serialisation. | 1. Let value be the result of applying Serializing an Item | |||
| (Section 4.1.3) to mem. | ||||
| 3. For each inner_mem of inner_list: | 2. Append value to output. | |||
| 1. Let value be the result of applying Serialising an Item | 3. If inner_list is not empty, append a single WS to output. | |||
| (Section 4.1.5) to inner_mem. | ||||
| 2. Append value to output. | 3. Append ")" to output. | |||
| 3. If more members remain in inner_list: | 4. Return output. | |||
| 1. Append a ";" to output. | 4.1.1.2. Serializing a Key | |||
| 2. Append a single WS to output. | Given a key as input_key: | |||
| 4. If more members remain in input_list: | 1. If input_key is not a sequence of characters, or contains | |||
| characters not allowed in the ABNF for key, fail serialisation. | ||||
| 1. Append a COMMA to output. | 2. Let output be an empty string. | |||
| 2. Append a single WS to output. | 3. Append input_key to output. | |||
| 3. Return output. | 4. Return output. | |||
| 4.1.4. Serialising a Parameterised List | 4.1.2. Serializing a Dictionary | |||
| Given a parameterised list as input_plist: | Given a dictionary as input_dictionary: | |||
| 1. Let output be an empty string. | 1. Let output be an empty string. | |||
| 2. For each member mem of input_plist: | 2. For each member mem of input_dictionary: | |||
| 1. Let id be the result of applying Serialising a Token | ||||
| (Section 4.1.9) to mem's token. | ||||
| 2. Append id to output. | ||||
| 3. For each parameter in mem's parameters: | ||||
| 1. Append ";" to output. | ||||
| 2. Let name be the result of applying Serialising a Key | 1. Let name be the result of applying Serializing a Key | |||
| (Section 4.1.1.1) to parameter's param-name. | (Section 4.1.1.2) to mem's member-name. | |||
| 3. Append name to output. | 2. Append name to output. | |||
| 4. If parameter has a param-value: | 3. Append "=" to output. | |||
| 1. Let value be the result of applying Serialising an | 4. If mem is an array, let value be the result of applying | |||
| Item (Section 4.1.5) to parameter's param-value. | Serialising an Inner List (Section 4.1.1.1) to mem. | |||
| 2. Append "=" to output. | 5. Otherwise, let value be the result of applying Serializing an | |||
| Item (Section 4.1.3) to mem. | ||||
| 3. Append value to output. | 6. Append value to output. | |||
| 4. If more members remain in input_plist: | 7. If more members remain in input_dictionary: | |||
| 1. Append a COMMA to output. | 1. Append a COMMA to output. | |||
| 2. Append a single WS to output. | 2. Append a single WS to output. | |||
| 3. Return output. | 3. Return output. | |||
| 4.1.5. Serialising an Item | 4.1.3. Serializing an Item | |||
| Given an item as input_item: | Given an item as input_item: | |||
| 1. If input_item is an integer, return the result of applying | 1. If input_item is an integer, return the result of applying | |||
| Serialising an Integer (Section 4.1.6) to input_item. | Serializing an Integer (Section 4.1.4) to input_item. | |||
| 2. If input_item is a float, return the result of applying | 2. If input_item is a float, return the result of applying | |||
| Serialising a Float (Section 4.1.7) to input_item. | Serializing a Float (Section 4.1.5) to input_item. | |||
| 3. If input_item is a string, return the result of applying | 3. If input_item is a string, return the result of applying | |||
| Serialising a String (Section 4.1.8) to input_item. | Serializing a String (Section 4.1.6) to input_item. | |||
| 4. If input_item is a token, return the result of Serialising a | 4. If input_item is a token, return the result of Serializing a | |||
| Token (Section 4.1.9) to input_item. | Token (Section 4.1.7) to input_item. | |||
| 5. If input_item is a Boolean, return the result of applying | 5. If input_item is a Boolean, return the result of applying | |||
| Serialising a Boolean (Section 4.1.11) to input_item. | Serializing a Boolean (Section 4.1.9) to input_item. | |||
| 6. If input_item is a byte sequence, return the result of applying | 6. If input_item is a byte sequence, return the result of applying | |||
| Serialising a Byte Sequence (Section 4.1.10) to input_item. | Serializing a Byte Sequence (Section 4.1.8) to input_item. | |||
| 7. Otherwise, fail serialisation. | 7. Otherwise, fail serialisation. | |||
| 4.1.6. Serialising an Integer | 4.1.4. Serializing an Integer | |||
| Given an integer as input_integer: | Given an integer as input_integer: | |||
| 1. If input_integer is not an integer in the range of | 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 | -999,999,999,999,999 to 999,999,999,999,999 inclusive, fail | |||
| serialisation. | serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. If input_integer is less than (but not equal to) 0, append "-" to | 3. If input_integer is less than (but not equal to) 0, append "-" to | |||
| output. | output. | |||
| 4. Append input_integer's numeric value represented in base 10 using | 4. Append input_integer's numeric value represented in base 10 using | |||
| only decimal digits to output. | only decimal digits to output. | |||
| 5. Return output. | 5. Return output. | |||
| 4.1.7. Serialising a Float | 4.1.5. Serializing a Float | |||
| Given a float as input_float: | Given a float as input_float: | |||
| 1. If input_float is not a IEEE 754 double precision number, fail | 1. If input_float is not a IEEE 754 double precision number, fail | |||
| serialisation. | serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. If input_float is less than (but not equal to) 0, append "-" to | 3. If input_float is less than (but not equal to) 0, append "-" to | |||
| output. | output. | |||
| skipping to change at page 16, line 37 ¶ | skipping to change at page 15, line 37 ¶ | |||
| 4. Append input_float's integer component represented in base 10 | 4. Append input_float's integer component represented in base 10 | |||
| using only decimal digits to output; if it is zero, append "0". | using only decimal digits to output; if it is zero, append "0". | |||
| 5. Append "." to output. | 5. Append "." to output. | |||
| 6. Append input_float's decimal component represented in base 10 | 6. Append input_float's decimal component represented in base 10 | |||
| using only decimal digits to output; if it is zero, append "0". | using only decimal digits to output; if it is zero, append "0". | |||
| 7. Return output. | 7. Return output. | |||
| 4.1.8. Serialising a String | 4.1.6. Serializing a String | |||
| Given a string as input_string: | Given a string as input_string: | |||
| 1. If input_string is not a sequence of characters, or contains | 1. If input_string is not a sequence of characters, or contains | |||
| characters outside the range allowed by VCHAR or SP, fail | characters outside the range allowed by VCHAR or SP, fail | |||
| serialisation. | serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. Append DQUOTE to output. | 3. Append DQUOTE to output. | |||
| 4. For each character char in input_string: | 4. For each character char in input_string: | |||
| 1. If char is "\" or DQUOTE: | 1. If char is "\" or DQUOTE: | |||
| 1. Append "\" to output. | 1. Append "\" to output. | |||
| 2. Append char to output, using ASCII encoding [RFC0020]. | 2. Append char to output. | |||
| 5. Append DQUOTE to output. | 5. Append DQUOTE to output. | |||
| 6. Return output. | 6. Return output. | |||
| 4.1.9. Serialising a Token | 4.1.7. Serializing a Token | |||
| Given a token as input_token: | Given a token as input_token: | |||
| 1. If input_token is not a sequence of characters, or contains | 1. If input_token is not a sequence of characters, or contains | |||
| characters not allowed in Section 3.9}, fail serialisation. | characters not allowed in Section 3.7}, fail serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. Append input_token to output, using ASCII encoding [RFC0020]. | 3. Append input_token to output. | |||
| 4. Return output. | 4. Return output. | |||
| 4.1.10. Serialising a Byte Sequence | 4.1.8. Serializing a Byte Sequence | |||
| Given a byte sequence as input_bytes: | Given a byte sequence as input_bytes: | |||
| 1. If input_bytes is not a sequence of bytes, fail serialisation. | 1. If input_bytes is not a sequence of bytes, fail serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. Append "*" to output. | 3. Append "*" to output. | |||
| 4. Append the result of base64-encoding input_bytes as per | 4. Append the result of base64-encoding input_bytes as per | |||
| skipping to change at page 18, line 5 ¶ | skipping to change at page 17, line 5 ¶ | |||
| 6. Return output. | 6. Return output. | |||
| The encoded data is required to be padded with "=", as per [RFC4648], | The encoded data is required to be padded with "=", as per [RFC4648], | |||
| Section 3.2. | Section 3.2. | |||
| Likewise, encoded data SHOULD have pad bits set to zero, as per | 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 | [RFC4648], Section 3.5, unless it is not possible to do so due to | |||
| implementation constraints. | implementation constraints. | |||
| 4.1.11. Serialising a Boolean | 4.1.9. Serializing a Boolean | |||
| Given a Boolean as input_boolean: | Given a Boolean as input_boolean: | |||
| 1. If input_boolean is not a boolean, fail serialisation. | 1. If input_boolean is not a boolean, fail serialisation. | |||
| 2. Let output be an empty string. | 2. Let output be an empty string. | |||
| 3. Append "?" to output. | 3. Append "?" to output. | |||
| 4. If input_boolean is true, append "1" to output. | 4. If input_boolean is true, append "1" to output. | |||
| 5. If input_boolean is false, append "0" to output. | 5. If input_boolean is false, append "0" to output. | |||
| 6. Return output. | 6. Return output. | |||
| 4.2. Parsing HTTP/1 Header Fields into Structured Headers | 4.2. Parsing Header Fields into Structured Headers | |||
| When a receiving implementation parses textual HTTP header fields | When a receiving implementation parses textual HTTP header fields | |||
| (e.g., in HTTP/1 or HTTP/2) that are known to be Structured Headers, | that are known to be Structured Headers, it is important that care be | |||
| it is important that care be taken, as there are a number of edge | taken, as there are a number of edge cases that can cause | |||
| cases that can cause interoperability or even security problems. | interoperability or even security problems. This section specifies | |||
| This section specifies the algorithm for doing so. | the algorithm for doing so. | |||
| Given an ASCII string input_string that represents the chosen | Given an array of bytes input_bytes that represents the chosen | |||
| header's field-value, and header_type, one of "dictionary", "list", | header's field-value (which is an empty string if that header is not | |||
| "list-list", "param-list", or "item", return the parsed header value. | present), and header_type (one of "dictionary", "list", or "item"), | |||
| return the parsed header value. | ||||
| 1. Discard any leading OWS from input_string. | 1. Convert input_bytes into an ASCII string input_string; if | |||
| conversion fails, fail parsing. | ||||
| 2. If header_type is "dictionary", let output be the result of | 2. Discard any leading OWS from input_string. | |||
| Parsing a Dictionary from Text (Section 4.2.1). | ||||
| 3. If header_type is "list", let output be the result of Parsing a | 3. If header_type is "list", let output be the result of Parsing a | |||
| List from Text (Section 4.2.3). | List from Text (Section 4.2.1). | |||
| 4. If header_type is "list-list", let output be the result of | ||||
| Parsing a List of Lists from Text (Section 4.2.4). | ||||
| 5. If header_type is "param-list", let output be the result of | 4. If header_type is "dictionary", let output be the result of | |||
| Parsing a Parameterised List from Text (Section 4.2.5). | Parsing a Dictionary from Text (Section 4.2.2). | |||
| 6. If header_type is "item", let output be the result of Parsing an | 5. If header_type is "item", let output be the result of Parsing an | |||
| Item from Text (Section 4.2.7). | Item from Text (Section 4.2.4). | |||
| 7. Discard any leading OWS from input_string. | 6. Discard any leading OWS from input_string. | |||
| 8. If input_string is not empty, fail parsing. | 7. If input_string is not empty, fail parsing. | |||
| 9. Otherwise, return output. | 8. Otherwise, return output. | |||
| When generating input_string, parsers MUST combine all instances of | When generating input_bytes, parsers MUST combine all instances of | |||
| the target header field into one comma-separated field-value, as per | the target header field into one comma-separated field-value, as per | |||
| [RFC7230], Section 3.2.2; this assures that the header is processed | [RFC7230], Section 3.2.2; this assures that the header is processed | |||
| correctly. | correctly. | |||
| For Lists, Lists of Lists, Parameterised Lists and Dictionaries, this | For Lists and Dictionaries, this has the effect of correctly | |||
| has the effect of correctly concatenating all instances of the header | concatenating all instances of the header field, as long as | |||
| field, as long as individual individual members of the top-level data | individual individual members of the top-level data structure are not | |||
| structure are not split across multiple header instances. | split across multiple header instances. | |||
| Strings split across multiple header instances will have | Strings split across multiple header instances will have | |||
| unpredictable results, because comma(s) and whitespace inserted upon | unpredictable results, because comma(s) and whitespace inserted upon | |||
| combination will become part of the string output by the parser. | combination will become part of the string output by the parser. | |||
| Since concatenation might be done by an upstream intermediary, the | Since concatenation might be done by an upstream intermediary, the | |||
| results are not under the control of the serialiser or the parser. | results are not under the control of the serializer or the parser. | |||
| Integers, Floats and Byte Sequences cannot be split across multiple | Tokens, Integers, Floats and Byte Sequences cannot be split across | |||
| headers because the inserted commas will cause parsing to fail. | multiple headers because the inserted commas will cause parsing to | |||
| fail. | ||||
| If parsing fails - including when calling another algorithm - the | If parsing fails - including when calling another algorithm - the | |||
| entire header field's value MUST be discarded. This is intentionally | entire header field's value MUST be discarded. This is intentionally | |||
| strict, to improve interoperability and safety, and specifications | strict, to improve interoperability and safety, and specifications | |||
| referencing this document cannot loosen this requirement. | referencing this document are not allowed to loosen this requirement. | |||
| Note that this has the effect of discarding any header field with | ||||
| non-ASCII characters in input_string. | ||||
| 4.2.1. Parsing a Dictionary from Text | 4.2.1. Parsing a List from Text | |||
| Given an ASCII string input_string, return an ordered map of (key, | Given an ASCII string input_string, return an array of (member, | |||
| item). input_string is modified to remove the parsed value. | parameters). input_string is modified to remove the parsed value. | |||
| 1. Let dictionary be an empty, ordered map. | 1. Let members be an empty array. | |||
| 2. While input_string is not empty: | 2. While input_string is not empty: | |||
| 1. Let this_key be the result of running Parse a Key from Text | 1. Let member be the result of running Parsing a Parameterized | |||
| (Section 4.2.2) with input_string. | Member from Text (Section 4.2.1.1) with input_string. | |||
| 2. If dictionary already contains this_key, fail parsing. | ||||
| 3. Consume the first character of input_string; if it is not | ||||
| "=", fail parsing. | ||||
| 4. Let this_value be the result of running Parse Item from Text | ||||
| (Section 4.2.7) with input_string. | ||||
| 5. Add key this_key with value this_value to dictionary. | ||||
| 6. Discard any leading OWS from input_string. | ||||
| 7. If input_string is empty, return dictionary. | ||||
| 8. Consume the first character of input_string; if it is not | ||||
| COMMA, fail parsing. | ||||
| 9. Discard any leading OWS from input_string. | ||||
| 10. If input_string is empty, fail parsing. | 2. Append member to members. | |||
| 3. No structured data has been found; fail parsing. | 3. Discard any leading OWS from input_string. | |||
| 4.2.2. Parsing a Key from Text | 4. If input_string is empty, return members. | |||
| Given an ASCII string input_string, return a key. input_string is | 5. Consume the first character of input_string; if it is not | |||
| modified to remove the parsed value. | COMMA, fail parsing. | |||
| 1. If the first character of input_string is not lcalpha, fail | 6. Discard any leading OWS from input_string. | |||
| parsing. | ||||
| 2. Let output_string be an empty string. | 7. If input_string is empty, there is a trailing comma; fail | |||
| parsing. | ||||
| 3. While input_string is not empty: | 3. No structured data has been found; return members (which is | |||
| empty). | ||||
| 1. Let char be the result of removing the first character of | 4.2.1.1. Parsing a Parameterized Member from Text | |||
| input_string. | ||||
| 2. If char is not one of lcalpha, DIGIT, "_", or "-": | Given an ASCII string input_string, return an token with an ordered | |||
| map of parameters. input_string is modified to remove the parsed | ||||
| value. | ||||
| 1. Prepend char to input_string. | 1. If the first character of input_string is "(", let member be the | |||
| result of running Parsing an Inner List (Section 4.2.1.2) with | ||||
| input_string. | ||||
| 2. Return output_string. | 2. Else, let member be the result of running Parsing an Item | |||
| (Section 4.2.4) with input_string. | ||||
| 3. Append char to output_string. | 3. Let parameters be an empty, ordered map. | |||
| 4. Return output_string. | 4. In a loop: | |||
| 4.2.3. Parsing a List from Text | 1. Discard any leading OWS from input_string. | |||
| Given an ASCII string input_string, return a list of items. | 2. If the first character of input_string is not ";", exit the | |||
| input_string is modified to remove the parsed value. | loop. | |||
| 1. Let items be an empty array. | 3. Consume a ";" character from the beginning of input_string. | |||
| 2. While input_string is not empty: | 4. Discard any leading OWS from input_string. | |||
| 1. Let item be the result of running Parse Item from Text | 5. let param_name be the result of Parsing a key from Text | |||
| (Section 4.2.7) with input_string. | (Section 4.2.3) from input_string. | |||
| 2. Append item to items. | 6. If param_name is already present in parameters, there is a | |||
| duplicate; fail parsing. | ||||
| 3. Discard any leading OWS from input_string. | 7. Let param_value be a null value. | |||
| 4. If input_string is empty, return items. | 8. If the first character of input_string is "=": | |||
| 5. Consume the first character of input_string; if it is not | 1. Consume the "=" character at the beginning of | |||
| COMMA, fail parsing. | input_string. | |||
| 6. Discard any leading OWS from input_string. | 2. Let param_value be the result of Parsing an Item from | |||
| Text (Section 4.2.4) from input_string. | ||||
| 7. If input_string is empty, fail parsing. | 9. Append key param_name with value param_value to parameters. | |||
| 3. No structured data has been found; fail parsing. | 5. Return the tuple (member, parameters). | |||
| 4.2.4. Parsing a List of Lists from Text | 4.2.1.2. Parsing an Inner List | |||
| Given an ASCII string input_string, return a list of lists of items. | Given an ASCII string input_string, return an array of items. | |||
| input_string is modified to remove the parsed value. | input_string is modified to remove the parsed value. | |||
| 1. let top_list be an empty array. | 1. Consume the first character of input_string; if it is not "(", | |||
| fail parsing. | ||||
| 2. Let inner_list be an empty array. | 2. Let inner_list be an empty array. | |||
| 3. While input_string is not empty: | 3. While input_string is not empty: | |||
| 1. Let item be the result of running Parse Item from Text | 1. Discard any leading OWS from input_string. | |||
| (Section 4.2.7) with input_string. | ||||
| 2. Append item to inner_list. | ||||
| 3. Discard any leading OWS from input_string. | ||||
| 4. If input_string is empty, append inner_list to top_list and | ||||
| return top_list. | ||||
| 5. Let char be the result of consuming the first character of | ||||
| input_string. | ||||
| 6. If char is COMMA: | 2. If the first character of input_string is ")": | |||
| 1. Append inner_list to top_list. | 1. Consume the first character of input_string. | |||
| 2. Let inner_list be an empty array. | 2. Return inner_list. | |||
| 7. Else if char is not ";", fail parsing. | 3. Let item be the result of running Parsing an Item from Text | |||
| (Section 4.2.4) with input_string. | ||||
| 8. Discard any leading OWS from input_string. | 4. Append item to inner_list. | |||
| 9. If input_string is empty, fail parsing. | 5. If the first character of input_string is not SP or ")", fail | |||
| parsing. | ||||
| 4. No structured data has been found; fail parsing. | 4. The end of the inner list was not found; fail parsing. | |||
| 4.2.5. Parsing a Parameterised List from Text | 4.2.2. Parsing a Dictionary from Text | |||
| Given an ASCII string input_string, return a list of parameterised | Given an ASCII string input_string, return an ordered map of (key, | |||
| identifiers. input_string is modified to remove the parsed value. | item). input_string is modified to remove the parsed value. | |||
| 1. Let items be an empty array. | 1. Let dictionary be an empty, ordered map. | |||
| 2. While input_string is not empty: | 2. While input_string is not empty: | |||
| 1. Let item be the result of running Parse Parameterised | 1. Let this_key be the result of running Parsing a Key from | |||
| Identifier from Text (Section 4.2.6) with input_string. | Text (Section 4.2.3) with input_string. | |||
| 2. Append item to items. | ||||
| 3. Discard any leading OWS from input_string. | ||||
| 4. If input_string is empty, return items. | 2. If dictionary already contains the name this_key, there is a | |||
| duplicate; fail parsing. | ||||
| 5. Consume the first character of input_string; if it is not | 3. Consume the first character of input_string; if it is not | |||
| COMMA, fail parsing. | "=", fail parsing. | |||
| 6. Discard any leading OWS from input_string. | 4. If the first character of input_string is "(", let | |||
| this_value be the result of running Parsing an Inner List | ||||
| (Section 4.2.1.2) with input_string. | ||||
| 7. If input_string is empty, fail parsing. | 5. Else, let this_value be the result of running Parsing an | |||
| Item (Section 4.2.4) with input_string. | ||||
| 3. No structured data has been found; fail parsing. | 6. Add name this_key with value this_value to dictionary. | |||
| 4.2.6. Parsing a Parameterised Identifier from Text | 7. Discard any leading OWS from input_string. | |||
| Given an ASCII string input_string, return an token with an unordered | 8. If input_string is empty, return dictionary. | |||
| map of parameters. input_string is modified to remove the parsed | ||||
| value. | ||||
| 1. Let primary_identifier be the result of Parsing a Token from Text | 9. Consume the first character of input_string; if it is not | |||
| (Section 4.2.10) from input_string. | COMMA, fail parsing. | |||
| 2. Let parameters be an empty, ordered map. | 10. Discard any leading OWS from input_string. | |||
| 3. In a loop: | 11. If input_string is empty, there is a trailing comma; fail | |||
| parsing. | ||||
| 1. Discard any leading OWS from input_string. | 3. No structured data has been found; return dictionary (which is | |||
| empty). | ||||
| 2. If the first character of input_string is not ";", exit the | 4.2.3. Parsing a Key from Text | |||
| loop. | ||||
| 3. Consume a ";" character from the beginning of input_string. | Given an ASCII string input_string, return a key. input_string is | |||
| modified to remove the parsed value. | ||||
| 4. Discard any leading OWS from input_string. | 1. If the first character of input_string is not lcalpha, fail | |||
| parsing. | ||||
| 5. let param_name be the result of Parsing a key from Text | 2. Let output_string be an empty string. | |||
| (Section 4.2.2) from input_string. | ||||
| 6. If param_name is already present in parameters, fail parsing. | 3. While input_string is not empty: | |||
| 7. Let param_value be a null value. | 1. Let char be the result of removing the first character of | |||
| input_string. | ||||
| 8. If the first character of input_string is "=": | 2. If char is not one of lcalpha, DIGIT, "_", or "-": | |||
| 1. Consume the "=" character at the beginning of | 1. Prepend char to input_string. | |||
| input_string. | ||||
| 2. Let param_value be the result of Parsing an Item from | 2. Return output_string. | |||
| Text (Section 4.2.7) from input_string. | ||||
| 9. Add key param_name with value param_value to parameters. | 3. Append char to output_string. | |||
| 4. Return the tuple (primary_identifier, parameters). | 4. Return output_string. | |||
| 4.2.7. Parsing an Item from Text | 4.2.4. Parsing an Item from Text | |||
| Given an ASCII string input_string, return an item. input_string is | Given an ASCII string input_string, return an item. input_string is | |||
| modified to remove the parsed value. | modified to remove the parsed value. | |||
| 1. If the first character of input_string is a "-" or a DIGIT, | 1. If the first character of input_string is a "-" or a DIGIT, | |||
| process input_string as a number (Section 4.2.8) and return the | process input_string as a number (Section 4.2.5) and return the | |||
| result. | result. | |||
| 2. If the first character of input_string is a DQUOTE, process | 2. If the first character of input_string is a DQUOTE, process | |||
| input_string as a string (Section 4.2.9) and return the result. | input_string as a string (Section 4.2.6) and return the result. | |||
| 3. If the first character of input_string is "*", process | 3. If the first character of input_string is "*", process | |||
| input_string as a byte sequence (Section 4.2.11) and return the | input_string as a byte sequence (Section 4.2.8) and return the | |||
| result. | result. | |||
| 4. If the first character of input_string is "?", process | 4. If the first character of input_string is "?", process | |||
| input_string as a Boolean (Section 4.2.12) and return the result. | input_string as a Boolean (Section 4.2.9) and return the result. | |||
| 5. If the first character of input_string is an ALPHA, process | 5. If the first character of input_string is an ALPHA, process | |||
| input_string as a token (Section 4.2.10) and return the result. | input_string as a token (Section 4.2.7) and return the result. | |||
| 6. Otherwise, fail parsing. | 6. Otherwise, the item type is unrecognized; fail parsing. | |||
| 4.2.8. Parsing a Number from Text | 4.2.5. Parsing a Number from Text | |||
| Given an ASCII string input_string, return a number. input_string is | Given an ASCII string input_string, return a number. input_string is | |||
| modified to remove the parsed value. | modified to remove the parsed value. | |||
| NOTE: This algorithm parses both Integers Section 3.6 and Floats | NOTE: This algorithm parses both Integers Section 3.4 and Floats | |||
| Section 3.7, and returns the corresponding structure. | Section 3.5, and returns the corresponding structure. | |||
| 1. Let type be "integer". | 1. Let type be "integer". | |||
| 2. Let sign be 1. | 2. Let sign be 1. | |||
| 3. Let input_number be an empty string. | 3. Let input_number be an empty string. | |||
| 4. If the first character of input_string is "-", remove it from | 4. If the first character of input_string is "-", consume it and | |||
| input_string and set sign to -1. | set sign to -1. | |||
| 5. If input_string is empty, fail parsing. | 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 | 6. If the first character of input_string is not a DIGIT, fail | |||
| parsing. | parsing. | |||
| 7. While input_string is not empty: | 7. While input_string is not empty: | |||
| 1. Let char be the result of removing the first character of | 1. Let char be the result of consuming the first character of | |||
| input_string. | input_string. | |||
| 2. If char is a DIGIT, append it to input_number. | 2. If char is a DIGIT, append it to input_number. | |||
| 3. Else, if type is "integer" and char is ".", append char to | 3. Else, if type is "integer" and char is ".", append char to | |||
| input_number and set type to "float". | input_number and set type to "float". | |||
| 4. Otherwise, prepend char to input_string, and exit the loop. | 4. Otherwise, prepend char to input_string, and exit the loop. | |||
| 5. If type is "integer" and input_number contains more than 15 | 5. If type is "integer" and input_number contains more than 15 | |||
| skipping to change at page 25, line 9 ¶ | skipping to change at page 23, line 32 ¶ | |||
| 6. If type is "float" and input_number contains more than 16 | 6. If type is "float" and input_number contains more than 16 | |||
| characters, fail parsing. | characters, fail parsing. | |||
| 8. If type is "integer": | 8. If type is "integer": | |||
| 1. Parse input_number as an integer and let output_number be | 1. Parse input_number as an integer and let output_number be | |||
| the product of the result and sign. | the product of the result and sign. | |||
| 2. If output_number is outside the range defined in | 2. If output_number is outside the range defined in | |||
| Section 3.6, fail parsing. | Section 3.4, fail parsing. | |||
| 9. Otherwise: | 9. Otherwise: | |||
| 1. If the final character of input_number is ".", fail parsing. | 1. If the final character of input_number is ".", fail parsing. | |||
| 2. Parse input_number as a float and let output_number be the | 2. Parse input_number as a float and let output_number be the | |||
| product of the result and sign. | product of the result and sign. | |||
| 10. Return output_number. | 10. Return output_number. | |||
| 4.2.9. Parsing a String from Text | 4.2.6. Parsing a String from Text | |||
| Given an ASCII string input_string, return an unquoted string. | Given an ASCII string input_string, return an unquoted string. | |||
| input_string is modified to remove the parsed value. | input_string is modified to remove the parsed value. | |||
| 1. Let output_string be an empty string. | 1. Let output_string be an empty string. | |||
| 2. If the first character of input_string is not DQUOTE, fail | 2. If the first character of input_string is not DQUOTE, fail | |||
| parsing. | parsing. | |||
| 3. Discard the first character of input_string. | 3. Discard the first character of input_string. | |||
| 4. While input_string is not empty: | 4. While input_string is not empty: | |||
| 1. Let char be the result of removing the first character of | 1. Let char be the result of consuming the first character of | |||
| input_string. | input_string. | |||
| 2. If char is a backslash ("\"): | 2. If char is a backslash ("\"): | |||
| 1. If input_string is now empty, fail parsing. | 1. If input_string is now empty, fail parsing. | |||
| 2. Else: | 2. Else: | |||
| 1. Let next_char be the result of removing the first | 1. Let next_char be the result of consuming the first | |||
| character of input_string. | character of input_string. | |||
| 2. If next_char is not DQUOTE or "\", fail parsing. | 2. If next_char is not DQUOTE or "\", fail parsing. | |||
| 3. Append next_char to output_string. | 3. Append next_char to output_string. | |||
| 3. Else, if char is DQUOTE, return output_string. | 3. Else, if char is DQUOTE, return output_string. | |||
| 4. Else, if char is in the range %x00-1f or %x7f (i.e., is not | 4. Else, if char is in the range %x00-1f or %x7f (i.e., is not | |||
| in VCHAR or SP), fail parsing. | in VCHAR or SP), fail parsing. | |||
| 5. Else, append char to output_string. | 5. Else, append char to output_string. | |||
| 5. Reached the end of input_string without finding a closing DQUOTE; | 5. Reached the end of input_string without finding a closing DQUOTE; | |||
| fail parsing. | fail parsing. | |||
| 4.2.10. Parsing a Token from Text | 4.2.7. Parsing a Token from Text | |||
| Given an ASCII string input_string, return a token. input_string is | Given an ASCII string input_string, return a token. input_string is | |||
| modified to remove the parsed value. | modified to remove the parsed value. | |||
| 1. If the first character of input_string is not ALPHA, fail | 1. If the first character of input_string is not ALPHA, fail | |||
| parsing. | parsing. | |||
| 2. Let output_string be an empty string. | 2. Let output_string be an empty string. | |||
| 3. While input_string is not empty: | 3. While input_string is not empty: | |||
| 1. Let char be the result of removing the first character of | 1. Let char be the result of consuming the first character of | |||
| input_string. | input_string. | |||
| 2. If char is not one of ALPHA, DIGIT, "_", "-", ".", ":", "%", | 2. If char is not one of ALPHA, DIGIT, "_", "-", ".", ":", "%", | |||
| "*" or "/": | "*" or "/": | |||
| 1. Prepend char to input_string. | 1. Prepend char to input_string. | |||
| 2. Return output_string. | 2. Return output_string. | |||
| 3. Append char to output_string. | 3. Append char to output_string. | |||
| 4. Return output_string. | 4. Return output_string. | |||
| 4.2.11. Parsing a Byte Sequence from Text | 4.2.8. Parsing a Byte Sequence from Text | |||
| Given an ASCII string input_string, return a byte sequence. | Given an ASCII string input_string, return a byte sequence. | |||
| input_string is modified to remove the parsed value. | input_string is modified to remove the parsed value. | |||
| 1. If the first character of input_string is not "*", fail parsing. | 1. If the first character of input_string is not "*", fail parsing. | |||
| 2. Discard the first character of input_string. | 2. Discard the first character of input_string. | |||
| 3. If there is not a "*" character before the end of input_string, | 3. If there is not a "*" character before the end of input_string, | |||
| fail parsing. | fail parsing. | |||
| 4. Let b64_content be the result of removing content of input_string | 4. Let b64_content be the result of consuming content of | |||
| up to but not including the first instance of the character "*". | input_string up to but not including the first instance of the | |||
| character "*". | ||||
| 5. Consume the "*" character at the beginning of input_string. | 5. Consume the "*" character at the beginning of input_string. | |||
| 6. If b64_content contains a character not included in ALPHA, DIGIT, | 6. If b64_content contains a character not included in ALPHA, DIGIT, | |||
| "+", "/" and "=", fail parsing. | "+", "/" and "=", fail parsing. | |||
| 7. Let binary_content be the result of Base 64 Decoding [RFC4648] | 7. Let binary_content be the result of Base 64 Decoding [RFC4648] | |||
| b64_content, synthesising padding if necessary (note the | b64_content, synthesizing padding if necessary (note the | |||
| requirements about recipient behaviour below). | requirements about recipient behaviour below). | |||
| 8. Return binary_content. | 8. Return binary_content. | |||
| Because some implementations of base64 do not allow reject of encoded | Because some implementations of base64 do not allow reject of encoded | |||
| data that is not properly "=" padded (see [RFC4648], Section 3.2), | data that is not properly "=" padded (see [RFC4648], Section 3.2), | |||
| parsers SHOULD NOT fail when it is not present, unless they cannot be | parsers SHOULD NOT fail when it is not present, unless they cannot be | |||
| configured to do so. | configured to do so. | |||
| Because some implementations of base64 do not allow rejection of | Because some implementations of base64 do not allow rejection of | |||
| encoded data that has non-zero pad bits (see [RFC4648], Section 3.5), | encoded data that has non-zero pad bits (see [RFC4648], Section 3.5), | |||
| parsers SHOULD NOT fail when it is present, unless they cannot be | parsers SHOULD NOT fail when it is present, unless they cannot be | |||
| configured to do so. | configured to do so. | |||
| This specification does not relax the requirements in [RFC4648], | This specification does not relax the requirements in [RFC4648], | |||
| Section 3.1 and 3.3; therefore, parsers MUST fail on characters | Section 3.1 and 3.3; therefore, parsers MUST fail on characters | |||
| outside the base64 alphabet, and on line feeds in encoded data. | outside the base64 alphabet, and on line feeds in encoded data. | |||
| 4.2.12. Parsing a Boolean from Text | 4.2.9. Parsing a Boolean from Text | |||
| Given an ASCII string input_string, return a Boolean. input_string is | Given an ASCII string input_string, return a Boolean. input_string is | |||
| modified to remove the parsed value. | modified to remove the parsed value. | |||
| 1. If the first character of input_string is not "?", fail parsing. | 1. If the first character of input_string is not "?", fail parsing. | |||
| 2. Discard the first character of input_string. | 2. Discard the first character of input_string. | |||
| 3. If the first character of input_string matches "1", discard the | 3. If the first character of input_string matches "1", discard the | |||
| first character, and return true. | first character, and return true. | |||
| skipping to change at page 28, line 10 ¶ | skipping to change at page 26, line 31 ¶ | |||
| 5. IANA Considerations | 5. IANA Considerations | |||
| This draft has no actions for IANA. | This draft has no actions for IANA. | |||
| 6. Security Considerations | 6. Security Considerations | |||
| The size of most types defined by Structured Headers is not limited; | The size of most types defined by Structured Headers is not limited; | |||
| as a result, extremely large header fields could be an attack vector | as a result, extremely large header fields could be an attack vector | |||
| (e.g., for resource consumption). Most HTTP implementations limit | (e.g., for resource consumption). Most HTTP implementations limit | |||
| the sizes of size of individual header fields as well as the overall | the sizes of individual header fields as well as the overall header | |||
| header block size to mitigate such attacks. | block size to mitigate such attacks. | |||
| It is possible for parties with the ability to inject new HTTP header | It is possible for parties with the ability to inject new HTTP header | |||
| fields to change the meaning of a Structured Header. In some | fields to change the meaning of a Structured Header. In some | |||
| circumstances, this will cause parsing to fail, but it is not | circumstances, this will cause parsing to fail, but it is not | |||
| possible to reliably fail in all such circumstances. | possible to reliably fail in all such circumstances. | |||
| 7. References | 7. References | |||
| 7.1. Normative References | 7.1. Normative References | |||
| skipping to change at page 30, line 39 ¶ | skipping to change at page 29, line 10 ¶ | |||
| depths. Since the resulting memory commitment might be unsuitable | depths. Since the resulting memory commitment might be unsuitable | |||
| (e.g., in embedded and other limited server deployments), it's | (e.g., in embedded and other limited server deployments), it's | |||
| necessary to limit it in some fashion; however, existing JSON | necessary to limit it in some fashion; however, existing JSON | |||
| implementations have no such limits, and even if a limit is | implementations have no such limits, and even if a limit is | |||
| specified, it's likely that some header field definition will find a | specified, it's likely that some header field definition will find a | |||
| need to violate it. | need to violate it. | |||
| Because of JSON's broad adoption and implementation, it is difficult | Because of JSON's broad adoption and implementation, it is difficult | |||
| to impose such additional constraints across all implementations; | to impose such additional constraints across all implementations; | |||
| some deployments would fail to enforce them, thereby harming | some deployments would fail to enforce them, thereby harming | |||
| interoperability. | interoperability. In short, if it looks like JSON, people will be | |||
| tempted to use a JSON parser / serialiser on header fields. | ||||
| Since a major goal for Structured Headers is to improve | Since a major goal for Structured Headers is to improve | |||
| interoperability and simplify implementation, these concerns led to a | interoperability and simplify implementation, these concerns led to a | |||
| format that requires a dedicated parser and serialiser. | format that requires a dedicated parser and serializer. | |||
| Additionally, there were widely shared feelings that JSON doesn't | Additionally, there were widely shared feelings that JSON doesn't | |||
| "look right" in HTTP headers. | "look right" in HTTP headers. | |||
| B.2. Structured Headers don't "fit" my data. | B.2. Structured Headers don't "fit" my data. | |||
| Structured headers intentionally limits the complexity of data | Structured headers intentionally limits the complexity of data | |||
| structures, to assure that it can be processed in a performant manner | structures, to assure that it can be processed in a performant manner | |||
| with little overhead. This means that work is necessary to fit some | with little overhead. This means that work is necessary to fit some | |||
| data types into them. | data types into them. | |||
| Sometimes, this can be achieved by creating limited substructures in | Sometimes, this can be achieved by creating limited substructures in | |||
| values, and/or using more than one header. For example, consider: | values, and/or using more than one header. For example, consider: | |||
| Example-Thing: name="Widget", cost=89.2, descriptions="foo bar" | Example-Thing: name="Widget", cost=89.2, descriptions=(foo bar) | |||
| Example-Description: foo; url="https://example.net"; context=123, | Example-Description: foo; url="https://example.net"; context=123, | |||
| bar; url="https://example.org"; context=456 | bar; url="https://example.org"; context=456 | |||
| Since the description contains a list of key/value pairs, we use a | Since the description contains an array of key/value pairs, we use a | |||
| Parameterised List to represent them, with the token for each item in | List to represent them, with the token for each item in the array | |||
| the list used to identify it in the "descriptions" member of the | used to identify it in the "descriptions" member of the Example-Thing | |||
| Example-Thing header. | header. | |||
| When specifying more than one header, it's important to remember to | When specifying more than one header, it's important to remember to | |||
| describe what a processor's behaviour should be when one of the | describe what a processor's behaviour should be when one of the | |||
| headers is missing. | headers is missing. | |||
| If you need to fit arbitrarily complex data into a header, Structured | If you need to fit arbitrarily complex data into a header, Structured | |||
| Headers is probably a poor fit for your use case. | Headers is probably a poor fit for your use case. | |||
| B.3. What should generic Structured Headers implementations expose? | Appendix C. Implementation Notes | |||
| A generic implementation should expose the top-level parse | A generic implementation of this specification should expose the top- | |||
| (Section 4.2) and serialise (Section 4.1) functions. They need not | level parse (Section 4.2) and serialize (Section 4.1) functions. | |||
| be functions; for example, it could be implemented as an object, with | They need not be functions; for example, it could be implemented as | |||
| methods for each of the different top-level types. | an object, with methods for each of the different top-level types. | |||
| For interoperability, it's important that generic implementations be | For interoperability, it's important that generic implementations be | |||
| complete and follow the algorithms closely; see Section 1.1. To aid | complete and follow the algorithms closely; see Section 1.1. To aid | |||
| this, a common test suite is being maintained by the community; see | this, a common test suite is being maintained by the community; see | |||
| https://github.com/httpwg/structured-header-tests [7]. | https://github.com/httpwg/structured-header-tests [7]. | |||
| Implementers should note that dictionaries and parameters are order- | Implementers should note that dictionaries and parameters are order- | |||
| preserving maps. Some headers may not convey meaning in the ordering | preserving maps. Some headers may not convey meaning in the ordering | |||
| of these data types, but it should still be exposed so that | of these data types, but it should still be exposed so that | |||
| applications which need to use it will have it available. | applications which need to use it will have it available. | |||
| Appendix C. Changes | 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. | ||||
| Appendix D. Changes | ||||
| _RFC Editor: Please remove this section before publication._ | _RFC Editor: Please remove this section before publication._ | |||
| C.1. Since draft-ietf-httpbis-header-structure-09 | D.1. Since draft-ietf-httpbis-header-structure-10 | |||
| o Update abstract (#799). | ||||
| o Input and output are now arrays of bytes (#662). | ||||
| o Implementations need to preserve difference between token and | ||||
| string (#790). | ||||
| o Allow empty dictionaries and lists (#781). | ||||
| o Change parameterized lists to have primary items (#797). | ||||
| o Allow inner lists in both dictionaries and lists; removes lists of | ||||
| lists (#816). | ||||
| o Subsume Parameterised Lists into Lists (#839). | ||||
| D.2. Since draft-ietf-httpbis-header-structure-09 | ||||
| o Changed Boolean from T/F to 1/0 (#784). | o Changed Boolean from T/F to 1/0 (#784). | |||
| o Parameters are now ordered maps (#765). | o Parameters are now ordered maps (#765). | |||
| o Clamp integers to 15 digits (#737). | o Clamp integers to 15 digits (#737). | |||
| C.2. Since draft-ietf-httpbis-header-structure-08 | D.3. Since draft-ietf-httpbis-header-structure-08 | |||
| o Disallow whitespace before items properly (#703). | o Disallow whitespace before items properly (#703). | |||
| o Created "key" for use in dictionaries and parameters, rather than | o Created "key" for use in dictionaries and parameters, rather than | |||
| relying on identifier (#702). Identifiers have a separate minimum | relying on identifier (#702). Identifiers have a separate minimum | |||
| supported size. | supported size. | |||
| o Expanded the range of special characters allowed in identifier to | o Expanded the range of special characters allowed in identifier to | |||
| include all of ALPHA, ".", ":", and "%" (#702). | include all of ALPHA, ".", ":", and "%" (#702). | |||
| skipping to change at page 32, line 31 ¶ | skipping to change at page 31, line 29 ¶ | |||
| o Gave better names for referring specs to use in Parameterised | o Gave better names for referring specs to use in Parameterised | |||
| Lists (#720). | Lists (#720). | |||
| o Added Lists of Lists (#721). | o Added Lists of Lists (#721). | |||
| o Rename Identifier to Token (#725). | o Rename Identifier to Token (#725). | |||
| o Add implementation guidance (#727). | o Add implementation guidance (#727). | |||
| C.3. Since draft-ietf-httpbis-header-structure-07 | D.4. Since draft-ietf-httpbis-header-structure-07 | |||
| o Make Dictionaries ordered mappings (#659). | o Make Dictionaries ordered mappings (#659). | |||
| o Changed "binary content" to "byte sequence" to align with Infra | o Changed "binary content" to "byte sequence" to align with Infra | |||
| specification (#671). | specification (#671). | |||
| o Changed "mapping" to "map" for #671. | o Changed "mapping" to "map" for #671. | |||
| o Don't fail if byte sequences aren't "=" padded (#658). | o Don't fail if byte sequences aren't "=" padded (#658). | |||
| o Add Booleans (#683). | o Add Booleans (#683). | |||
| o Allow identifiers in items again (#629). | o Allow identifiers in items again (#629). | |||
| o Disallowed whitespace before items (#703). | o Disallowed whitespace before items (#703). | |||
| o Explain the consequences of splitting a string across multiple | o Explain the consequences of splitting a string across multiple | |||
| headers (#686). | headers (#686). | |||
| C.4. Since draft-ietf-httpbis-header-structure-06 | D.5. Since draft-ietf-httpbis-header-structure-06 | |||
| o Add a FAQ. | o Add a FAQ. | |||
| o Allow non-zero pad bits. | o Allow non-zero pad bits. | |||
| o Explicitly check for integers that violate constraints. | o Explicitly check for integers that violate constraints. | |||
| C.5. Since draft-ietf-httpbis-header-structure-05 | D.6. Since draft-ietf-httpbis-header-structure-05 | |||
| o Reorganise specification to separate parsing out. | o Reorganise specification to separate parsing out. | |||
| o Allow referencing specs to use ABNF. | o Allow referencing specs to use ABNF. | |||
| o Define serialisation algorithms. | o Define serialisation algorithms. | |||
| o Refine relationship between ABNF, parsing and serialisation | o Refine relationship between ABNF, parsing and serialisation | |||
| algorithms. | algorithms. | |||
| C.6. Since draft-ietf-httpbis-header-structure-04 | D.7. Since draft-ietf-httpbis-header-structure-04 | |||
| o Remove identifiers from item. | o Remove identifiers from item. | |||
| o Remove most limits on sizes. | o Remove most limits on sizes. | |||
| o Refine number parsing. | o Refine number parsing. | |||
| C.7. Since draft-ietf-httpbis-header-structure-03 | D.8. Since draft-ietf-httpbis-header-structure-03 | |||
| o Strengthen language around failure handling. | o Strengthen language around failure handling. | |||
| C.8. Since draft-ietf-httpbis-header-structure-02 | D.9. Since draft-ietf-httpbis-header-structure-02 | |||
| o Split Numbers into Integers and Floats. | o Split Numbers into Integers and Floats. | |||
| o Define number parsing. | o Define number parsing. | |||
| o Tighten up binary parsing and give it an explicit end delimiter. | o Tighten up binary parsing and give it an explicit end delimiter. | |||
| o Clarify that mappings are unordered. | o Clarify that mappings are unordered. | |||
| o Allow zero-length strings. | o Allow zero-length strings. | |||
| o Improve string parsing algorithm. | o Improve string parsing algorithm. | |||
| o Improve limits in algorithms. | o Improve limits in algorithms. | |||
| o Require parsers to combine header fields before processing. | o Require parsers to combine header fields before processing. | |||
| o Throw an error on trailing garbage. | o Throw an error on trailing garbage. | |||
| C.9. Since draft-ietf-httpbis-header-structure-01 | D.10. Since draft-ietf-httpbis-header-structure-01 | |||
| o Replaced with draft-nottingham-structured-headers. | o Replaced with draft-nottingham-structured-headers. | |||
| C.10. Since draft-ietf-httpbis-header-structure-00 | D.11. Since draft-ietf-httpbis-header-structure-00 | |||
| o Added signed 64bit integer type. | o Added signed 64bit integer type. | |||
| o Drop UTF8, and settle on BCP137 ::EmbeddedUnicodeChar for h1- | o Drop UTF8, and settle on BCP137 ::EmbeddedUnicodeChar for h1- | |||
| unicode-string. | unicode-string. | |||
| o Change h1_blob delimiter to ":" since "'" is valid t_char | o Change h1_blob delimiter to ":" since "'" is valid t_char | |||
| Authors' Addresses | Authors' Addresses | |||
| End of changes. 257 change blocks. | ||||
| 527 lines changed or deleted | 480 lines changed or added | |||
This html diff was produced by rfcdiff 1.45. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||