From 5468c3c410e408b21e4cfbd4034b72935b24cdcf Mon Sep 17 00:00:00 2001 From: Sebastian Mayr Date: Mon, 2 Nov 2020 03:44:14 -0500 Subject: [PATCH] Drop content length headers from 101 responses (#1767) Co-authored-by: Sebastian Mayr --- actix-http/CHANGES.md | 4 ++++ actix-http/src/h1/encoder.rs | 39 ++++++++++++++++++++++++++++++------ actix-web-actors/src/ws.rs | 9 ++++----- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index bb5a962f5..edb1409b2 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,10 @@ # Changes ## Unreleased - 2020-xx-xx +### Fixed +* Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767] + +[#1767]: https://github.com/actix/actix-web/pull/1767 ## 2.1.0 - 2020-10-30 diff --git a/actix-http/src/h1/encoder.rs b/actix-http/src/h1/encoder.rs index e16b4c3dc..b7648eff1 100644 --- a/actix-http/src/h1/encoder.rs +++ b/actix-http/src/h1/encoder.rs @@ -64,14 +64,17 @@ pub(crate) trait MessageType: Sized { // Content length if let Some(status) = self.status() { match status { - StatusCode::NO_CONTENT - | StatusCode::CONTINUE - | StatusCode::PROCESSING => length = BodySize::None, - StatusCode::SWITCHING_PROTOCOLS => { + StatusCode::CONTINUE + | StatusCode::SWITCHING_PROTOCOLS + | StatusCode::PROCESSING + | StatusCode::NO_CONTENT => { + // skip content-length and transfer-encoding headers + // See https://tools.ietf.org/html/rfc7230#section-3.3.1 + // and https://tools.ietf.org/html/rfc7230#section-3.3.2 skip_len = true; - length = BodySize::Stream; + length = BodySize::None } - _ => (), + _ => {} } } match length { @@ -676,4 +679,28 @@ mod tests { assert!(data.contains("authorization: another authorization\r\n")); assert!(data.contains("date: date\r\n")); } + + #[test] + fn test_no_content_length() { + let mut bytes = BytesMut::with_capacity(2048); + + let mut res: Response<()> = + Response::new(StatusCode::SWITCHING_PROTOCOLS).into_body::<()>(); + res.headers_mut() + .insert(DATE, HeaderValue::from_static(&"")); + res.headers_mut() + .insert(CONTENT_LENGTH, HeaderValue::from_static(&"0")); + + let _ = res.encode_headers( + &mut bytes, + Version::HTTP_11, + BodySize::Stream, + ConnectionType::Upgrade, + &ServiceConfig::default(), + ); + let data = + String::from_utf8(Vec::from(bytes.split().freeze().as_ref())).unwrap(); + assert!(!data.contains("content-length: 0\r\n")); + assert!(!data.contains("transfer-encoding: chunked\r\n")); + } } diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 3f5972532..8fd03f6a1 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -164,7 +164,6 @@ pub fn handshake_with_protocols( let mut response = HttpResponse::build(StatusCode::SWITCHING_PROTOCOLS) .upgrade("websocket") - .header(header::TRANSFER_ENCODING, "chunked") .header(header::SEC_WEBSOCKET_ACCEPT, key.as_str()) .take(); @@ -664,10 +663,10 @@ mod tests { ) .to_http_request(); - assert_eq!( - StatusCode::SWITCHING_PROTOCOLS, - handshake(&req).unwrap().finish().status() - ); + let resp = handshake(&req).unwrap().finish(); + assert_eq!(StatusCode::SWITCHING_PROTOCOLS, resp.status()); + assert_eq!(None, resp.headers().get(&header::CONTENT_LENGTH)); + assert_eq!(None, resp.headers().get(&header::TRANSFER_ENCODING)); let req = TestRequest::default() .header(