A socket's own error closes that socket, not the server

A message over the size limit or a malformed frame raised an error on
the socket, which had no listener, and Node ended the process: one
message from anyone could take the server down until systemd restarted
it. The socket is terminated instead. Messages are capped at 1 KB, since the server never reads them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-27 01:21:44 -04:00
co-authored by Claude Opus 5.5
parent 41349036d1
commit cc71ee4421
+4 -1
View File
@@ -312,7 +312,8 @@ const server = createServer((req, res) => {
}); });
}); });
const wss = new WebSocketServer({ noServer: true }); // The socket only ever speaks to the browser; anything the browser sends is ignored, so it may send almost nothing.
const wss = new WebSocketServer({ noServer: true, maxPayload: 1024 });
server.on('upgrade', (req, socket, head) => { server.on('upgrade', (req, socket, head) => {
const url = new URL(req.url ?? '/', 'http://localhost'); const url = new URL(req.url ?? '/', 'http://localhost');
if (url.pathname !== '/ws') return socket.destroy(); if (url.pathname !== '/ws') return socket.destroy();
@@ -332,6 +333,8 @@ server.on('upgrade', (req, socket, head) => {
}; };
const unsubscribe = seatId === SPECTATOR ? rooms.watch(room, onChange) : rooms.subscribe(room.id, onChange); const unsubscribe = seatId === SPECTATOR ? rooms.watch(room, onChange) : rooms.subscribe(room.id, onChange);
ws.on('close', unsubscribe); ws.on('close', unsubscribe);
// A socket's own error (a message over the limit, a malformed frame) closes that socket, never the server.
ws.on('error', () => ws.terminate());
ws.send(JSON.stringify({ type: 'hello', seat: seatId })); ws.send(JSON.stringify({ type: 'hello', seat: seatId }));
}); });
}); });