http icon indicating copy to clipboard operation
http copied to clipboard

Header fields should be case insensitive (RFC 7230 §3.2, RFC 9110 §5.1)

Open tgrushka opened this issue 1 year ago • 1 comments

I'm working with http::HeaderMap and noticed that HeaderMap::get, HeaderMap::insert, and HeaderName::from_static all seem to be case sensitive (in fact, the latter panics:

HeaderName::from_static("Content-Type")

panics with:

index out of bounds: the len is 0 but the index is 0

while:

HeaderName::from_static("content-type")

does not.

This goes against the HTTP spec requiring case-insensitive handling of header values:

  • RFC 7230 §3.2

    Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace.

  • RFC 9110 §5.1

    Field names are case-insensitive...

IMO, this is distinct from #670, and in fact case-insensitive keys should solve that issue as well, while not requiring the original cases to be changed.

It looks like crates like case_insensitive_hashmap and unicase are examples of case-insensitive String handling.

Is there any way to just make the HeaderMap case-insensitive for retrieval? That would preserve original case as well as allow any case for HeaderMap::get to meet the spec and prevent errors.

tgrushka avatar Dec 13 '24 02:12 tgrushka

HeaderName does support any casing, depending on how you use it. If you are parsing dynamic strings, such as with TryFrom or FromStr or from_bytes, etc, then it will handle and normalize the casing.

What you've noticed is that using a static string will enforce that the casing is lowercase. That was decided because static string likely means you have access to it at compile-time, so we can enforce that it is the optimal case. If you want dynamic casing, parse the values as a HeaderName first.

For some more background, there's some explanation in https://docs.rs/http/latest/http/header/index.html.

seanmonstar avatar Dec 13 '24 16:12 seanmonstar