I am using the (ws package) to serve websockets from Node.js. I use the "on upgrade" event to authenticate the connecting clients using a token passed in as a URL parameter. Following the example here, in the event of the token being invalid/missing/expired, I use the following (typescript) code to reject the connection:
server.on('upgrade', async (req: Request, socket: Socket) => {
// Make sure that we only handle WebSocket upgrade requests
if (req.headers['upgrade'] !== 'websocket') {
socket.destroy(new Error(`Expected headers upgrade == 'websocket', received ${req.headers['upgrade']}`));
return;
}
if (_.get(this.config, 'security.enableAuth')) {
logger.info('[socket] security: validating the session key parameter');
const u = querystring.parse(req.url.substring(req.url.indexOf('?') + 1));
if (!u.sessionKey) {
logger.info('[debug] no session key found');
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
const token = u.sessionKey as string;
let result: AuthResult;
try {
result = await auth(token);
} catch (err) {
logger.warn('[socket] error validating session key:', err);
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
// and so on...
This all works, except on the client side I do not receive the 401 message, nor anything that can tell me why the connection failed. Chrome network tab shows no messages received, and the close event has code 1006 (CLOSE_ABNORMAL), with no other information. How do I pass a sensible error code or message so that the client knows why the failure occurred?