From 0c9d6cbb2adc4a0903b18e3c290e9b2c8c8b4e91 Mon Sep 17 00:00:00 2001 From: Leo K Date: Fri, 13 Aug 2021 20:52:13 +0200 Subject: [PATCH] fix(http/ws): support multiple options in connection header (#11675) Co-authored-by: Luca Casonato --- cli/tests/integration/mod.rs | 35 +++++++++++++++++++ ...rver_multi_field_connection_header_test.ts | 17 +++++++++ ext/http/lib.rs | 22 +++++++----- 3 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 cli/tests/testdata/websocket_server_multi_field_connection_header_test.ts diff --git a/cli/tests/integration/mod.rs b/cli/tests/integration/mod.rs index 8448e77e18..7d13c78316 100644 --- a/cli/tests/integration/mod.rs +++ b/cli/tests/integration/mod.rs @@ -684,6 +684,41 @@ fn websocketstream() { assert!(status.success()); } +#[test] +fn websocket_server_multi_field_connection_header() { + let script = util::testdata_path() + .join("websocket_server_multi_field_connection_header_test.ts"); + let root_ca = util::testdata_path().join("tls/RootCA.pem"); + let mut child = util::deno_cmd() + .arg("run") + .arg("--unstable") + .arg("--allow-net") + .arg("--cert") + .arg(root_ca) + .arg(script) + .stdout(std::process::Stdio::piped()) + .spawn() + .unwrap(); + + let stdout = child.stdout.as_mut().unwrap(); + let mut buffer = [0; 5]; + let read = stdout.read(&mut buffer).unwrap(); + assert_eq!(read, 5); + let msg = std::str::from_utf8(&buffer).unwrap(); + assert_eq!(msg, "READY"); + + let req = http::request::Builder::new() + .header(http::header::CONNECTION, "keep-alive, Upgrade") + .uri("ws://localhost:4319") + .body(()) + .unwrap(); + assert!( + deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::connect(req) + .is_ok() + ); + assert!(child.wait().unwrap().success()); +} + #[cfg(not(windows))] #[test] fn set_raw_should_not_panic_on_no_tty() { diff --git a/cli/tests/testdata/websocket_server_multi_field_connection_header_test.ts b/cli/tests/testdata/websocket_server_multi_field_connection_header_test.ts new file mode 100644 index 0000000000..a662ce9ef1 --- /dev/null +++ b/cli/tests/testdata/websocket_server_multi_field_connection_header_test.ts @@ -0,0 +1,17 @@ +import { deferred } from "../unit/test_util.ts"; + +const promise = deferred(); +const listener = Deno.listen({ port: 4319 }); +console.log("READY"); +const conn = await listener.accept(); +const httpConn = Deno.serveHttp(conn); +const { request, respondWith } = (await httpConn.nextRequest())!; +const { + response, + socket, +} = Deno.upgradeWebSocket(request); +socket.onerror = () => Deno.exit(1); +socket.onopen = () => socket.close(); +socket.onclose = () => promise.resolve(); +await respondWith(response); +await promise; diff --git a/ext/http/lib.rs b/ext/http/lib.rs index db55ca53d3..38c14409cb 100644 --- a/ext/http/lib.rs +++ b/ext/http/lib.rs @@ -268,18 +268,22 @@ async fn op_http_request_next( let is_websocket_request = req .headers() - .get(hyper::header::CONNECTION) - .and_then(|v| { - v.to_str().ok().map(|s| "Upgrade".eq_ignore_ascii_case(s)) + .get_all(hyper::header::CONNECTION) + .iter() + .any(|v| { + v.to_str() + .map(|s| s.to_lowercase().contains("upgrade")) + .unwrap_or(false) }) - .unwrap_or(false) && req .headers() - .get(hyper::header::UPGRADE) - .and_then(|v| { - v.to_str().ok().map(|s| "websocket".eq_ignore_ascii_case(s)) - }) - .unwrap_or(false); + .get_all(hyper::header::UPGRADE) + .iter() + .any(|v| { + v.to_str() + .map(|s| s.to_lowercase().contains("websocket")) + .unwrap_or(false) + }); let has_body = if let Some(exact_size) = req.size_hint().exact() { exact_size > 0