Skip to content

Commit

Permalink
[feature] Allow http and https schemes (#2162)
Browse files Browse the repository at this point in the history
Allow HTTP(S) URLs to be used in the WebSocket constructor. They are
immediately converted to the ws and wss schemes.

Refs: whatwg/websockets#45
  • Loading branch information
lpinca committed Aug 28, 2023
1 parent 79dab96 commit 347aab6
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 10 deletions.
12 changes: 9 additions & 3 deletions lib/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -667,24 +667,30 @@ 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;

if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
invalidUrlMessage =
'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"';
'The URL\'s protocol must be one of "ws:", "wss:", ' +
'"http:", "https", or "ws+unix:"';
} else if (isIpcUrl && !parsedUrl.pathname) {
invalidUrlMessage = "The URL's pathname is empty";
} else if (parsedUrl.hash) {
Expand Down
57 changes: 50 additions & 7 deletions test/websocket.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,16 @@ describe('WebSocket', () => {
);

assert.throws(
() => new WebSocket('https://websocket-echo.com'),
/^SyntaxError: The URL's protocol must be one of "ws:", "wss:", or "ws\+unix:"$/
() => new WebSocket('bad-scheme://websocket-echo.com'),
(err) => {
assert.strictEqual(
err.message,
'The URL\'s protocol must be one of "ws:", "wss:", ' +
'"http:", "https", or "ws+unix:"'
);

return true;
}
);

assert.throws(
Expand Down Expand Up @@ -72,6 +80,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();
Expand Down Expand Up @@ -539,10 +571,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']
]);

for (const [key, value] of schemes) {
const ws = new WebSocket(`${key}://localhost/`, { lookup() {} });

assert.strictEqual(ws.url, url);
assert.strictEqual(ws.url, `${value}://localhost/`);
}
});
});
});
Expand Down Expand Up @@ -1174,7 +1214,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: bad-scheme://localhost\r\n\r\n'
);
});

const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
Expand All @@ -1186,7 +1228,8 @@ describe('WebSocket', () => {
assert.ok(err instanceof SyntaxError);
assert.strictEqual(
err.message,
'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"'
'The URL\'s protocol must be one of "ws:", "wss:", ' +
'"http:", "https", or "ws+unix:"'
);
assert.strictEqual(ws._redirects, 1);

Expand Down

0 comments on commit 347aab6

Please sign in to comment.