From f11b8eac2825eeb3c8b7cd0cf2d0fb9cb325f3c9 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 12 Dec 2019 13:02:31 -0800 Subject: [PATCH] fix(http1): fix response with non-chunked transfer-encoding to be close-delimited Closes #2058 --- src/proto/h1/role.rs | 17 +++++++++++++++-- src/proto/mod.rs | 12 +++++++++++- tests/client.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 1adf708103..4b93b34090 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -800,7 +800,7 @@ impl Client { Ok(Some((DecodedLength::CHUNKED, false))) } else { trace!("not chunked, read till eof"); - Ok(Some((DecodedLength::CHUNKED, false))) + Ok(Some((DecodedLength::CLOSE_DELIMITED, false))) } } else if let Some(len) = headers::content_length_parse_all(&inc.headers) { Ok(Some((DecodedLength::checked_new(len)?, false))) @@ -1441,7 +1441,7 @@ mod tests { ", ); - // transfer-encoding + // transfer-encoding: chunked assert_eq!( parse( "\ @@ -1454,6 +1454,19 @@ mod tests { DecodedLength::CHUNKED ); + // transfer-encoding not-chunked is close-delimited + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + transfer-encoding: yolo\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CLOSE_DELIMITED + ); + // transfer-encoding and content-length = chunked assert_eq!( parse( diff --git a/src/proto/mod.rs b/src/proto/mod.rs index f95b06cbfc..5e2c631be0 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -47,7 +47,7 @@ pub(crate) enum Dispatched { mod body_length { use std::fmt; - #[derive(Clone, Copy, Debug, PartialEq, Eq)] + #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) struct DecodedLength(u64); const MAX_LEN: u64 = ::std::u64::MAX - 2; @@ -92,6 +92,16 @@ mod body_length { } } + impl fmt::Debug for DecodedLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + DecodedLength::CLOSE_DELIMITED => f.write_str("CLOSE_DELIMITED"), + DecodedLength::CHUNKED => f.write_str("CHUNKED"), + DecodedLength(n) => f.debug_tuple("DecodedLength").field(&n).finish(), + } + } + } + impl fmt::Display for DecodedLength { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { diff --git a/tests/client.rs b/tests/client.rs index 03c3913beb..bdd297ea5e 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -655,6 +655,35 @@ test! { body: None, } +test! { + name: client_response_transfer_encoding_not_chunked, + + server: + expected: "\ + GET /te-not-chunked HTTP/1.1\r\n\ + host: {addr}\r\n\ + \r\n\ + ", + reply: "\ + HTTP/1.1 200 OK\r\n\ + transfer-encoding: yolo\r\n\ + \r\n\ + hallo\ + ", + + client: + request: { + method: GET, + url: "http://{addr}/te-not-chunked", + }, + response: + status: OK, + headers: { + "transfer-encoding" => "yolo", + }, + body: &b"hallo"[..], +} + test! { name: client_pipeline_responses_extra,