From 61b1030882781f93c0228b5605041a197e5eb8f5 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 8 Nov 2018 20:35:47 -0800 Subject: [PATCH] Fix websockets connection drop if request contains content-length header #567 --- CHANGES.md | 2 ++ Cargo.toml | 4 ++-- src/server/h1decoder.rs | 31 +++++++++++++++++++++++++------ src/server/service.rs | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 61723741..b1717ea9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,8 @@ ### Fixed +* Fix websockets connection drop if request contains "content-length" header #567 + * Fix keep-alive timer reset * HttpServer now treats streaming bodies the same for HTTP/1.x protocols. #549 diff --git a/Cargo.toml b/Cargo.toml index 0dcce54b..4abb64e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,8 +61,8 @@ flate2-rust = ["flate2/rust_backend"] cell = ["actix-net/cell"] [dependencies] -actix = "^0.7.5" -actix-net = "0.2.0" +actix = "0.7.6" +actix-net = "0.2.1" askama_escape = "0.1.0" base64 = "0.10" diff --git a/src/server/h1decoder.rs b/src/server/h1decoder.rs index 434dc42d..10f7e68a 100644 --- a/src/server/h1decoder.rs +++ b/src/server/h1decoder.rs @@ -43,7 +43,9 @@ impl H1Decoder { } pub fn decode( - &mut self, src: &mut BytesMut, settings: &ServiceConfig, + &mut self, + src: &mut BytesMut, + settings: &ServiceConfig, ) -> Result, DecoderError> { // read payload if self.decoder.is_some() { @@ -80,7 +82,9 @@ impl H1Decoder { } fn parse_message( - &self, buf: &mut BytesMut, settings: &ServiceConfig, + &self, + buf: &mut BytesMut, + settings: &ServiceConfig, ) -> Poll<(Request, Option), ParseError> { // Parse http message let mut has_upgrade = false; @@ -178,6 +182,13 @@ impl H1Decoder { } header::UPGRADE => { 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 { 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; for (header, indices) in headers.iter().zip(indices.iter_mut()) { @@ -369,7 +382,10 @@ macro_rules! byte ( impl ChunkedState { fn step( - &self, body: &mut BytesMut, size: &mut u64, buf: &mut Option, + &self, + body: &mut BytesMut, + size: &mut u64, + buf: &mut Option, ) -> Poll { use self::ChunkedState::*; match *self { @@ -432,7 +448,8 @@ impl ChunkedState { } } fn read_size_lf( - rdr: &mut BytesMut, size: &mut u64, + rdr: &mut BytesMut, + size: &mut u64, ) -> Poll { match byte!(rdr) { b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)), @@ -445,7 +462,9 @@ impl ChunkedState { } fn read_body( - rdr: &mut BytesMut, rem: &mut u64, buf: &mut Option, + rdr: &mut BytesMut, + rem: &mut u64, + buf: &mut Option, ) -> Poll { trace!("Chunked read, remaining={:?}", rem); diff --git a/src/server/service.rs b/src/server/service.rs index cd4b3d3f..e3402e30 100644 --- a/src/server/service.rs +++ b/src/server/service.rs @@ -88,7 +88,7 @@ where 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) } }