feat(client): add option to allow misplaced spaces in HTTP/1 responses (#2506)
This commit is contained in:
		| @@ -961,6 +961,31 @@ impl Builder { | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     /// Set whether HTTP/1 connections will accept spaces between header names | ||||
|     /// and the colon that follow them in responses. | ||||
|     /// | ||||
|     /// You probably don't need this, here is what [RFC 7230 Section 3.2.4.] has | ||||
|     /// to say about it: | ||||
|     /// | ||||
|     /// > No whitespace is allowed between the header field-name and colon. In | ||||
|     /// > the past, differences in the handling of such whitespace have led to | ||||
|     /// > security vulnerabilities in request routing and response handling. A | ||||
|     /// > server MUST reject any received request message that contains | ||||
|     /// > whitespace between a header field-name and colon with a response code | ||||
|     /// > of 400 (Bad Request). A proxy MUST remove any such whitespace from a | ||||
|     /// > response message before forwarding the message downstream. | ||||
|     /// | ||||
|     /// Note that this setting does not affect HTTP/2. | ||||
|     /// | ||||
|     /// Default is false. | ||||
|     /// | ||||
|     /// [RFC 7230 Section 3.2.4.]: https://tools.ietf.org/html/rfc7230#section-3.2.4 | ||||
|     pub fn http1_allow_spaces_after_header_name_in_responses(&mut self, val: bool) -> &mut Self { | ||||
|         self.conn_builder | ||||
|             .h1_allow_spaces_after_header_name_in_responses(val); | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     /// Set whether HTTP/1 connections will write header names as title case at | ||||
|     /// the socket level. | ||||
|     /// | ||||
|   | ||||
| @@ -56,6 +56,7 @@ use std::time::Duration; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use futures_util::future::{self, Either, FutureExt as _}; | ||||
| use httparse::ParserConfig; | ||||
| use pin_project::pin_project; | ||||
| use tokio::io::{AsyncRead, AsyncWrite}; | ||||
| use tower_service::Service; | ||||
| @@ -123,6 +124,7 @@ where | ||||
| pub struct Builder { | ||||
|     pub(super) exec: Exec, | ||||
|     h09_responses: bool, | ||||
|     h1_parser_config: ParserConfig, | ||||
|     h1_title_case_headers: bool, | ||||
|     h1_read_buf_exact_size: Option<usize>, | ||||
|     h1_max_buf_size: Option<usize>, | ||||
| @@ -496,6 +498,7 @@ impl Builder { | ||||
|             exec: Exec::Default, | ||||
|             h09_responses: false, | ||||
|             h1_read_buf_exact_size: None, | ||||
|             h1_parser_config: Default::default(), | ||||
|             h1_title_case_headers: false, | ||||
|             h1_max_buf_size: None, | ||||
|             #[cfg(feature = "http2")] | ||||
| @@ -521,6 +524,14 @@ impl Builder { | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn h1_allow_spaces_after_header_name_in_responses( | ||||
|         &mut self, | ||||
|         enabled: bool, | ||||
|     ) -> &mut Builder { | ||||
|         self.h1_parser_config.allow_spaces_after_header_name_in_responses(enabled); | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     pub(super) fn h1_title_case_headers(&mut self, enabled: bool) -> &mut Builder { | ||||
|         self.h1_title_case_headers = enabled; | ||||
|         self | ||||
| @@ -704,6 +715,7 @@ impl Builder { | ||||
|                 #[cfg(feature = "http1")] | ||||
|                 Proto::Http1 => { | ||||
|                     let mut conn = proto::Conn::new(io); | ||||
|                     conn.set_h1_parser_config(opts.h1_parser_config); | ||||
|                     if opts.h1_title_case_headers { | ||||
|                         conn.set_title_case_headers(); | ||||
|                     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user