From 570da500c028d81ff9154d0ebb26b92fef0973c0 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 20 Aug 2023 12:04:24 +0200 Subject: [PATCH] [feature] Allow http(s) scheme in the WebSocket constructor Refs: https://github.com/whatwg/websockets/pull/45 --- lib/websocket.js | 9 +++++++-- test/websocket.test.js | 44 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/websocket.js b/lib/websocket.js index b2b2b0926..65db78c69 100644 --- a/lib/websocket.js +++ b/lib/websocket.js @@ -667,17 +667,22 @@ function initAsClient(websocket, address, protocols, options) { if (address instanceof URL) { parsedUrl = address; - websocket._url = address.href; } else { try { parsedUrl = new URL(address); } catch (e) { throw new SyntaxError(`Invalid URL: ${address}`); } + } - websocket._url = address; + if (parsedUrl.protocol === 'http:') { + parsedUrl.protocol = 'ws:'; + } else if (parsedUrl.protocol === 'https:') { + parsedUrl.protocol = 'wss:'; } + websocket._url = parsedUrl.href; + const isSecure = parsedUrl.protocol === 'wss:'; const isIpcUrl = parsedUrl.protocol === 'ws+unix:'; let invalidUrlMessage; diff --git a/test/websocket.test.js b/test/websocket.test.js index 7b3978428..5fc0a8d78 100644 --- a/test/websocket.test.js +++ b/test/websocket.test.js @@ -36,7 +36,7 @@ describe('WebSocket', () => { ); assert.throws( - () => new WebSocket('https://websocket-echo.com'), + () => new WebSocket('http+ws://websocket-echo.com'), /^SyntaxError: The URL's protocol must be one of "ws:", "wss:", or "ws\+unix:"$/ ); @@ -72,6 +72,30 @@ describe('WebSocket', () => { const ws = new WebSocket(new URL('ws://[::1]'), { agent }); }); + it('allows the http scheme', (done) => { + const agent = new CustomAgent(); + + agent.addRequest = (req, opts) => { + assert.strictEqual(opts.host, 'localhost'); + assert.strictEqual(opts.port, 80); + done(); + }; + + const ws = new WebSocket('http://localhost', { agent }); + }); + + it('allows the https scheme', (done) => { + const agent = new https.Agent(); + + agent.addRequest = (req, opts) => { + assert.strictEqual(opts.host, 'localhost'); + assert.strictEqual(opts.port, 443); + done(); + }; + + const ws = new WebSocket('https://localhost', { agent }); + }); + describe('options', () => { it('accepts the `options` object as 3rd argument', () => { const agent = new http.Agent(); @@ -539,10 +563,18 @@ describe('WebSocket', () => { }); it('exposes the server url', () => { - const url = 'ws://localhost'; - const ws = new WebSocket(url, { agent: new CustomAgent() }); + const schemes = new Map([ + ['ws', 'ws'], + ['wss', 'wss'], + ['http', 'ws'], + ['https', 'wss'] + ]); - assert.strictEqual(ws.url, url); + for (const [key, value] of schemes) { + const ws = new WebSocket(`${key}://localhost/`, { lookup() {} }); + + assert.strictEqual(ws.url, `${value}://localhost/`); + } }); }); }); @@ -1174,7 +1206,9 @@ describe('WebSocket', () => { it('emits an error if the redirect URL is invalid (2/2)', (done) => { server.once('upgrade', (req, socket) => { - socket.end('HTTP/1.1 302 Found\r\nLocation: http://localhost\r\n\r\n'); + socket.end( + 'HTTP/1.1 302 Found\r\nLocation: http+ws://localhost\r\n\r\n' + ); }); const ws = new WebSocket(`ws://localhost:${server.address().port}`, {