From 1a940d4c18d7ab234800857817f087c9121272b1 Mon Sep 17 00:00:00 2001 From: Douman Date: Sun, 16 Dec 2018 13:46:11 +0300 Subject: [PATCH] H1 decoded should ignore header cases --- CHANGES.md | 6 ++++++ src/server/h1.rs | 33 +++++++++++++++++++++++++++++++++ src/server/h1decoder.rs | 18 +++++++----------- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7965bc75..45faf35b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [0.7.17] - 2018-xx-xx + +### Fixed + +* HTTP1 decoder should perform case-insentive comparison for client requests (e.g. `Keep-Alive`). #631 + ## [0.7.16] - 2018-12-11 ### Added diff --git a/src/server/h1.rs b/src/server/h1.rs index f491ba59..f0edefae 100644 --- a/src/server/h1.rs +++ b/src/server/h1.rs @@ -942,6 +942,14 @@ mod tests { let req = parse_ready!(&mut buf); assert!(!req.keep_alive()); + + let mut buf = BytesMut::from( + "GET /test HTTP/1.1\r\n\ + connection: Close\r\n\r\n", + ); + let req = parse_ready!(&mut buf); + + assert!(!req.keep_alive()); } #[test] @@ -953,10 +961,26 @@ mod tests { let req = parse_ready!(&mut buf); assert!(!req.keep_alive()); + + let mut buf = BytesMut::from( + "GET /test HTTP/1.0\r\n\ + connection: Close\r\n\r\n", + ); + let req = parse_ready!(&mut buf); + + assert!(!req.keep_alive()); } #[test] fn test_conn_keep_alive_1_0() { + let mut buf = BytesMut::from( + "GET /test HTTP/1.0\r\n\ + connection: Keep-Alive\r\n\r\n", + ); + let req = parse_ready!(&mut buf); + + assert!(req.keep_alive()); + let mut buf = BytesMut::from( "GET /test HTTP/1.0\r\n\ connection: keep-alive\r\n\r\n", @@ -1009,6 +1033,15 @@ mod tests { let req = parse_ready!(&mut buf); assert!(req.upgrade()); + + let mut buf = BytesMut::from( + "GET /test HTTP/1.1\r\n\ + upgrade: Websockets\r\n\ + connection: Upgrade\r\n\r\n", + ); + let req = parse_ready!(&mut buf); + + assert!(req.upgrade()); } #[test] diff --git a/src/server/h1decoder.rs b/src/server/h1decoder.rs index 10f7e68a..80b49983 100644 --- a/src/server/h1decoder.rs +++ b/src/server/h1decoder.rs @@ -157,23 +157,19 @@ impl H1Decoder { } // transfer-encoding header::TRANSFER_ENCODING => { - if let Ok(s) = value.to_str() { - chunked = s.to_lowercase().contains("chunked"); + if let Ok(s) = value.to_str().map(|s| s.trim()) { + chunked = s.eq_ignore_ascii_case("chunked"); } else { return Err(ParseError::Header); } } // connection keep-alive state header::CONNECTION => { - let ka = if let Ok(conn) = value.to_str() { - if version == Version::HTTP_10 - && conn.contains("keep-alive") - { + let ka = if let Ok(conn) = value.to_str().map(|conn| conn.trim()) { + if version == Version::HTTP_10 && conn.eq_ignore_ascii_case("keep-alive") { true } else { - version == Version::HTTP_11 && !(conn - .contains("close") - || conn.contains("upgrade")) + version == Version::HTTP_11 && !(conn.eq_ignore_ascii_case("close") || conn.eq_ignore_ascii_case("upgrade")) } } else { false @@ -184,8 +180,8 @@ impl H1Decoder { 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" { + if let Ok(val) = value.to_str().map(|val| val.trim()) { + if val.eq_ignore_ascii_case("websocket") { content_length = None; } }