-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Headers are lower-cased when sent and no option to disable this feature. #1492
Comments
I expected this problem to appear eventually. Clearly, the best thing to happen is for that server software to be fixed. But, I realized that there is likely other janky server software out there that also relies on title case, just rotting with no fix to ever come... Possibly a solution could be for hyper to add an configuration option to force all header names to Title Case when writing to the socket. It could be some |
That would perfectly fit my use case and not affect the functionality of the headers API for general use of the client library part of Hyper. Currently investigating how headers are written for HTTP/1.0 and HTTP/1.1 connections. |
I found the [1] Lines 638 to 645 in dfdca25
|
It's probably preferable to not have to check a boolean in a loop, so probably a second function. |
Alright, that's what I did for my naive example code (that's still WIP and unpublished). Is it preferable to search for the hyphen and capitalize the next character? Or go character by character in a for loop keeping state in a boolean to capitalize the next character? Or using a My naive example: fn title_case(dst: &mut Vec<u8>, name: &str) {
dst.reserve(name.len());
let mut should_capitalize = true;
for c in name.chars() {
if should_capitalize {
should_capitalize = false;
for c in c.to_uppercase() {
dst.push(c as u8);
}
} else {
if c == '-' {
should_capitalize = true;
}
dst.push(c as u8);
}
}
} |
A fn title_case(dst: &mut Vec<u8>, name: &str) {
dst.reserve(name.len());
let mut iter = name.chars();
let push_uppercase = |dst: &mut Vec<u8>, iter: &mut ::std::str::Chars| {
if let Some(c) = iter.next() {
for c in c.to_uppercase() {
dst.push(c as u8);
}
}
};
push_uppercase(dst, &mut iter);
while let Some(c) = iter.next() {
dst.push(c as u8);
if c == '-' {
push_uppercase(dst, &mut iter);
}
}
} |
Since header names are required to be ASCII, you can just work with the bytes directly. That has better performance than |
Revised this to use a byte slice ( I probably should open up a PR for this now, but I am still trying to work out how to add a configuration option to toggle between title case and straight lowercase output. |
Your use case is the client, right? So it could start there...
|
Made a PR. Thank you so very much for the guidance! |
This introduces support for the HTTP/1 Client to write header names as title case when encoding the request. Closes #1492
I am trying to use Hyper with a stubborn web service that does not like requests with headers that do not have the first letter of each word capitalized (
Content-Length
for example). I tried out some other HTTP client libraries for Rust (liketk-http
which hasn't been updated recently andmio_httpc
which doesn't work all the time with said web service), but Hyper doesn't have the issues as with the other libraries except for the header name mangling.After reading the RFC regarding header casing, I see that header names are supposed to be case-insensitive, so Hyper is not at fault here and from looking at
HeaderMap
I see that it relies on headers being lower-cased for performance.If it is not possible to accommodate case-sensitive header names, then could it be possible to directly provide an array of headers to be used in an HTTP request?
The text was updated successfully, but these errors were encountered: