diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 740c8e1d56..f467af8286 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -234,6 +234,7 @@ impl Http1Transaction for Server { let mut decoder = DecodedLength::ZERO; let mut expect_continue = false; let mut con_len = None; + let mut is_cl = false; let mut is_te = false; let mut is_te_chunked = false; let mut wants_upgrade = subject.0 == Method::CONNECT; @@ -272,6 +273,9 @@ impl Http1Transaction for Server { return Err(Parse::transfer_encoding_unexpected()); } is_te = true; + if is_cl && con_len.take().is_some() { + headers.remove(header::CONTENT_LENGTH); + } if headers::is_chunked_(&value) { is_te_chunked = true; decoder = DecodedLength::CHUNKED; @@ -280,6 +284,7 @@ impl Http1Transaction for Server { } } header::CONTENT_LENGTH => { + is_cl = true; if is_te { continue; } @@ -340,6 +345,10 @@ impl Http1Transaction for Server { return Err(Parse::transfer_encoding_invalid()); } + if is_te && is_cl { + keep_alive = false; + } + let mut extensions = http::Extensions::default(); if let Some(header_case_map) = header_case_map { @@ -2048,45 +2057,55 @@ mod tests { ); // transfer-encoding and content-length = chunked - assert_eq!( - parse( - "\ - POST / HTTP/1.1\r\n\ - content-length: 10\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - " - ) - .decode, - DecodedLength::CHUNKED + let msg = parse( + "\ + POST / HTTP/1.1\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + ", ); + assert_eq!(msg.decode, DecodedLength::CHUNKED); + assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH)); + assert!(!msg.keep_alive); - assert_eq!( - parse( - "\ - POST / HTTP/1.1\r\n\ - transfer-encoding: chunked\r\n\ - content-length: 10\r\n\ - \r\n\ - " - ) - .decode, - DecodedLength::CHUNKED + let msg = parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: chunked\r\n\ + content-length: 10\r\n\ + \r\n\ + ", ); + assert_eq!(msg.decode, DecodedLength::CHUNKED); + assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH)); + assert!(!msg.keep_alive); - assert_eq!( - parse( - "\ - POST / HTTP/1.1\r\n\ - transfer-encoding: gzip\r\n\ - content-length: 10\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - " - ) - .decode, - DecodedLength::CHUNKED + let msg = parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: gzip\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + ", + ); + assert_eq!(msg.decode, DecodedLength::CHUNKED); + assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH)); + assert!(!msg.keep_alive); + + let msg = parse( + "\ + POST / HTTP/1.1\r\n\ + connection: keep-alive\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + ", ); + assert_eq!(msg.decode, DecodedLength::CHUNKED); + assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH)); + assert!(!msg.keep_alive); // multiple content-lengths of same value are fine assert_eq!(