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,
|
Empty,
|
||||||
Sized(usize),
|
Sized(usize),
|
||||||
Sized64(u64),
|
Sized64(u64),
|
||||||
Chunked,
|
|
||||||
Stream,
|
Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +330,7 @@ where
|
|||||||
E: Into<Error>,
|
E: Into<Error>,
|
||||||
{
|
{
|
||||||
fn length(&self) -> BodyLength {
|
fn length(&self) -> BodyLength {
|
||||||
BodyLength::Chunked
|
BodyLength::Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
||||||
|
@ -47,7 +47,7 @@ where
|
|||||||
|
|
||||||
// Content length
|
// Content length
|
||||||
let _ = match length {
|
let _ = match length {
|
||||||
BodyLength::Chunked | BodyLength::None => None,
|
BodyLength::None => None,
|
||||||
BodyLength::Stream => {
|
BodyLength::Stream => {
|
||||||
skip_len = false;
|
skip_len = false;
|
||||||
None
|
None
|
||||||
|
@ -45,6 +45,8 @@ pub(crate) trait MessageType: Sized {
|
|||||||
|
|
||||||
fn headers(&self) -> &HeaderMap;
|
fn headers(&self) -> &HeaderMap;
|
||||||
|
|
||||||
|
fn chunked(&self) -> bool;
|
||||||
|
|
||||||
fn encode_status(&mut self, dst: &mut BytesMut) -> io::Result<()>;
|
fn encode_status(&mut self, dst: &mut BytesMut) -> io::Result<()>;
|
||||||
|
|
||||||
fn encode_headers(
|
fn encode_headers(
|
||||||
@ -71,8 +73,10 @@ pub(crate) trait MessageType: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match length {
|
match length {
|
||||||
BodyLength::Chunked => {
|
BodyLength::Stream => {
|
||||||
dst.extend_from_slice(b"\r\ntransfer-encoding: chunked\r\n")
|
if self.chunked() {
|
||||||
|
dst.extend_from_slice(b"\r\ntransfer-encoding: chunked\r\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BodyLength::Empty => {
|
BodyLength::Empty => {
|
||||||
dst.extend_from_slice(b"\r\ncontent-length: 0\r\n");
|
dst.extend_from_slice(b"\r\ncontent-length: 0\r\n");
|
||||||
@ -83,7 +87,7 @@ pub(crate) trait MessageType: Sized {
|
|||||||
write!(dst.writer(), "{}", len)?;
|
write!(dst.writer(), "{}", len)?;
|
||||||
dst.extend_from_slice(b"\r\n");
|
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
|
// Connection
|
||||||
@ -159,6 +163,10 @@ impl MessageType for Response<()> {
|
|||||||
Some(self.head().status)
|
Some(self.head().status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chunked(&self) -> bool {
|
||||||
|
!self.head().no_chunking
|
||||||
|
}
|
||||||
|
|
||||||
fn connection_type(&self) -> Option<ConnectionType> {
|
fn connection_type(&self) -> Option<ConnectionType> {
|
||||||
self.head().ctype
|
self.head().ctype
|
||||||
}
|
}
|
||||||
@ -188,6 +196,10 @@ impl MessageType for RequestHead {
|
|||||||
self.ctype
|
self.ctype
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chunked(&self) -> bool {
|
||||||
|
!self.no_chunking
|
||||||
|
}
|
||||||
|
|
||||||
fn headers(&self) -> &HeaderMap {
|
fn headers(&self) -> &HeaderMap {
|
||||||
&self.headers
|
&self.headers
|
||||||
}
|
}
|
||||||
@ -236,8 +248,13 @@ impl<T: MessageType> MessageEncoder<T> {
|
|||||||
BodyLength::Empty => TransferEncoding::empty(),
|
BodyLength::Empty => TransferEncoding::empty(),
|
||||||
BodyLength::Sized(len) => TransferEncoding::length(len as u64),
|
BodyLength::Sized(len) => TransferEncoding::length(len as u64),
|
||||||
BodyLength::Sized64(len) => TransferEncoding::length(len),
|
BodyLength::Sized64(len) => TransferEncoding::length(len),
|
||||||
BodyLength::Chunked => TransferEncoding::chunked(),
|
BodyLength::Stream => {
|
||||||
BodyLength::Stream => TransferEncoding::eof(),
|
if message.chunked() {
|
||||||
|
TransferEncoding::chunked()
|
||||||
|
} else {
|
||||||
|
TransferEncoding::eof()
|
||||||
|
}
|
||||||
|
}
|
||||||
BodyLength::None => TransferEncoding::empty(),
|
BodyLength::None => TransferEncoding::empty(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,7 +181,7 @@ where
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
let _ = match length {
|
let _ = match length {
|
||||||
BodyLength::Chunked | BodyLength::None | BodyLength::Stream => None,
|
BodyLength::None | BodyLength::Stream => None,
|
||||||
BodyLength::Empty => res
|
BodyLength::Empty => res
|
||||||
.headers_mut()
|
.headers_mut()
|
||||||
.insert(CONTENT_LENGTH, HeaderValue::from_static("0")),
|
.insert(CONTENT_LENGTH, HeaderValue::from_static("0")),
|
||||||
|
@ -36,6 +36,7 @@ pub trait Head: Default + 'static {
|
|||||||
self.connection_type() == ConnectionType::Upgrade
|
self.connection_type() == ConnectionType::Upgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if keep-alive is enabled
|
||||||
fn keep_alive(&self) -> bool {
|
fn keep_alive(&self) -> bool {
|
||||||
self.connection_type() == ConnectionType::KeepAlive
|
self.connection_type() == ConnectionType::KeepAlive
|
||||||
}
|
}
|
||||||
@ -50,6 +51,7 @@ pub struct RequestHead {
|
|||||||
pub version: Version,
|
pub version: Version,
|
||||||
pub headers: HeaderMap,
|
pub headers: HeaderMap,
|
||||||
pub ctype: Option<ConnectionType>,
|
pub ctype: Option<ConnectionType>,
|
||||||
|
pub no_chunking: bool,
|
||||||
pub extensions: RefCell<Extensions>,
|
pub extensions: RefCell<Extensions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ impl Default for RequestHead {
|
|||||||
version: Version::HTTP_11,
|
version: Version::HTTP_11,
|
||||||
headers: HeaderMap::with_capacity(16),
|
headers: HeaderMap::with_capacity(16),
|
||||||
ctype: None,
|
ctype: None,
|
||||||
|
no_chunking: false,
|
||||||
extensions: RefCell::new(Extensions::new()),
|
extensions: RefCell::new(Extensions::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +123,7 @@ pub struct ResponseHead {
|
|||||||
pub status: StatusCode,
|
pub status: StatusCode,
|
||||||
pub headers: HeaderMap,
|
pub headers: HeaderMap,
|
||||||
pub reason: Option<&'static str>,
|
pub reason: Option<&'static str>,
|
||||||
|
pub no_chunking: bool,
|
||||||
pub(crate) ctype: Option<ConnectionType>,
|
pub(crate) ctype: Option<ConnectionType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +134,7 @@ impl Default for ResponseHead {
|
|||||||
status: StatusCode::OK,
|
status: StatusCode::OK,
|
||||||
headers: HeaderMap::with_capacity(16),
|
headers: HeaderMap::with_capacity(16),
|
||||||
reason: None,
|
reason: None,
|
||||||
|
no_chunking: false,
|
||||||
ctype: None,
|
ctype: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,6 +144,7 @@ impl Head for ResponseHead {
|
|||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.ctype = None;
|
self.ctype = None;
|
||||||
self.reason = None;
|
self.reason = None;
|
||||||
|
self.no_chunking = false;
|
||||||
self.headers.clear();
|
self.headers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +459,15 @@ impl ResponseBuilder {
|
|||||||
self
|
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
|
/// Set response content type
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn content_type<V>(&mut self, value: V) -> &mut Self
|
pub fn content_type<V>(&mut self, value: V) -> &mut Self
|
||||||
|
Loading…
Reference in New Issue
Block a user