diff --git a/examples/http_proxy.rs b/examples/http_proxy.rs index a08bdc4a29..5911a2dbe8 100644 --- a/examples/http_proxy.rs +++ b/examples/http_proxy.rs @@ -23,14 +23,21 @@ type HttpClient = Client; #[tokio::main] async fn main() { let addr = SocketAddr::from(([127, 0, 0, 1], 8100)); - let client = HttpClient::new(); + + let client = Client::builder() + .http1_title_case_headers(true) + .http1_preserve_header_case(true) + .build_http(); let make_service = make_service_fn(move |_| { let client = client.clone(); async move { Ok::<_, Infallible>(service_fn(move |req| proxy(client.clone(), req))) } }); - let server = Server::bind(&addr).serve(make_service); + let server = Server::bind(&addr) + .http1_preserve_header_case(true) + .http1_title_case_headers(true) + .serve(make_service); println!("Listening on http://{}", addr); diff --git a/src/server/conn.rs b/src/server/conn.rs index 0cef9d5e78..c1a52f1c0d 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -89,6 +89,7 @@ pub struct Http { h1_half_close: bool, h1_keep_alive: bool, h1_title_case_headers: bool, + h1_preserve_header_case: bool, #[cfg(feature = "http2")] h2_builder: proto::h2::server::Config, mode: ConnectionMode, @@ -236,6 +237,7 @@ impl Http { h1_half_close: false, h1_keep_alive: true, h1_title_case_headers: false, + h1_preserve_header_case: false, #[cfg(feature = "http2")] h2_builder: Default::default(), mode: ConnectionMode::default(), @@ -301,6 +303,19 @@ impl Http { self } + /// Set whether HTTP/1 connections will write header names as provided + /// at the socket level. + /// + /// Note that this setting does not affect HTTP/2. + /// + /// Default is false. + #[cfg(feature = "http1")] + #[cfg_attr(docsrs, doc(cfg(feature = "http1")))] + pub fn http1_preserve_header_case(&mut self, enabled: bool) -> &mut Self { + self.h1_preserve_header_case = enabled; + self + } + /// Sets whether HTTP2 is required. /// /// Default is false @@ -475,6 +490,7 @@ impl Http { h1_half_close: self.h1_half_close, h1_keep_alive: self.h1_keep_alive, h1_title_case_headers: self.h1_title_case_headers, + h1_preserve_header_case: self.h1_preserve_header_case, #[cfg(feature = "http2")] h2_builder: self.h2_builder, mode: self.mode, @@ -533,6 +549,9 @@ impl Http { if self.h1_title_case_headers { conn.set_title_case_headers(); } + if self.h1_preserve_header_case { + conn.set_preserve_header_case(); + } conn.set_flush_pipeline(self.pipeline_flush); if let Some(max) = self.max_buf_size { conn.set_max_buf_size(max); diff --git a/src/server/server.rs b/src/server/server.rs index 3fa949162c..20c993e8ac 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -244,6 +244,19 @@ impl Builder { self } + /// Set whether HTTP/1 connections will write header names as provided + /// at the socket level. + /// + /// Note that this setting does not affect HTTP/2. + /// + /// Default is false. + #[cfg(feature = "http1")] + #[cfg_attr(docsrs, doc(cfg(feature = "http1")))] + pub fn http1_preserve_header_case(mut self, val: bool) -> Self { + self.protocol.http1_preserve_header_case(val); + self + } + /// Sets whether HTTP/1 is required. /// /// Default is `false`.