draft-ietf-httpbis-header-structure-10.txt   draft-ietf-httpbis-header-structure-latest.txt 
HTTP Working Group M. Nottingham HTTP Working Group 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: November 17, 2019 The Varnish Cache Project
April 17, 2019 May 16, 2019
Structured Headers for HTTP Structured Headers for HTTP
draft-ietf-httpbis-header-structure-10 draft-ietf-httpbis-header-structure-latest
Abstract Abstract
This document describes a set of data types and algorithms associated This document describes a set of data types and algorithms associated
with them that are intended to make it easier and safer to define and with them that are intended to make it easier and safer to define and
handle HTTP header fields. It is intended for use by new handle HTTP header fields. It is intended for use by new
specifications of HTTP header fields as well as revisions of existing specifications of HTTP header fields as well as revisions of existing
header field specifications when doing so does not cause header field specifications when doing so does not cause
interoperability issues. interoperability issues.
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 November 17, 2019.
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 37 skipping to change at page 2, line 37
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 . . . . . . . . . . . . . . . . 7
3.1. Dictionaries . . . . . . . . . . . . . . . . . . . . . . 7 3.1. Dictionaries . . . . . . . . . . . . . . . . . . . . . . 7
3.2. Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2. Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3. Lists of Lists . . . . . . . . . . . . . . . . . . . . . 8 3.3. Lists of Lists . . . . . . . . . . . . . . . . . . . . . 8
3.4. Parameterised Lists . . . . . . . . . . . . . . . . . . . 8 3.4. Parameterized Lists . . . . . . . . . . . . . . . . . . . 8
3.5. Items . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.5. Items . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.6. Integers . . . . . . . . . . . . . . . . . . . . . . . . 9 3.6. Integers . . . . . . . . . . . . . . . . . . . . . . . . 9
3.7. Floats . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.7. Floats . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.8. Strings . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.8. Strings . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.9. Tokens . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.9. Tokens . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.10. Byte Sequences . . . . . . . . . . . . . . . . . . . . . 11 3.10. Byte Sequences . . . . . . . . . . . . . . . . . . . . . 11
3.11. Booleans . . . . . . . . . . . . . . . . . . . . . . . . 11 3.11. Booleans . . . . . . . . . . . . . . . . . . . . . . . . 11
4. Structured Headers in HTTP/1 . . . . . . . . . . . . . . . . 12 4. Structured Headers in HTTP/1 . . . . . . . . . . . . . . . . 12
4.1. Serialising Structured Headers into HTTP/1 . . . . . . . 12 4.1. Serializing Structured Headers into HTTP/1 . . . . . . . 12
4.2. Parsing HTTP/1 Header Fields into Structured Headers . . 18 4.2. Parsing HTTP/1 Header Fields into Structured Headers . . 18
5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 27 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 28
6. Security Considerations . . . . . . . . . . . . . . . . . . . 28 6. Security Considerations . . . . . . . . . . . . . . . . . . . 28
7. References . . . . . . . . . . . . . . . . . . . . . . . . . 28 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.1. Normative References . . . . . . . . . . . . . . . . . . 28 7.1. Normative References . . . . . . . . . . . . . . . . . . 28
7.2. Informative References . . . . . . . . . . . . . . . . . 29 7.2. Informative References . . . . . . . . . . . . . . . . . 29
7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 29 7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 30 Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 30
Appendix B. Frequently Asked Questions . . . . . . . . . . . . . 30 Appendix B. Frequently Asked Questions . . . . . . . . . . . . . 30
B.1. Why not JSON? . . . . . . . . . . . . . . . . . . . . . . 30 B.1. Why not JSON? . . . . . . . . . . . . . . . . . . . . . . 30
B.2. Structured Headers don't "fit" my data. . . . . . . . . . 30 B.2. Structured Headers don't "fit" my data. . . . . . . . . . 31
B.3. What should generic Structured Headers implementations B.3. What should generic Structured Headers implementations
expose? . . . . . . . . . . . . . . . . . . . . . . . . . 31 expose? . . . . . . . . . . . . . . . . . . . . . . . . . 31
Appendix C. Changes . . . . . . . . . . . . . . . . . . . . . . 31 Appendix C. Changes . . . . . . . . . . . . . . . . . . . . . . 31
C.1. Since draft-ietf-httpbis-header-structure-09 . . . . . . 31 C.1. Since draft-ietf-httpbis-header-structure-10 . . . . . . 32
C.2. Since draft-ietf-httpbis-header-structure-08 . . . . . . 32 C.2. Since draft-ietf-httpbis-header-structure-09 . . . . . . 32
C.3. Since draft-ietf-httpbis-header-structure-07 . . . . . . 32 C.3. Since draft-ietf-httpbis-header-structure-08 . . . . . . 32
C.4. Since draft-ietf-httpbis-header-structure-06 . . . . . . 33 C.4. Since draft-ietf-httpbis-header-structure-07 . . . . . . 32
C.5. Since draft-ietf-httpbis-header-structure-05 . . . . . . 33 C.5. Since draft-ietf-httpbis-header-structure-06 . . . . . . 33
C.6. Since draft-ietf-httpbis-header-structure-04 . . . . . . 33 C.6. Since draft-ietf-httpbis-header-structure-05 . . . . . . 33
C.7. Since draft-ietf-httpbis-header-structure-03 . . . . . . 33 C.7. Since draft-ietf-httpbis-header-structure-04 . . . . . . 33
C.8. Since draft-ietf-httpbis-header-structure-02 . . . . . . 33 C.8. Since draft-ietf-httpbis-header-structure-03 . . . . . . 33
C.9. Since draft-ietf-httpbis-header-structure-01 . . . . . . 34 C.9. Since draft-ietf-httpbis-header-structure-02 . . . . . . 33
C.10. Since draft-ietf-httpbis-header-structure-00 . . . . . . 34 C.10. Since draft-ietf-httpbis-header-structure-01 . . . . . . 34
C.11. Since draft-ietf-httpbis-header-structure-00 . . . . . . 34
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 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, HTTP header field values to address these problems. In particular,
it defines a generic, abstract model for header field values, along it defines a generic, abstract model for header field values, along
with a concrete serialisation for expressing that model in HTTP/1 with a concrete serialisation for expressing that model in HTTP/1
[RFC7230] header fields. [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
skipping to change at page 4, line 14 skipping to change at page 4, line 14
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. To specify a header field that is a Structured Header, see Section 2.
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 serialised into and parsed from textual Those abstract types can be serialized into and parsed from textual
headers - such as those used in HTTP/1 - using the algorithms headers - such as those used in HTTP/1 - using the algorithms
described in Section 4. 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 This is designed to encourage faithful implementation and therefore
skipping to change at page 6, line 5 skipping to change at page 6, line 5
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 a structure or its processing because doing so would preclude
handling by generic software; they can only add additional handling by generic software; they can only add additional
constraints. Likewise, header field definitions should use constraints. Likewise, header field definitions should use
Structured Headers for the entire header field value, not a portion Structured Headers for the entire header field value, not a portion
thereof. thereof.
For example: For example:
# Foo-Example Header 2. 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:
skipping to change at page 8, line 37 skipping to change at page 8, line 37
defined as a list of lists of strings could look like: defined as a list of lists of strings could look like:
Example-StrListListHeader: "foo";"bar", "baz", "bat"; "one" Example-StrListListHeader: "foo";"bar", "baz", "bat"; "one"
Header specifications can constrain the types of individual inner- Header specifications can constrain the types of individual inner-
list values if necessary. list values if necessary.
Parsers MUST support lists of lists containing at least 1024 members, Parsers MUST support lists of lists containing at least 1024 members,
and inner-lists containing at least 256 members. and inner-lists containing at least 256 members.
3.4. Parameterised Lists 3.4. Parameterized Lists
Parameterised Lists are arrays of parameterised identifiers, with one Parameterized Lists are arrays of parameterized identifiers, with one
or more members. or more members.
A parameterised identifier is a primary identifier (a Section 3.9}) A parameterized identifier is a primary identifier (a Section 3.9})
with associated parameters, an ordered map of key-value pairs where with associated parameters, an ordered map of key-value pairs where
the keys are short, textual strings and the values are items the keys are short, textual strings and the values are items
(Section 3.5). There can be zero or more parameters, and keys are (Section 3.5). There can be zero or more parameters, and keys are
required to be unique. required to be unique.
The ABNF for parameterised lists in HTTP/1 headers is: The ABNF for parameterized lists in HTTP/1 headers is:
sh-param-list = param-item *( OWS "," OWS param-item ) sh-param-list = param-item *( OWS "," OWS param-item )
param-item = primary-id *parameter param-item = primary-id *parameter
primary-id = sh-token primary-id = sh-token
parameter = OWS ";" OWS param-name [ "=" param-value ] parameter = OWS ";" OWS param-name [ "=" param-value ]
param-name = key param-name = key
param-value = sh-item param-value = sh-item
In HTTP/1, each param-id is separated by a comma and optional In HTTP/1, each param-id is separated by a comma and optional
whitespace (as in Lists), and the parameters are separated by whitespace (as in Lists), and the parameters are separated by
semicolons. For example: semicolons. For example:
Example-ParamListHeader: abc_123;a=1;b=2; cdef_456, ghi;q="9";r="w" Example-ParamListHeader: abc_123;a=1;b=2; cdef_456, ghi;q="9";r="w"
Parsers MUST support parameterised lists containing at least 1024 Parsers MUST support parameterized lists containing at least 1024
members, support members with at least 256 parameters, and support members, support members with at least 256 parameters, and support
parameter keys with at least 64 characters. parameter keys with at least 64 characters.
3.5. Items 3.5. Items
An item is can be a integer (Section 3.6), float (Section 3.7), An item is can be a integer (Section 3.6), float (Section 3.7),
string (Section 3.8), token (Section 3.9), byte sequence string (Section 3.8), token (Section 3.9), byte sequence
(Section 3.10), or Boolean (Section 3.11). (Section 3.10), or Boolean (Section 3.11).
The ABNF for items in HTTP/1 headers is: The ABNF for items in HTTP/1 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.6. 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 HTTP/1 headers is:
sh-integer = ["-"] 1*15DIGIT sh-integer = ["-"] 1*15DIGIT
For example: For example:
Example-IntegerHeader: 42 Example-IntegerHeader: 42
3.7. Floats 3.7. Floats
skipping to change at page 11, line 18 skipping to change at page 11, line 18
Parsers MUST support strings with at least 1024 characters. Parsers MUST support strings with at least 1024 characters.
3.9. Tokens 3.9. 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 HTTP/1 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.10. Byte Sequences
Byte sequences can be conveyed in Structured Headers. Byte sequences can be conveyed in Structured Headers.
skipping to change at page 11, line 50 skipping to change at page 12, line 4
decoding. decoding.
3.11. Booleans 3.11. 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 HTTP/1 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 HTTP/1 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. Structured Headers in HTTP/1
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 HTTP/1 textual header fields, and protocols compatible with them
(e.g., in HTTP/2 [RFC7540] before HPACK [RFC7541] is applied). (e.g., in HTTP/2 [RFC7540] before HPACK [RFC7541] is applied).
4.1. Serialising Structured Headers into HTTP/1 4.1. Serializing Structured Headers into HTTP/1
Given a structured defined in this specification: Given a structured defined in this specification:
1. If the structure is a dictionary, return the result of 1. If the structure is a dictionary, return the result of
Serialising a Dictionary (Section 4.1.1). Serializing a Dictionary (Section 4.1.1).
2. If the structure is a parameterised list, return the result of 2. If the structure is a parameterized list, return the result of
Serialising a Parameterised List (Section 4.1.4). Serializing a Parameterized List (Section 4.1.4).
3. If the structure is a list of lists, return the result of 3. If the structure is a list of lists, return the result of
Serialising a List of Lists ({ser-listlist}). Serializing a List of Lists ({ser-listlist}).
4. If the structure is a list, return the result of Serialising a 4. If the structure is a list, return the result of Serializing a
List Section 4.1.2. List Section 4.1.2.
5. If the structure is an item, return the result of Serialising an 5. If the structure is an item, return the result of Serializing an
Item (Section 4.1.5). Item (Section 4.1.5).
6. Otherwise, fail serialisation. 6. Otherwise, fail serialisation.
4.1.1. Serialising a Dictionary 4.1.1. Serializing a Dictionary
Given a dictionary as input_dictionary: 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_dictionary: 2. For each member mem of input_dictionary:
1. Let name be the result of applying Serialising an Key 1. Let name be the result of applying Serializing a Key
(Section 4.1.1.1) to mem's member-name. (Section 4.1.1.1) to mem's member-name.
2. Append name to output. 2. Append name to output.
3. Append "=" to output. 3. Append "=" to output.
4. Let value be the result of applying Serialising an Item 4. Let value be the result of applying Serializing an Item
(Section 4.1.5) to mem's member-value. (Section 4.1.5) to mem's member-value.
5. Append value to output. 5. Append value to output.
6. If more members remain in input_dictionary: 6. 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.1.1. Serialising a Key 4.1.1.1. Serializing a Key
Given a key as input_key: Given a key as input_key:
1. If input_key is not a sequence of characters, or contains 1. If input_key is not a sequence of characters, or contains
characters not allowed in the ABNF for key, fail serialisation. characters not allowed in the ABNF for key, fail serialisation.
2. Let output be an empty string. 2. Let output be an empty string.
3. Append input_key to output, using ASCII encoding [RFC0020]. 3. Append input_key to output, using ASCII encoding [RFC0020].
4. Return output. 4. Return output.
4.1.2. Serialising a List 4.1.2. Serializing a List
Given a list as input_list: Given a list as input_list:
1. Let output be an empty string. 1. Let output be an empty string.
2. For each member mem of input_list: 2. For each member mem of input_list:
1. Let value be the result of applying Serialising an Item 1. Let value be the result of applying Serializing an Item
(Section 4.1.5) to mem. (Section 4.1.5) to mem.
2. Append value to output. 2. Append value to output.
3. If more members remain in input_list: 3. If more members remain in input_list:
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.3. Serializing a List of Lists
Given a list of lists of items as input_list: Given a list of lists of items as input_list:
1. Let output be an empty string. 1. Let output be an empty string.
2. For each member inner_list of input_list: 2. For each member inner_list of input_list:
1. If inner_list is not a list, fail serialisation. 1. If inner_list is not a list, fail serialisation.
2. If inner_list is empty, fail serialisation. 2. If inner_list is empty, fail serialisation.
3. For each inner_mem of inner_list: 3. For each inner_mem of inner_list:
1. Let value be the result of applying Serialising an Item 1. Let value be the result of applying Serializing an Item
(Section 4.1.5) to inner_mem. (Section 4.1.5) to inner_mem.
2. Append value to output. 2. Append value to output.
3. If more members remain in inner_list: 3. If more members remain in inner_list:
1. Append a ";" to output. 1. Append a ";" to output.
2. Append a single WS to output. 2. Append a single WS to output.
4. If more members remain in input_list: 4. If more members remain in input_list:
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.4. Serialising a Parameterised List 4.1.4. Serializing a Parameterized List
Given a parameterised list as input_plist: Given a parameterized list as input_plist:
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_plist:
1. Let id be the result of applying Serialising a Token 1. Let id be the result of applying Serializing a Token
(Section 4.1.9) to mem's token. (Section 4.1.9) to mem's token.
2. Append id to output. 2. Append id to output.
3. For each parameter in mem's parameters: 3. For each parameter in mem's parameters:
1. Append ";" to output. 1. Append ";" to output.
2. Let name be the result of applying Serialising a Key 2. Let name be the result of applying Serializing a Key
(Section 4.1.1.1) to parameter's param-name. (Section 4.1.1.1) to parameter's param-name.
3. Append name to output. 3. Append name to output.
4. If parameter has a param-value: 4. If parameter has a param-value:
1. Let value be the result of applying Serialising an 1. Let value be the result of applying Serializing an
Item (Section 4.1.5) to parameter's param-value. Item (Section 4.1.5) to parameter's param-value.
2. Append "=" to output. 2. Append "=" to output.
3. Append value to output. 3. Append value to output.
4. If more members remain in input_plist: 4. 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.5. Serialising an Item 4.1.5. 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.6) 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.7) 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.8) 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.9) 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.11) 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.10) to input_item.
7. Otherwise, fail serialisation. 7. Otherwise, fail serialisation.
4.1.6. Serialising an Integer 4.1.6. 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.7. 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 16, line 45
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.8. 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.
skipping to change at page 17, line 13 skipping to change at page 17, line 21
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, using ASCII encoding [RFC0020].
5. Append DQUOTE to output. 5. Append DQUOTE to output.
6. Return output. 6. Return output.
4.1.9. Serialising a Token 4.1.9. 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.9}, 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, using ASCII encoding [RFC0020].
4. Return output. 4. Return output.
4.1.10. Serialising a Byte Sequence 4.1.10. 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 18, line 9
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.11. 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.
skipping to change at page 18, line 45 skipping to change at page 18, line 49
2. If header_type is "dictionary", let output be the result of 2. If header_type is "dictionary", let output be the result of
Parsing a Dictionary from Text (Section 4.2.1). 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.3).
4. If header_type is "list-list", let output be the result of 4. If header_type is "list-list", let output be the result of
Parsing a List of Lists from Text (Section 4.2.4). Parsing a List of Lists from Text (Section 4.2.4).
5. If header_type is "param-list", let output be the result of 5. If header_type is "param-list", let output be the result of
Parsing a Parameterised List from Text (Section 4.2.5). Parsing a Parameterized List from Text (Section 4.2.5).
6. If header_type is "item", let output be the result of Parsing an 6. 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.7).
7. Discard any leading OWS from input_string. 7. Discard any leading OWS from input_string.
8. If input_string is not empty, fail parsing. 8. If input_string is not empty, fail parsing.
9. Otherwise, return output. 9. Otherwise, return output.
When generating input_string, parsers MUST combine all instances of When generating input_string, 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, Lists of Lists, Parameterized Lists and Dictionaries, this
has the effect of correctly concatenating all instances of the header has the effect of correctly concatenating all instances of the header
field, as long as individual individual members of the top-level data field, as long as individual individual members of the top-level data
structure are not split across multiple header instances. structure are not 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 Integers, Floats and Byte Sequences cannot be split across multiple
headers because the inserted commas will cause parsing to fail. 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 cannot loosen this requirement.
Note that this has the effect of discarding any header field with Note that this has the effect of discarding any header field with
skipping to change at page 22, line 13 skipping to change at page 22, line 22
2. Let inner_list be an empty array. 2. Let inner_list be an empty array.
7. Else if char is not ";", fail parsing. 7. Else if char is not ";", fail parsing.
8. Discard any leading OWS from input_string. 8. Discard any leading OWS from input_string.
9. If input_string is empty, fail parsing. 9. If input_string is empty, fail parsing.
4. No structured data has been found; fail parsing. 4. No structured data has been found; fail parsing.
4.2.5. Parsing a Parameterised List from Text 4.2.5. Parsing a Parameterized List from Text
Given an ASCII string input_string, return a list of parameterised Given an ASCII string input_string, return a list of parameterized
identifiers. input_string is modified to remove the parsed value. identifiers. input_string is modified to remove the parsed value.
1. Let items be an empty array. 1. Let items be an empty array.
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 item be the result of running Parse Parameterized
Identifier from Text (Section 4.2.6) with input_string. Identifier from Text (Section 4.2.6) with input_string.
2. Append item to items. 2. Append item to items.
3. Discard any leading OWS from input_string. 3. Discard any leading OWS from input_string.
4. If input_string is empty, return items. 4. If input_string is empty, return items.
5. Consume the first character of input_string; if it is not 5. Consume the first character of input_string; if it is not
COMMA, fail parsing. COMMA, fail parsing.
6. Discard any leading OWS from input_string. 6. Discard any leading OWS from input_string.
7. If input_string is empty, fail parsing. 7. If input_string is empty, fail parsing.
3. No structured data has been found; fail parsing. 3. No structured data has been found; fail parsing.
4.2.6. Parsing a Parameterised Identifier from Text 4.2.6. Parsing a Parameterized Identifier from Text
Given an ASCII string input_string, return an token with an unordered Given an ASCII string input_string, return an token with an unordered
map of parameters. input_string is modified to remove the parsed map of parameters. input_string is modified to remove the parsed
value. value.
1. Let primary_identifier be the result of Parsing a Token from Text 1. Let primary_identifier be the result of Parsing a Token from Text
(Section 4.2.10) from input_string. (Section 4.2.10) from input_string.
2. Let parameters be an empty, ordered map. 2. Let parameters be an empty, ordered map.
skipping to change at page 27, line 11 skipping to change at page 27, line 26
4. Let b64_content be the result of removing content of input_string 4. Let b64_content be the result of removing content of input_string
up to but not including the first instance of the character "*". 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
skipping to change at page 28, line 10 skipping to change at page 28, line 22
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 43 skipping to change at page 30, line 49
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.
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 a list of key/value pairs, we use a
Parameterised List to represent them, with the token for each item in Parameterized List to represent them, with the token for each item in
the list used to identify it in the "descriptions" member of the the list used to identify it in the "descriptions" member of the
Example-Thing header. Example-Thing 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? B.3. What should generic Structured Headers implementations expose?
A generic implementation should expose the top-level parse A generic implementation should expose the top-level parse
(Section 4.2) and serialise (Section 4.1) functions. They need not (Section 4.2) and serialize (Section 4.1) functions. They need not
be functions; for example, it could be implemented as an object, with be functions; for example, it could be implemented as an object, with
methods for each of the different top-level types. 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 Appendix C. 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 C.1. Since draft-ietf-httpbis-header-structure-10
_None yet._
C.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 C.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 32, line 41
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 C.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 C.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 C.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 C.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 C.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 C.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 C.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 C.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. 74 change blocks. 
86 lines changed or deleted 93 lines changed or added

This html diff was produced by rfcdiff 1.44jr. The latest version is available from http://tools.ietf.org/tools/rfcdiff/