Repository navigation
clarity around http headers #1402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,7 +184,9 @@ The [`data`](#22-data) byte-sequence is used as the HTTP message body. | |
| #### 3.1.3. Metadata Headers | ||
|
|
||
| All other [CloudEvents][ce] attributes, including extensions, MUST be | ||
| individually mapped to and from distinct HTTP message header. | ||
| individually mapped to and from distinct HTTP message headers and follow | ||
| the guidelines defined by the | ||
| [HTTP specification](https://www.rfc-editor.org/info/rfc9110/#section-5.1). | ||
|
|
||
| CloudEvents extensions that define their own attributes MAY define a secondary | ||
| mapping to HTTP headers for those attributes, especially if specific attributes | ||
|
|
@@ -205,7 +207,7 @@ Examples: | |
| * `id` maps to `ce-id` | ||
| * `specversion` maps to `ce-specversion` | ||
|
|
||
| Note: per the [HTTP](https://tools.ietf.org/html/rfc7230#section-3.2) | ||
| Note: per the [HTTP](https://www.rfc-editor.org/info/rfc9110/#section-5.1) | ||
| specification, header names are case-insensitive. | ||
|
|
||
| ##### 3.1.3.2. HTTP Header Values | ||
|
|
@@ -214,52 +216,36 @@ The value for each HTTP header is constructed from the respective attribute | |
| type's [canonical string representation][ce-types]. | ||
|
|
||
| Some CloudEvents metadata attributes can contain arbitrary UTF-8 string content, | ||
| and per [RFC7230, section 3][rfc7230-section-3], HTTP headers MUST only use | ||
| printable characters from the US-ASCII character set, and are terminated by a | ||
| CRLF sequence with OPTIONAL whitespace around the header value. | ||
|
|
||
| When encoding a CloudEvent as an HTTP message, string values | ||
| represented as HTTP header values MUST be percent-encoded as | ||
| described below. This is compatible with [RFC3986, section | ||
| 2.1][rfc3986-section-2-1] but is more specific about what needs | ||
| encoding. The resulting string SHOULD NOT be further encoded. | ||
| (Rationale: quoted string escaping is unnecessary when every space | ||
| and double-quote character is already percent-encoded.) | ||
|
|
||
| When decoding an HTTP message into a CloudEvent, any HTTP header | ||
| value MUST first be unescaped with respect to double-quoted strings, | ||
| as described in [RFC7230, section 3.2.6][rfc7230-section-3-2-6]. A single | ||
| round of percent-decoding MUST then be performed as described | ||
| below. HTTP headers for CloudEvent attribute values do not support | ||
| parenthetical comments, so the initial unescaping only needs to handle | ||
| double-quoted values, including processing backslash escapes within | ||
| double-quoted values. Header values produced via the | ||
| percent-encoding described here will never include double-quoted | ||
| values, but they MUST be supported when receiving events, for | ||
| compatibility with older versions of this specification which did | ||
| not require double-quote and space characters to be percent-encoded. | ||
|
|
||
| Percent encoding is performed by considering each Unicode character | ||
| within the attribute's canonical string representation. Any | ||
| character represented in memory as a [Unicode surrogate | ||
| pair][surrogate-pair] MUST be treated as a single Unicode character. | ||
| The following characters MUST be percent-encoded: | ||
|
|
||
| - Space (U+0020) | ||
| - Double-quote (U+0022) | ||
| - Percent (U+0025) | ||
| - Any characters outside the printable ASCII range of U+0021-U+007E | ||
| inclusive | ||
|
|
||
| Attribute values are already constrained to prohibit characters in | ||
| the range U+0000-U+001F inclusive and U+007F-U+009F inclusive; | ||
| however for simplicity and to account for potential future changes, | ||
| it is RECOMMENDED that any HTTP header encoding implementation treats | ||
| such characters as requiring percent-encoding. | ||
|
|
||
| Space and double-quote are encoded to avoid requiring any further | ||
| quoting. Percent is encoded to avoid ambiguity with percent-encoding | ||
| itself. | ||
| and per the | ||
| [HTTP specification](https://www.rfc-editor.org/info/rfc9110/#section-5), any | ||
| non-printable characters from the US-ASCII character set MUST be encoded. | ||
| CloudEvents implementations MUST use | ||
| [percent-encoding](https://www.rfc-editor.org/info/rfc8187). | ||
|
|
||
| Implementations MAY choose to percent-encode printable US-ASCII characters in | ||
| addition to the characters mandated to be encoded by | ||
| [RFC8187](https://www.rfc-editor.org/info/rfc8187). | ||
|
|
||
| Since CloudEvents does not define a list/array data type, CloudEvents HTTP | ||
| headers SHOULD NOT need to leverage the "combined field value" | ||
| feature of HTTP where multiple header values can be specified on a single | ||
| HTTP header separated by a comma (`,`). | ||
|
|
||
| Previous versions of the CloudEvents specification mandated that all | ||
| non-leading/trailing spaces be percent-encoded, however, that is no longer the | ||
| case. Instead, per the HTTP specification, only leading or trailing spaces that | ||
| are not meant to be "stripped" MUST be encoded. Note that all spaces that are | ||
| within double-quoted range of characters, or are non-leading/trailing, | ||
| MUST NOT be stripped by receivers. | ||
|
|
||
| Processing of double-quotes MUST adhere to the HTTP specification. | ||
|
|
||
| Percent-encoding is performed by considering each non-printable Unicode | ||
| character (ones outside the ASCII range of U+0021-U+007E) within the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the double quote character always be percent-encoded too?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And do we have to encode a space, if it's already within a string? So for example does "x y" have to be encoded as "x%20y" or is it okay as-is? As the space isn't leading or trailing, I wouldn't expect it to be trimmed.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, double quotes should only be encoded if they are part of the actual value. Otherwise, a double-quote is just for grouping purposes. E.g. if I need leading spaces retained then I can encode them or wrap them in double-quotes. No, you don't need to encode a space that's in a string - so |
||
| attribute's canonical string representation. Any character represented in | ||
| memory as a [Unicode surrogate pair][surrogate-pair] MUST be treated as a | ||
| single Unicode character. Note that percent (`%`), as a character of the | ||
| value and not part of an encoding sequence, MUST also be encoded. | ||
|
|
||
| Steps to encode a Unicode character: | ||
|
|
||
|
|
@@ -272,21 +258,27 @@ Steps to encode a Unicode character: | |
| Percent-encoding SHOULD be performed using upper-case for values A-F, | ||
| but decoding MUST accept lower-case values. | ||
|
|
||
| When performing percent-decoding (when decoding an HTTP message to a | ||
| CloudEvent), values that have been unnecessarily percent-encoded MUST be | ||
| accepted, but encoded byte sequences which are invalid in UTF-8 MUST be | ||
| rejected. (For example, "%C0%A0" is an overlong encoding of U+0020, and | ||
| MUST be rejected.) | ||
| Decoding of an HTTP header value MUST adhere to the HTTP specification. | ||
| For clarity, that includes: | ||
| - removing any non-encoded leading/trailing whitespaces from each value. | ||
| - processing backslashed (`\`) characters within double-quoted ranges. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't mentioned in the encoding part as far as I can see. Should it be?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no it's part of the http spec. I'm trying hard not to duplicate the entire spec - but if you think I should for this I can.... or I can do the other route and remove this "For clarity" section entirely. |
||
| - removing any non-encoded double-quoted characters from each value. | ||
| - decoding any percent-encoded characters. | ||
|
|
||
| Example: a header value of "Euro € 😀" SHOULD be encoded as follows: | ||
| When performing percent-decoding, values that have been unnecessarily | ||
| percent-encoded MUST be accepted, but encoded byte sequences which are invalid | ||
| in UTF-8 MUST be rejected. (For example, "%C0%A0" is an overlong encoding of | ||
| U+0020, and MUST be rejected.) | ||
|
|
||
| - The characters, 'E', 'u', 'r', 'o' do not require encoding | ||
| Example: a header value of `Euro € 😀` SHOULD be encoded as | ||
| follows: | ||
|
|
||
| - The characters, `E`, `u`, `r`, `o` do not require encoding | ||
| - Space, the Euro symbol, and the grinning face emoji require encoding. | ||
| They are characters U+0020, U+20AC and U+1F600 respectively. | ||
| - The encoded HTTP header value is therefore "Euro%20%E2%82%AC%20%F0%9F%98%80" | ||
| where "%20" is the encoded form of space, "%E2%82%AC" is the encoded form | ||
| of the Euro symbol, and "%F0%9F%98%80" is the encoded form of the | ||
| grinning face emoji. | ||
| - The encoded HTTP header value is therefore `Euro %E2%82%AC%F0%9F%98%80` | ||
| where `%E2%82%AC` is the encoded form of the Euro symbol, and `%F0%9F%98%80` | ||
| is the encoded form of the grinning face emoji. | ||
|
|
||
| #### 3.1.4. Examples | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at that RFC, section 5 doesn't actually mention percent-encoding explicitly as far as I can see. I've only skimmed admittedly - should we perhaps clarify exactly which bit of section 5 we're talking about, and maybe link to an additional spec, RFC 3986 perhaps?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're correct that it just says that things must be encoded but it leaves it open for people to choose what encoding mechanism they want. So from that perspective, we're talking about ALL of section 5. I added a link to 3986 for %-encoding.