diff --git a/src/body.rs b/src/body.rs index d3e63f9c..1f218c4b 100644 --- a/src/body.rs +++ b/src/body.rs @@ -13,7 +13,6 @@ pub enum BodyLength { Empty, Sized(usize), Sized64(u64), - Chunked, Stream, } @@ -331,7 +330,7 @@ where E: Into, { fn length(&self) -> BodyLength { - BodyLength::Chunked + BodyLength::Stream } fn poll_next(&mut self) -> Poll, Error> { diff --git a/src/client/h2proto.rs b/src/client/h2proto.rs index 8804d13f..617c21b6 100644 --- a/src/client/h2proto.rs +++ b/src/client/h2proto.rs @@ -47,7 +47,7 @@ where // Content length let _ = match length { - BodyLength::Chunked | BodyLength::None => None, + BodyLength::None => None, BodyLength::Stream => { skip_len = false; None diff --git a/src/h1/encoder.rs b/src/h1/encoder.rs index 32c8f9c4..7627f697 100644 --- a/src/h1/encoder.rs +++ b/src/h1/encoder.rs @@ -45,6 +45,8 @@ pub(crate) trait MessageType: Sized { fn headers(&self) -> &HeaderMap; + fn chunked(&self) -> bool; + fn encode_status(&mut self, dst: &mut BytesMut) -> io::Result<()>; fn encode_headers( @@ -71,8 +73,10 @@ pub(crate) trait MessageType: Sized { } } match length { - BodyLength::Chunked => { - dst.extend_from_slice(b"\r\ntransfer-encoding: chunked\r\n") + BodyLength::Stream => { + if self.chunked() { + dst.extend_from_slice(b"\r\ntransfer-encoding: chunked\r\n") + } } BodyLength::Empty => { dst.extend_from_slice(b"\r\ncontent-length: 0\r\n"); @@ -83,7 +87,7 @@ pub(crate) trait MessageType: Sized { write!(dst.writer(), "{}", len)?; dst.extend_from_slice(b"\r\n"); } - BodyLength::None | BodyLength::Stream => dst.extend_from_slice(b"\r\n"), + BodyLength::None => dst.extend_from_slice(b"\r\n"), } // Connection @@ -159,6 +163,10 @@ impl MessageType for Response<()> { Some(self.head().status) } + fn chunked(&self) -> bool { + !self.head().no_chunking + } + fn connection_type(&self) -> Option { self.head().ctype } @@ -188,6 +196,10 @@ impl MessageType for RequestHead { self.ctype } + fn chunked(&self) -> bool { + !self.no_chunking + } + fn headers(&self) -> &HeaderMap { &self.headers } @@ -236,8 +248,13 @@ impl MessageEncoder { BodyLength::Empty => TransferEncoding::empty(), BodyLength::Sized(len) => TransferEncoding::length(len as u64), BodyLength::Sized64(len) => TransferEncoding::length(len), - BodyLength::Chunked => TransferEncoding::chunked(), - BodyLength::Stream => TransferEncoding::eof(), + BodyLength::Stream => { + if message.chunked() { + TransferEncoding::chunked() + } else { + TransferEncoding::eof() + } + } BodyLength::None => TransferEncoding::empty(), }; } else { diff --git a/src/h2/dispatcher.rs b/src/h2/dispatcher.rs index 5a8c4b85..ea8756d2 100644 --- a/src/h2/dispatcher.rs +++ b/src/h2/dispatcher.rs @@ -181,7 +181,7 @@ where _ => (), } let _ = match length { - BodyLength::Chunked | BodyLength::None | BodyLength::Stream => None, + BodyLength::None | BodyLength::Stream => None, BodyLength::Empty => res .headers_mut() .insert(CONTENT_LENGTH, HeaderValue::from_static("0")), diff --git a/src/message.rs b/src/message.rs index 812f099e..3a1ac130 100644 --- a/src/message.rs +++ b/src/message.rs @@ -36,6 +36,7 @@ pub trait Head: Default + 'static { self.connection_type() == ConnectionType::Upgrade } + /// Check if keep-alive is enabled fn keep_alive(&self) -> bool { self.connection_type() == ConnectionType::KeepAlive } @@ -50,6 +51,7 @@ pub struct RequestHead { pub version: Version, pub headers: HeaderMap, pub ctype: Option, + pub no_chunking: bool, pub extensions: RefCell, } @@ -61,6 +63,7 @@ impl Default for RequestHead { version: Version::HTTP_11, headers: HeaderMap::with_capacity(16), ctype: None, + no_chunking: false, extensions: RefCell::new(Extensions::new()), } } @@ -120,6 +123,7 @@ pub struct ResponseHead { pub status: StatusCode, pub headers: HeaderMap, pub reason: Option<&'static str>, + pub no_chunking: bool, pub(crate) ctype: Option, } @@ -130,6 +134,7 @@ impl Default for ResponseHead { status: StatusCode::OK, headers: HeaderMap::with_capacity(16), reason: None, + no_chunking: false, ctype: None, } } @@ -139,6 +144,7 @@ impl Head for ResponseHead { fn clear(&mut self) { self.ctype = None; self.reason = None; + self.no_chunking = false; self.headers.clear(); } diff --git a/src/response.rs b/src/response.rs index 0295758b..2c627d53 100644 --- a/src/response.rs +++ b/src/response.rs @@ -459,6 +459,15 @@ impl ResponseBuilder { self } + /// Disable chunked transfer encoding for HTTP/1.1 streaming responses. + #[inline] + pub fn no_chunking(&mut self) -> &mut Self { + if let Some(parts) = parts(&mut self.head, &self.err) { + parts.no_chunking = true; + } + self + } + /// Set response content type #[inline] pub fn content_type(&mut self, value: V) -> &mut Self