Skip to content

Commit

Permalink
[fix] Do not throw if the redirect URL is invalid
Browse files Browse the repository at this point in the history
If the redirect URL is invalid, then emit the error instead of throwing
it, otherwise there is no way to handle it.
  • Loading branch information
lpinca committed Nov 23, 2021
1 parent 2d968a6 commit 73dec34
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 5 deletions.
35 changes: 30 additions & 5 deletions lib/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,14 @@ function initAsClient(websocket, address, protocols, options) {
const isUnixSocket = parsedUrl.protocol === 'ws+unix:';

if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
throw new Error(`Invalid URL: ${websocket.url}`);
const err = new Error(`Invalid URL: ${websocket.url}`);

if (websocket._redirects === 0) {
throw err;
} else {
emitErrorAndClose(websocket, err);
return;
}
}

const isSecure =
Expand Down Expand Up @@ -687,9 +694,7 @@ function initAsClient(websocket, address, protocols, options) {
if (req === null || req.aborted) return;

req = websocket._req = null;
websocket._readyState = WebSocket.CLOSING;
websocket.emit('error', err);
websocket.emitClose();
emitErrorAndClose(websocket, err);
});

req.on('response', (res) => {
Expand All @@ -709,7 +714,14 @@ function initAsClient(websocket, address, protocols, options) {

req.abort();

const addr = new URL(location, address);
let addr;

try {
addr = new URL(location, address);
} catch (err) {
emitErrorAndClose(websocket, err);
return;
}

initAsClient(websocket, addr, protocols, options);
} else if (!websocket.emit('unexpected-response', req, res)) {
Expand Down Expand Up @@ -811,6 +823,19 @@ function initAsClient(websocket, address, protocols, options) {
});
}

/**
* Emit the `'error'` and `'close'` event.
*
* @param {WebSocket} websocket The WebSocket instance
* @param {Error} The error to emit
* @private
*/
function emitErrorAndClose(websocket, err) {
websocket._readyState = WebSocket.CLOSING;
websocket.emit('error', err);
websocket.emitClose();
}

/**
* Create a `net.Socket` and initiate a connection.
*
Expand Down
45 changes: 45 additions & 0 deletions test/websocket.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,51 @@ describe('WebSocket', () => {
ws.on('close', () => done());
});
});

it('emits an error if the redirect URL is invalid (1/2)', (done) => {
const onUpgrade = (req, socket) => {
socket.end('HTTP/1.1 302 Found\r\nLocation: ws://\r\n\r\n');
};

server.on('upgrade', onUpgrade);

const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
followRedirects: true
});

ws.on('open', () => done(new Error("Unexpected 'open' event")));
ws.on('error', (err) => {
assert.ok(err instanceof Error);
assert.ok(/Invalid URL/.test(err.message));
assert.strictEqual(err.input, 'ws://');
assert.strictEqual(ws._redirects, 1);

server.removeListener('upgrade', onUpgrade);
ws.on('close', () => done());
});
});

it('emits an error if the redirect URL is invalid (2/2)', (done) => {
const onUpgrade = (req, socket) => {
socket.end('HTTP/1.1 302 Found\r\nLocation: ws+unix:\r\n\r\n');
};

server.on('upgrade', onUpgrade);

const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
followRedirects: true
});

ws.on('open', () => done(new Error("Unexpected 'open' event")));
ws.on('error', (err) => {
assert.ok(err instanceof Error);
assert.strictEqual(err.message, 'Invalid URL: ws+unix:');
assert.strictEqual(ws._redirects, 1);

server.removeListener('upgrade', onUpgrade);
ws.on('close', () => done());
});
});
});

describe('Connection with query string', () => {
Expand Down

0 comments on commit 73dec34

Please sign in to comment.