diff --git a/src/bind.rs b/src/bind.rs index 7789a9dda..36bb1fbb6 100644 --- a/src/bind.rs +++ b/src/bind.rs @@ -20,7 +20,11 @@ use ctx::transport::TlsStatus; use watch_service::{WatchService, Rebind}; /// An HTTP `Service` that is created for each `Endpoint` and `Protocol`. -pub type Stack = proxy::http::orig_proto::Upgrade>>; +pub type Stack = proxy::http::orig_proto::Upgrade< + proxy::http::normalize_uri::Service< + WatchTls + > +>; type WatchTls = WatchService>; @@ -131,20 +135,6 @@ pub enum Host { NoAuthority, } -/// Rewrites HTTP/1.x requests so that their URIs are in a canonical form. -/// -/// The following transformations are applied: -/// - If an absolute-form URI is received, it must replace -/// the host header (in accordance with RFC7230#section-5.4) -/// - If the request URI is not in absolute form, it is rewritten to contain -/// the authority given in the `Host:` header, or, failing that, from the -/// request's original destination according to `SO_ORIGINAL_DST`. -#[derive(Copy, Clone, Debug)] -pub struct NormalizeUri { - inner: S, - was_absolute_form: bool, -} - pub struct RebindTls { bind: Bind, protocol: Protocol, @@ -293,7 +283,10 @@ where // and request URI are not in agreement, or are not present. // // TODO move this into proxy::Client? - let normalize_uri = NormalizeUri::new(watch_tls, protocol.was_absolute_form()); + let normalize_uri = proxy::http::normalize_uri::Service::new( + watch_tls, + protocol.was_absolute_form() + ); // Upgrade HTTP/1.1 requests to be HTTP/2 if the endpoint supports HTTP/2. proxy::http::orig_proto::Upgrade::new(normalize_uri, protocol.is_http2()) @@ -356,41 +349,6 @@ where } } - -// ===== impl NormalizeUri ===== - -impl NormalizeUri { - fn new(inner: S, was_absolute_form: bool) -> Self { - Self { inner, was_absolute_form } - } -} - -impl tower::Service for NormalizeUri -where - S: tower::Service>, -{ - type Request = S::Request; - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self) -> Poll<(), S::Error> { - self.inner.poll_ready() - } - - fn call(&mut self, mut request: S::Request) -> Self::Future { - if request.version() != http::Version::HTTP_2 && - // Skip normalizing the URI if it was received in - // absolute form. - !self.was_absolute_form - { - proxy::http::h1::normalize_our_view_of_uri(&mut request); - } - self.inner.call(request) - } -} -// ===== impl Binding ===== - impl tower::Service for BoundService where B: tower_h2::Body + Send + 'static, diff --git a/src/proxy/http/mod.rs b/src/proxy/http/mod.rs index 5289aa6b0..2723ca981 100644 --- a/src/proxy/http/mod.rs +++ b/src/proxy/http/mod.rs @@ -1,9 +1,10 @@ pub mod client; pub(super) mod glue; pub mod h1; +pub mod normalize_uri; +pub mod orig_proto; pub mod router; pub mod upgrade; -pub mod orig_proto; pub use self::client::{Client, Error as ClientError}; pub use self::glue::HttpBody as Body; diff --git a/src/proxy/http/normalize_uri.rs b/src/proxy/http/normalize_uri.rs new file mode 100644 index 000000000..d4e76405e --- /dev/null +++ b/src/proxy/http/normalize_uri.rs @@ -0,0 +1,52 @@ +use http; +use futures::Poll; + +use super::h1::normalize_our_view_of_uri; +use svc; + +/// Rewrites HTTP/1.x requests so that their URIs are in a canonical form. +/// +/// The following transformations are applied: +/// - If an absolute-form URI is received, it must replace +/// the host header (in accordance with RFC7230#section-5.4) +/// - If the request URI is not in absolute form, it is rewritten to contain +/// the authority given in the `Host:` header, or, failing that, from the +/// request's original destination according to `SO_ORIGINAL_DST`. +#[derive(Copy, Clone, Debug)] +pub struct Service { + inner: S, + was_absolute_form: bool, +} + +// ===== impl Service ===== + +impl Service { + pub fn new(inner: S, was_absolute_form: bool) -> Self { + Self { inner, was_absolute_form } + } +} + +impl svc::Service for Service +where + S: svc::Service>, +{ + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self) -> Poll<(), S::Error> { + self.inner.poll_ready() + } + + fn call(&mut self, mut request: S::Request) -> Self::Future { + if request.version() != http::Version::HTTP_2 && + // Skip normalizing the URI if it was received in + // absolute form. + !self.was_absolute_form + { + normalize_our_view_of_uri(&mut request); + } + self.inner.call(request) + } +}