diff --git a/lib/websocket.js b/lib/websocket.js index 400a610d1..0915fa4c3 100644 --- a/lib/websocket.js +++ b/lib/websocket.js @@ -613,18 +613,32 @@ function initAsClient(websocket, address, protocols, options) { parsedUrl = address; websocket._url = address.href; } else { - parsedUrl = new URL(address); + try { + parsedUrl = new URL(address); + } catch (e) { + throw new SyntaxError(`Invalid URL: ${address}`); + } + websocket._url = address; } + const isSecure = parsedUrl.protocol === 'wss:'; const isUnixSocket = parsedUrl.protocol === 'ws+unix:'; - if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) { - throw new Error(`Invalid URL: ${websocket.url}`); + if (parsedUrl.protocol !== 'ws:' && !isSecure && !isUnixSocket) { + throw new SyntaxError( + 'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"' + ); + } + + if (isUnixSocket && !parsedUrl.pathname) { + throw new SyntaxError("The URL's pathname is empty"); + } + + if (parsedUrl.hash) { + throw new SyntaxError('The URL contains a fragment identifier'); } - const isSecure = - parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:'; const defaultPort = isSecure ? 443 : 80; const key = randomBytes(16).toString('base64'); const get = isSecure ? https.get : http.get; diff --git a/test/websocket.test.js b/test/websocket.test.js index 3301902f3..5c4058e8d 100644 --- a/test/websocket.test.js +++ b/test/websocket.test.js @@ -20,9 +20,24 @@ class CustomAgent extends http.Agent { describe('WebSocket', () => { describe('#ctor', () => { it('throws an error when using an invalid url', () => { + assert.throws( + () => new WebSocket('foo'), + /^SyntaxError: Invalid URL: foo$/ + ); + + assert.throws( + () => new WebSocket('https://echo.websocket.org'), + /^SyntaxError: The URL's protocol must be one of "ws:", "wss:", or "ws\+unix:"$/ + ); + assert.throws( () => new WebSocket('ws+unix:'), - /^Error: Invalid URL: ws\+unix:$/ + /^SyntaxError: The URL's pathname is empty$/ + ); + + assert.throws( + () => new WebSocket('wss://echo.websocket.org#foo'), + /^SyntaxError: The URL contains a fragment identifier$/ ); });