Skip to content

Commit bcb8ec5

Browse files
authored
fix(http1): use httparse config for Servers (#4002)
Previously, you could config the httparse config on the server `Builder`, just like you can for clients, but unlike clients, hyper forgot to _use_ that config when parsing requests. This fixes the mistake. Closes #3923
1 parent 32b76f4 commit bcb8ec5

1 file changed

Lines changed: 60 additions & 1 deletion

File tree

src/proto/h1/role.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ impl Http1Transaction for Server {
164164
trace!(bytes = buf.len(), "Request.parse");
165165
let mut req = httparse::Request::new(&mut []);
166166
let bytes = buf.as_ref();
167-
match req.parse_with_uninit_headers(bytes, &mut headers) {
167+
match ctx.h1_parser_config.parse_request_with_uninit_headers(
168+
&mut req,
169+
bytes,
170+
&mut headers,
171+
) {
168172
Ok(httparse::Status::Complete(parsed_len)) => {
169173
trace!("Request.parse Complete({})", parsed_len);
170174
len = parsed_len;
@@ -1811,6 +1815,61 @@ mod tests {
18111815
Client::parse(&mut raw, ctx).unwrap_err();
18121816
}
18131817

1818+
const REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE: &str =
1819+
"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n";
1820+
1821+
#[cfg(feature = "server")]
1822+
#[test]
1823+
fn test_parse_allow_request_with_multiple_spaces_in_request_line() {
1824+
use httparse::ParserConfig;
1825+
1826+
let _ = pretty_env_logger::try_init();
1827+
let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1828+
let mut h1_parser_config = ParserConfig::default();
1829+
h1_parser_config.allow_multiple_spaces_in_request_line_delimiters(true);
1830+
let mut method = None;
1831+
let ctx = ParseContext {
1832+
cached_headers: &mut None,
1833+
req_method: &mut method,
1834+
h1_parser_config,
1835+
h1_max_headers: None,
1836+
preserve_header_case: false,
1837+
#[cfg(feature = "ffi")]
1838+
preserve_header_order: false,
1839+
h09_responses: false,
1840+
#[cfg(feature = "client")]
1841+
on_informational: &mut None,
1842+
};
1843+
let msg = Server::parse(&mut raw, ctx).unwrap().unwrap();
1844+
assert_eq!(raw.len(), 0);
1845+
assert_eq!(msg.head.subject.0, crate::Method::GET);
1846+
assert_eq!(msg.head.subject.1, "/echo");
1847+
assert_eq!(msg.head.version, crate::Version::HTTP_11);
1848+
assert_eq!(msg.head.headers.len(), 1);
1849+
assert_eq!(msg.head.headers["Host"], "hyper.rs");
1850+
assert_eq!(method, Some(crate::Method::GET));
1851+
}
1852+
1853+
#[cfg(feature = "server")]
1854+
#[test]
1855+
fn test_parse_reject_request_with_multiple_spaces_in_request_line() {
1856+
let _ = pretty_env_logger::try_init();
1857+
let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1858+
let ctx = ParseContext {
1859+
cached_headers: &mut None,
1860+
req_method: &mut None,
1861+
h1_parser_config: Default::default(),
1862+
h1_max_headers: None,
1863+
preserve_header_case: false,
1864+
#[cfg(feature = "ffi")]
1865+
preserve_header_order: false,
1866+
h09_responses: false,
1867+
#[cfg(feature = "client")]
1868+
on_informational: &mut None,
1869+
};
1870+
Server::parse(&mut raw, ctx).unwrap_err();
1871+
}
1872+
18141873
#[cfg(feature = "server")]
18151874
#[test]
18161875
fn test_parse_preserve_header_case_in_request() {

0 commit comments

Comments
 (0)