mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 08:22:59 +01:00
fix chunked transfer encoding handling
This commit is contained in:
parent
d180b2a1e3
commit
842da939dc
@ -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> {
|
||||
|
@ -47,7 +47,7 @@ where
|
||||
|
||||
// Content length
|
||||
let _ = match length {
|
||||
BodyLength::Chunked | BodyLength::None => None,
|
||||
BodyLength::None => None,
|
||||
BodyLength::Stream => {
|
||||
skip_len = false;
|
||||
None
|
||||
|
@ -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 {
|
||||
|
@ -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")),
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user