Skip to content

Commit afbcfa6

Browse files
authored
Merge pull request #2747 from fermyon/allow-uri-authority
Also allow getting authority from the request URI's authority.
2 parents 8fd30f5 + 1d31765 commit afbcfa6

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

crates/trigger-http2/src/server.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::{collections::HashMap, future::Future, io::IsTerminal, net::SocketAddr, sync::Arc};
22

3-
use anyhow::Context;
4-
use http::{uri::Scheme, Request, Response, StatusCode, Uri};
3+
use anyhow::{bail, Context};
4+
use http::{
5+
uri::{Authority, Scheme},
6+
Request, Response, StatusCode, Uri,
7+
};
58
use http_body_util::BodyExt;
69
use hyper::{
710
body::{Bytes, Incoming},
@@ -392,29 +395,39 @@ impl HttpServer {
392395
/// The incoming request's scheme and authority
393396
///
394397
/// The incoming request's URI is relative to the server, so we need to set the scheme and authority.
395-
/// The `Host` header is used to set the authority. This function will error if no `Host` header is
396-
/// present or if it is not parsable as an `Authority`.
398+
/// Either the `Host` header or the request's URI's authority is used as the source of truth for the authority.
399+
/// This function will error if the authority cannot be unambiguously determined.
397400
fn set_req_uri(req: &mut Request<Body>, scheme: Scheme) -> anyhow::Result<()> {
398401
let uri = req.uri().clone();
399402
let mut parts = uri.into_parts();
400403
let headers = req.headers();
401-
let host_header = headers
404+
let header_authority = headers
402405
.get(http::header::HOST)
403-
.context("missing 'Host' header")?
404-
.to_str()
405-
.context("'Host' header is not valid UTF-8")?;
406-
let authority = host_header
407-
.parse()
408-
.context("'Host' header contains an invalid authority")?;
409-
// Ensure that if `req.authority` is set, it matches what was in the `Host` header
410-
// https://github.com/hyperium/hyper/issues/1612
411-
if let Some(a) = parts.authority.as_ref() {
412-
if a != &authority {
413-
return Err(anyhow::anyhow!(
414-
"authority in 'Host' header does not match authority in URI"
415-
));
406+
.map(|h| -> anyhow::Result<Authority> {
407+
let host_header = h.to_str().context("'Host' header is not valid UTF-8")?;
408+
host_header
409+
.parse()
410+
.context("'Host' header contains an invalid authority")
411+
})
412+
.transpose()?;
413+
let uri_authority = parts.authority;
414+
415+
// Get authority either from request URI or from 'Host' header
416+
let authority = match (header_authority, uri_authority) {
417+
(None, None) => bail!("no 'Host' header present in request"),
418+
(None, Some(a)) => a,
419+
(Some(a), None) => a,
420+
(Some(a1), Some(a2)) => {
421+
// Ensure that if `req.authority` is set, it matches what was in the `Host` header
422+
// https://github.com/hyperium/hyper/issues/1612
423+
if a1 != a2 {
424+
return Err(anyhow::anyhow!(
425+
"authority in 'Host' header does not match authority in URI"
426+
));
427+
}
428+
a1
416429
}
417-
}
430+
};
418431
parts.scheme = Some(scheme);
419432
parts.authority = Some(authority);
420433
*req.uri_mut() = Uri::from_parts(parts).unwrap();

0 commit comments

Comments
 (0)