diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index f9a44d8ef0..c8ec0d594b 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -693,6 +693,18 @@ unitTest(function httpUpgradeWebSocketLowercaseUpgradeHeader() { assertEquals(response.status, 101); }); +unitTest(function httpUpgradeWebSocketMultipleConnectionOptions() { + const request = new Request("https://deno.land/", { + headers: { + connection: "keep-alive, upgrade", + upgrade: "websocket", + "sec-websocket-key": "dGhlIHNhbXBsZSBub25jZQ==", + }, + }); + const { response } = Deno.upgradeWebSocket(request); + assertEquals(response.status, 101); +}); + unitTest({ perms: { net: true } }, async function httpCookieConcatenation() { const promise = (async () => { const listener = Deno.listen({ port: 4501 }); diff --git a/extensions/http/01_http.js b/extensions/http/01_http.js index e0f221ce0a..2b0d8cd2c6 100644 --- a/extensions/http/01_http.js +++ b/extensions/http/01_http.js @@ -22,8 +22,10 @@ const { ArrayPrototypeIncludes, ArrayPrototypePush, + ArrayPrototypeSome, Promise, StringPrototypeIncludes, + StringPrototypeToLowerCase, StringPrototypeSplit, Symbol, SymbolAsyncIterator, @@ -321,7 +323,13 @@ ); } - if (request.headers.get("connection")?.toLowerCase() !== "upgrade") { + const connection = request.headers.get("connection"); + const connectionHasUpgradeOption = connection !== null && + ArrayPrototypeSome( + StringPrototypeSplit(connection, /\s*,\s*/), + (option) => StringPrototypeToLowerCase(option) === "upgrade", + ); + if (!connectionHasUpgradeOption) { throw new TypeError( "Invalid Header: 'connection' header must be 'Upgrade'", );