Seeming contradiction in RFC for HTTP/2 case sensitivity
Asked Answered
W

2

7

There is a confusing bit of terminology in the RFC for HTTP/2 that I wish was clearer.

Per the RFC https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2

Just as in HTTP/1.x, header field names are strings of ASCII characters that are compared in a case-insensitive fashion. However, header field names MUST be converted to lowercase prior to their encoding in HTTP/2. A request or response containing uppercase header field names MUST be treated as malformed

This seems to outline two conflicting ideas

  • Header field names are case-insensitive in HTTP/2
  • If you receive or send fields that are not lowercase, the request/response is malformed.

If a request or response that contains non-lowercase headers is invalid, how can it be considered case-insensitive?

Whisenhunt answered 23/12, 2019 at 23:44 Comment(0)
E
6

There are two levels of "HTTP": a more abstract, upper, layer with the HTTP semantic (e.g. PUT resource r1), and a lower layer where that semantic is encoded. Think of these two as, respectively, the application layer of HTTP, and the network layer of HTTP.

The application layer can be completely unaware of whether the semantic HTTP request PUT r1 has arrived in HTTP/1.1 or HTTP/2 format.
On the other hand, the same semantic, PUT r1, is encoded differently in HTTP/1.1 (textual) vs HTTP/2 (binary) by the network layer.

The referenced section of the specification should be interpreted in the first sentence as referring to the application layer: "as in HTTP/1.1 header names should compared case insensitively".
This means that if an application is asked "is header ACCEPT present?", the application should look at the header names in a case insensitive fashion (or be sure that the implementation provides such feature), and return true if Accept or accept is present.

The second sentence should be interpreted as referring to the network layer: a compliant HTTP/2 implementation MUST send the headers over the network lowercase, because that is how HTTP/2 encodes header names to be sent over the wire.

Nothing forbids a compliant HTTP/2 implementation to receive content-length: 128 (lowercase), but then convert this header into Content-Length: 128 when it makes it available to the application - for example for maximum compatibility with HTTP/1.1 where the header has uppercase first letters (for example to be printed on screen).

Explicate answered 24/12, 2019 at 0:23 Comment(4)
Now I’m confused. OP referred to a single paragraph which doesn’t differentiate between network or application layers. What are you referring to with first and second paragraph?Janiecejanifer
I meant first and second sentence of that section of the specification. I have updated the answer.Explicate
Doesn't make much sense. The text itself doesn't in any way signal the difference you say should be made. What's more, it points to section 8.1.2.6, which uses the terms request and response, which have obvious semantic meaning, not at all related to encoding, and says they should be considered malformed if headers contain uppercase characters. What I make of that paragraph is that http 2 clients should accept headers that contain upper case characters, but never emit them. This, however, contradicts 8.1.2.6, which says that such requests and responses should be considered malformed.Handiwork
The paragraph from the OP at section 8.1.2 speaks about HTTP in more generic terms, what I call the upper layer, now clearly specified by RFC 9110. Section 8.1.2 clearly states that "header field names MUST be converted to lowercase prior to their encoding in HTTP/2.", implying that there are representations of HTTP headers with upper case chars, that must be converted to lowercase when using HTTP/2. Section 8.1.2.6 is specific to HTTP/2 only.Explicate
H
1

It's a mistake, or at least an unnecessarily confusing specification.

Header names must be compared case-insensitive, but that's irrelevant since they are only transmitted or received lowercase.

I.e. in the RFC, "Content-Length" refers to to the header "content-length."


RFC 7540 has been obsoleted by RFC 9113, which states simply:

Field names MUST be converted to lowercase when constructing an HTTP/2 message.

https://www.rfc-editor.org/rfc/rfc9113#section-8.2

And the prose now uses the lowercase header names.

Headachy answered 15/8, 2022 at 4:21 Comment(1)
RFC 9113 is much more strict than 7540, and explicitly makes HTTP/2 headers incompatible with earlier versions of the HTTP spec. In other parts of the spec it also says that you can compare header names case insensitive any time you want, but must treat requests and responses containing headers with uppercase characters as malformed, and not process them.Handiwork

© 2022 - 2024 — McMap. All rights reserved.