1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-09-09 05:08:32 +00:00

fix chunked transfer encoding handling

This commit is contained in:
Nikolay Kim 2019-02-18 20:24:50 -08:00
parent d180b2a1e3
commit 842da939dc
6 changed files with 40 additions and 9 deletions

View file

@ -13,7 +13,6 @@ pub enum BodyLength {
Empty,
Sized(usize),
Sized64(u64),
Chunked,
Stream,
}
@ -331,7 +330,7 @@ where
E: Into<Error>,
{
fn length(&self) -> BodyLength {
BodyLength::Chunked
BodyLength::Stream
}
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {

View file

@ -47,7 +47,7 @@ where
// Content length
let _ = match length {
BodyLength::Chunked | BodyLength::None => None,
BodyLength::None => None,
BodyLength::Stream => {
skip_len = false;
None

View file

@ -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<ConnectionType> {
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<T: MessageType> MessageEncoder<T> {
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 {

View file

@ -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")),

View file

@ -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<ConnectionType>,
pub no_chunking: bool,
pub extensions: RefCell<Extensions>,
}
@ -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<ConnectionType>,
}
@ -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();
}

View file

@ -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<V>(&mut self, value: V) -> &mut Self