-
Notifications
You must be signed in to change notification settings - Fork 85
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
Add proxies::Forwarded
header
#221
Conversation
I think using a Cow under the hood might make sense, but we probably shouldn't surface it to the end-user. So far I've been trying to make enums expose HTTP terminology only, and caring a bit less about internal optimizations. Also for |
@yoshuawuyts How do you think |
I guess the question is how 1:1 the headers types should be with a single header |
It's my understanding that those are no longer used much, and mostly exist for backwards compat purposes? Afaik they haven't been specced either. Perhaps let's not care about it now, and if we ever want to do something there we can add some higher-level "proxy" submodule (perhaps in Tide?) that is aware of how to handle this? |
Unfortunately, I think the standardization of forwarded isn't yet complete, and the x- variants are still common in the wild. A quick search turned up references like https://devcenter.heroku.com/articles/http-routing#heroku-headers, and there are "de facto" specs:
However, the forwarded spec also encourages implementers to convert from the x- headers to forwarded: https://tools.ietf.org/html/rfc7239.html#section-7.4, so it seems legit to consider them "the same thing" and accept either but only output Forwarded (like good spec-abiding implementers) |
Forwarded is part of RFC 7239, dated 2014. The iana HTTP header overview lists it as an accepted standard (experimental headers are highlighted). Given how long it's been around it would be surprising if it this wasn't supported by modern servers. Perhaps a compromise we can make here is that we try and detect X-Forwarded-For as a fallback in |
Exactly what I suggested in the edit to #221 (comment), which I might have made at the same time as you posted this 👍 Also switching to making each field an |
Ah interesting; none of the other headers has a fallibly apply. They all assume that once they contain a value it's valid; this makes it easy to reason about the inner state for both parsing and encoding. What would the error be that surfaces for apply? Is there a way we could surface it sooner? |
3f80510
to
14b33f3
Compare
14b33f3
to
703611d
Compare
@yoshuawuyts @Fishrock123 This is now ready for review. Although I do hope that this is fairly readable as far as hand-rolled nearly-zero-copy parsers go, I think the most valuable way to review this would be to take a look at the spec and the test cases before looking at the implementation. The general approach to parsing in this pr is for parsers to return It was unnecessary in this PR, but it would not be terribly hard to write higher order logic based on a |
src/proxies/forwarded.rs
Outdated
/// let mut request = Request::new(Get, Url::parse("http://_/").unwrap()); | ||
/// request.insert_header("X-Forwarded-For", "192.0.2.43, 2001:db8:cafe::17"); | ||
/// request.insert_header("X-Forwarded-Proto", "https"); | ||
/// let forwarded = Forwarded::from_headers(&request).unwrap().unwrap(); |
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.
These examples may be more useful written in the way we will likely suggest of their use in real code, I'm thinking:
if let Some(forwarded) = Forwarded::from_headers(&request)? {
// ...
}
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.
Halfway addressed. Switched to from_headers(&request)?.unwrap()
— it doesn't make sense to have a doctest that includes a conditional we know to be true
/// header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded). | ||
#[derive(Debug, Clone, Default)] | ||
pub struct Forwarded<'a> { | ||
by: Option<Cow<'a, str>>, |
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.
Is this lifetime necessary on the struct, or can these be '_
?
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.
Necessary, I believe. I'll try it to be sure, though
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.
If this were '_, I believe there would be no assurance to the compiler that the forwarded has the same lifetime as the &impl AsRef<Headers>
, and that all the Cows have same lifetime as the request/response. And we need that because in the borrowed state, we're just pointing at data held in the request/response
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.
Ok, I really don't understand lifetimes in structures yet, I think.
(Note: I did not review the spec) |
Co-authored-by: Jeremiah Senkpiel <fishrock123@rocketmail.com>
and switch to taking an impl Into<Cow<'a, str>>
I've removed the with_… chainable methods from this, should be good to go, cc @yoshuawuyts CI failing for unrelated reasons (async-std 1.6.3 doesn't compile on wasm) |
Experimented a bit with a COW-like interface for the forwarded header. Let me know if you'd prefer to switch to just the Owned version. Alternatively, if y'all like this pattern, we might want to use it for other headersedit: switching to draft — noticed some additional complexity in the spec that this version doesn't handle. Interested in feedback on the Cow-like interface, thoughOk! This pr now includes is now an efficient and correct hand-rolled parser for tokens and quoted strings as defined by https://tools.ietf.org/html/rfc7230#section-3.2.6, and for the Forwarded header, including a spec-conforming normalization from the x-forwarded-{for, proto, and by} headers. Hopefully the token and quoted-string parsers will be helpful for other header parsers in http-types
Ref #99