Conversation
Currently, various properties of HTTP requests are exposed into the stack target type, meaning that stacks (including their resolutions) cannot be shared across requests that vary by any of these settings and, worse, that per-request determinations must be made to determine which stack to use. In order to perform bind stacks according to connection-level metadata, where these request-level parameters cannot be known, we need to remove this metadata from the stack target. The HTTP server now applies URI normalization as an internal implementation detail (because it's a detail of how hyper clients and servers differ). This eliminates the `ShouldNormalizeUri` trait, as that determination can be made entirely based on the properties of the request without any additional stack-specific metadata. The HTTP client now takes an updated `Settings` type that explicitly handles the orig-proto upgrade logic (removing this from the client stack). Stack targets now hold an `http::Version` on the accept-side, and map that to a per-endpoint `http::client::Settings` for use by the http client.
hawkw
left a comment
There was a problem hiding this comment.
the new factoring makes a lot of sense to me --- this feels simpler and easier to understand. i had some style nits and suggestions, but didn't notice any problems.
| if orig_proto == "HTTP/1.1" { | ||
| Some(http::Version::HTTP_11) | ||
| } else if orig_proto == "HTTP/1.0" { | ||
| Some(http::Version::HTTP_10) | ||
| } else { | ||
| None | ||
| } |
There was a problem hiding this comment.
nit/tioli: could be
| if orig_proto == "HTTP/1.1" { | |
| Some(http::Version::HTTP_11) | |
| } else if orig_proto == "HTTP/1.0" { | |
| Some(http::Version::HTTP_10) | |
| } else { | |
| None | |
| } | |
| match orig_proto { | |
| "HTTP/1.1" => Some(http::Version::HTTP_11), | |
| "HTTP/1.0" => Some(http::Version::HTTP_10), | |
| _ => None, | |
| } |
...unless i'm missing something, of course?
There was a problem hiding this comment.
orig_proto is a HeaderValue and not a string, so the matching form doesn't work
| if client.is_none() { | ||
| debug!("Caching new client"); | ||
| *client = Some(hyper::Client::builder().set_host(absolute_form).build( | ||
| HyperConnect::new(self.connect.clone(), self.target.clone(), absolute_form), | ||
| )); | ||
| } | ||
|
|
||
| client.as_ref().unwrap().request(req) |
There was a problem hiding this comment.
nit/TIOLI: there's actually an [Option::get_or_insert_with] method that basically implements this logic and avoids the unwrap:
| if client.is_none() { | |
| debug!("Caching new client"); | |
| *client = Some(hyper::Client::builder().set_host(absolute_form).build( | |
| HyperConnect::new(self.connect.clone(), self.target.clone(), absolute_form), | |
| )); | |
| } | |
| client.as_ref().unwrap().request(req) | |
| client | |
| .get_or_insert_with(|| { | |
| debug!("Caching new client"); | |
| hyper::Client::builder().set_host(absolute_form).build( | |
| HyperConnect::new(self.connect.clone(), self.target.clone(), absolute_form), | |
| ) | |
| }) | |
| .request(req) |
There was a problem hiding this comment.
Unfortunately, this doesn't play with the borrow checker and self -- because we're holding a mutable ref to the client, we can't pass a reference to self into the closure.
kleimkuhler
left a comment
There was a problem hiding this comment.
This looks good! I have a question about a change in Gateway, but otherwise this makes sense to me.
| .map(|n| NameAddr::from_str(n).unwrap().into()) | ||
| .unwrap_or_else(|| socket_addr.into()), | ||
| http_settings: http::Settings::Http2, | ||
| http_version: http::Version::Http1, |
There was a problem hiding this comment.
Is this now Http1 because we know it should be upgraded to H2? If not, why this change?
There was a problem hiding this comment.
it's a test, so it's not actually used
|
So, this branch seems to impact CI time quite a bit. Locally, I see:
|
Helps compile times for some reason?!
This release fixes a recent regression in multicluster gateway configurations that would forbid inbound gateway traffic. It also fixes URI normalization for orig-proto-upgrade requests that do not include a `Host` header. --- * http: Simplify stacks and target types (linkerd/linkerd2-proxy#656) * Make SkipDetect more generic as stack::MakeSwitch (linkerd/linkerd2-proxy#657) * introduce tests for isolated services (linkerd/linkerd2-proxy#655) * http: Put normalize_uri back on the stack (linkerd/linkerd2-proxy#659) * inbound: Apply loop detection on the connect stack (linkerd/linkerd2-proxy#660) * tracing: Elide redundant info in tracing contexts (linkerd/linkerd2-proxy#661) * outbound: Reorganize outbound stacks (linkerd/linkerd2-proxy#662) * app: Decouple stacks from listeners (linkerd/linkerd2-proxy#663) * inbound: Split HTTP detection stack from TLS (linkerd/linkerd2-proxy#664) * integration: Bundle tests in src (linkerd/linkerd2-proxy#665)
This release fixes a recent regression in multicluster gateway configurations that would forbid inbound gateway traffic. It also fixes URI normalization for orig-proto-upgrade requests that do not include a `Host` header. --- * http: Simplify stacks and target types (linkerd/linkerd2-proxy#656) * Make SkipDetect more generic as stack::MakeSwitch (linkerd/linkerd2-proxy#657) * introduce tests for isolated services (linkerd/linkerd2-proxy#655) * http: Put normalize_uri back on the stack (linkerd/linkerd2-proxy#659) * inbound: Apply loop detection on the connect stack (linkerd/linkerd2-proxy#660) * tracing: Elide redundant info in tracing contexts (linkerd/linkerd2-proxy#661) * outbound: Reorganize outbound stacks (linkerd/linkerd2-proxy#662) * app: Decouple stacks from listeners (linkerd/linkerd2-proxy#663) * inbound: Split HTTP detection stack from TLS (linkerd/linkerd2-proxy#664) * integration: Bundle tests in src (linkerd/linkerd2-proxy#665)
Currently, various properties of HTTP requests are exposed into the
stack target type, meaning that stacks (including their resolutions)
cannot be shared across requests that vary by any of these settings and,
worse, that per-request determinations must be made to determine which
stack to use.
In order to bind stacks according to connection-level metadata,
where these request-level parameters cannot be known, we need to remove
this metadata from the stack target.
The HTTP server now applies URI normalization as an internal
implementation detail (because it's a detail of how hyper clients and
servers differ). This eliminates the
ShouldNormalizeUritrait, as thatdetermination can be made entirely based on the properties of the
request without any additional stack-specific metadata.
The HTTP client now takes an updated
Settingstype that explicitlyhandles the orig-proto upgrade logic (removing this from the client
stack).
Stack targets now hold an
http::Versionon the accept-side, and mapthat to a per-endpoint
http::client::Settingsfor use by the httpclient.