1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-27 17:52:56 +01:00

Fix websockets connection drop if request contains content-length header #567

This commit is contained in:
Nikolay Kim 2018-11-08 20:35:47 -08:00
parent 7065c540e1
commit 61b1030882
4 changed files with 30 additions and 9 deletions

View File

@ -11,6 +11,8 @@
### Fixed ### Fixed
* Fix websockets connection drop if request contains "content-length" header #567
* Fix keep-alive timer reset * Fix keep-alive timer reset
* HttpServer now treats streaming bodies the same for HTTP/1.x protocols. #549 * HttpServer now treats streaming bodies the same for HTTP/1.x protocols. #549

View File

@ -61,8 +61,8 @@ flate2-rust = ["flate2/rust_backend"]
cell = ["actix-net/cell"] cell = ["actix-net/cell"]
[dependencies] [dependencies]
actix = "^0.7.5" actix = "0.7.6"
actix-net = "0.2.0" actix-net = "0.2.1"
askama_escape = "0.1.0" askama_escape = "0.1.0"
base64 = "0.10" base64 = "0.10"

View File

@ -43,7 +43,9 @@ impl H1Decoder {
} }
pub fn decode<H>( pub fn decode<H>(
&mut self, src: &mut BytesMut, settings: &ServiceConfig<H>, &mut self,
src: &mut BytesMut,
settings: &ServiceConfig<H>,
) -> Result<Option<Message>, DecoderError> { ) -> Result<Option<Message>, DecoderError> {
// read payload // read payload
if self.decoder.is_some() { if self.decoder.is_some() {
@ -80,7 +82,9 @@ impl H1Decoder {
} }
fn parse_message<H>( fn parse_message<H>(
&self, buf: &mut BytesMut, settings: &ServiceConfig<H>, &self,
buf: &mut BytesMut,
settings: &ServiceConfig<H>,
) -> Poll<(Request, Option<EncodingDecoder>), ParseError> { ) -> Poll<(Request, Option<EncodingDecoder>), ParseError> {
// Parse http message // Parse http message
let mut has_upgrade = false; let mut has_upgrade = false;
@ -178,6 +182,13 @@ impl H1Decoder {
} }
header::UPGRADE => { header::UPGRADE => {
has_upgrade = true; has_upgrade = true;
// check content-length, some clients (dart)
// sends "content-length: 0" with websocket upgrade
if let Ok(val) = value.to_str() {
if val == "websocket" {
content_length = None;
}
}
} }
_ => (), _ => (),
} }
@ -221,7 +232,9 @@ pub(crate) struct HeaderIndex {
impl HeaderIndex { impl HeaderIndex {
pub(crate) fn record( pub(crate) fn record(
bytes: &[u8], headers: &[httparse::Header], indices: &mut [HeaderIndex], bytes: &[u8],
headers: &[httparse::Header],
indices: &mut [HeaderIndex],
) { ) {
let bytes_ptr = bytes.as_ptr() as usize; let bytes_ptr = bytes.as_ptr() as usize;
for (header, indices) in headers.iter().zip(indices.iter_mut()) { for (header, indices) in headers.iter().zip(indices.iter_mut()) {
@ -369,7 +382,10 @@ macro_rules! byte (
impl ChunkedState { impl ChunkedState {
fn step( fn step(
&self, body: &mut BytesMut, size: &mut u64, buf: &mut Option<Bytes>, &self,
body: &mut BytesMut,
size: &mut u64,
buf: &mut Option<Bytes>,
) -> Poll<ChunkedState, io::Error> { ) -> Poll<ChunkedState, io::Error> {
use self::ChunkedState::*; use self::ChunkedState::*;
match *self { match *self {
@ -432,7 +448,8 @@ impl ChunkedState {
} }
} }
fn read_size_lf( fn read_size_lf(
rdr: &mut BytesMut, size: &mut u64, rdr: &mut BytesMut,
size: &mut u64,
) -> Poll<ChunkedState, io::Error> { ) -> Poll<ChunkedState, io::Error> {
match byte!(rdr) { match byte!(rdr) {
b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)), b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)),
@ -445,7 +462,9 @@ impl ChunkedState {
} }
fn read_body( fn read_body(
rdr: &mut BytesMut, rem: &mut u64, buf: &mut Option<Bytes>, rdr: &mut BytesMut,
rem: &mut u64,
buf: &mut Option<Bytes>,
) -> Poll<ChunkedState, io::Error> { ) -> Poll<ChunkedState, io::Error> {
trace!("Chunked read, remaining={:?}", rem); trace!("Chunked read, remaining={:?}", rem);

View File

@ -88,7 +88,7 @@ where
Ok(Async::Ready(())) Ok(Async::Ready(()))
} }
fn call(&mut self, mut req: Self::Request) -> Self::Future { fn call(&mut self, req: Self::Request) -> Self::Future {
HttpChannel::new(self.settings.clone(), req) HttpChannel::new(self.settings.clone(), req)
} }
} }