mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 12:13:42 +01:00
Send the client's Host as :authority to HTTP/2 upstreams
Dropping Host lost a virtual host that differs from the CONNECT target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
11aca4539d
commit
4abc882e13
2 files changed
+25
-14
No files matched your search
@@ -412,26 +412,26 @@ async fn forward_https(
|
||||
|
||||
let (mut parts, body) = req.into_parts();
|
||||
let uri = match &upstream {
|
||||
Upstream::H2(_) => url.parse::<Uri>(),
|
||||
// `Host` moves into `:authority`. Google's servers reset any stream that has both, even
|
||||
// when they match.
|
||||
Upstream::H2(_) => match parts.headers.remove(HOST) {
|
||||
Some(host) => match host.to_str() {
|
||||
Ok(host) => format!("https://{host}{path}").parse::<Uri>(),
|
||||
Err(e) => return Ok(flow.fail(e.to_string())),
|
||||
},
|
||||
None => url.parse::<Uri>(),
|
||||
},
|
||||
Upstream::H1(_) => path.parse::<Uri>(),
|
||||
};
|
||||
parts.uri = match uri {
|
||||
Ok(uri) => uri,
|
||||
Err(e) => return Ok(flow.fail(e.to_string())),
|
||||
};
|
||||
match &upstream {
|
||||
// The URL carries `:authority`. Google's servers reset any stream that also has `Host`,
|
||||
// even a matching one.
|
||||
Upstream::H2(_) => {
|
||||
parts.headers.remove(HOST);
|
||||
}
|
||||
Upstream::H1(_) => {
|
||||
if !parts.headers.contains_key(HOST)
|
||||
&& let Ok(host) = target.authority.parse()
|
||||
{
|
||||
parts.headers.insert(HOST, host);
|
||||
}
|
||||
}
|
||||
if matches!(upstream, Upstream::H1(_))
|
||||
&& !parts.headers.contains_key(HOST)
|
||||
&& let Ok(host) = target.authority.parse()
|
||||
{
|
||||
parts.headers.insert(HOST, host);
|
||||
}
|
||||
let outgoing = Request::from_parts(parts, flow.capture_request(body));
|
||||
|
||||
|
||||
@@ -441,6 +441,17 @@ async fn https_h2_upstream_gets_authority_without_host() {
|
||||
assert!(captured_host, "the captured request keeps Host");
|
||||
}
|
||||
|
||||
/// A `Host` other than the CONNECT target still names the virtual host upstream.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn https_h2_upstream_gets_the_clients_host_as_authority() {
|
||||
let h = Harness::start(1024);
|
||||
let upstream = spawn_upstream(Some(h.pki.server.clone())).await;
|
||||
let url = format!("https://localhost:{}/authority", upstream.port());
|
||||
|
||||
let resp = h.client().get(&url).header("host", "yaak.test:8443").send().await.unwrap();
|
||||
assert_eq!(resp.text().await.unwrap(), "authority=yaak.test:8443 host=none");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn https_not_found() {
|
||||
let h = Harness::start(1024);
|
||||
|
||||
Reference in new issue
Block a user