-
-
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
Original Header Cases API #2695
Comments
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
We've also been bitten by this unfortunately. We know and realize that HTTP headers should be lower case. Alas, some of our customers have compatibility requirements because they've been sending them as upper case (or camel case, depending) and some of their customers rely on them being of specific casing. I'd be really grateful for even an experimental |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
How about this as a public API? pub trait HttpMessageExt {
fn headers_case_sensitive(&self) -> CaseSensitiveHeaderMap<'_>;
fn headers_case_sensitive_mut(&mut self) -> CaseSensitiveHeaderMapMut<'_>;
}
impl<T> HttpMessageExt for http::Request<T> { /* ... */ }
impl<T> HttpMessageExt for http::Response<T> { /* ... */ }
// CaseSensitiveHeaderMap and CaseSensitiveHeaderMapMut methods would be more or less obvious, I guess? For // request.rs
impl<T> Request<T> {
pub fn parts_mut(&mut self) -> (PartsMut<'_>, &mut T) { /* ... */ }
}
pub struct PartsMut<'a> {
/// The request's method
pub method: &'a mut Method,
/// The request's URI
pub uri: &'a mut Uri,
/// The request's version
pub version: &'a mut Version,
/// The request's headers
pub headers: &'a mut HeaderMap<HeaderValue>,
/// The request's extensions
pub extensions: &'a mut Extensions,
_priv: (),
}
// response.rs - equivalent with slightly different fields |
Hm. What would be the specific way a user would interact with this? What would the methods of |
Some examples let headers = response.headers_case_sensitive();
// Check for a header using the exact provided casing
if let Some(val) = message.headers_case_sensitive().get("Foo-Bar") {
// read val: HeaderValue
}
let mut headers = request.headers_case_sensitive();
// Insert a header using the exact provided casing
headers.insert("Foo-Bar", <header value>); Methods-wise, I could see this type having all of the methods (not constructors of course) of impl<'a> CaseSensitiveHeaderMap<'a> {
pub fn contains_key(&self, key: impl AsCaseSensitiveHeaderName) -> bool;
pub fn get(&self, key: impl AsaseSensitiveHeaderName) -> Option<&'a HeaderValue>;
// GetAll<'a>: IntoIterator<Item = &'a HeaderValue>
pub fn get_all(&self, key: impl AsCaseSensitiveHeaderName) -> GetAll<'a>;
// Iter<'a>: Iterator<Item = (&'a CaseSensitiveHeaderName, &'a HeaderValue)
pub fn iter(&self) -> Iter<'a>;
}
impl<'a> CaseSensitiveHeaderMapMut<'a> {
// same methods as CaseSensitiveHeaderMap
pub fn append(&mut self, key: impl IntoCaseSensitiveHeaderName, value: HeaderValue) -> bool;
pub fn insert(&mut self, key: impl IntoCaseSensitiveHeaderName, value: HeaderValue) -> Option<HeaderValue>;
// also try_append, try_insert
pub fn get_mut(&mut self, key: impl IntoCaseSensitiveHeaderName) -> Option<&mut HeaderValue);
pub fn remove(&mut self, key: impl IntoCaseSensitiveHeaderName) -> Option<HeaderValue>;
// IterMut<'a>: Iterator<Item = (&'a CaseSensitiveHeaderName, &'a mut HeaderValue)>
pub fn iter_mut(&mut self) -> IterMut<'_>;
}
pub trait AsCaseSensitiveHeaderName: hdr_as::Sealed {}
pub trait IntoCaseSensitiveHeaderName: hdr_into::Sealed {}
// similar impls, sealed traits as for upstream traits
#[repr(transparent)]
struct CaseSensitiveHeaderName([u8]); |
Here's my suggestion: I'd aim for just figuring out the minimal methods needed to expose the existing |
Alright, I can definitely work on that. At what level do you want to encapsulate things, though? Do you want the actual type stored in request / response extensions to be private? If yes, why? If not, sounds like the minimal API would just be what's already there, just made public, right? |
Sorta. The methods that currently exist were just the easiest to work internally. No care was taken regarding flexibility, forwards compatibility, what would be easier to extend in the future. What makes it impossible to refactor the internals if we try to make it faster. Those sorts of questions. Like, should the values just be |
This is a tracking issue for the feature to allow for sending and receiving the exact casing of header names, instead of the forced lowercasing of
http
. In most situations, simply forcing to lowercase is the better option, as it allows for a more performantHeaderMap
, and is the required format for newer versions of HTTP (HTTP/2 and 3). However, there are rare occasions when being able to see the exact casing is needed.Some initial support is available in hyper, and is exposed in the C API. But a public Rust API is not yet available.
The text was updated successfully, but these errors were encountered: