Files
coolify/tests/Fixtures/terminal-websocket-rejection-server.mjs
22a8c09dd6 Next (#12202)
Co-authored-by: Aditya Tripathi <aditya@climactic.co>
Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rosslh <ross@rosshill.ca>
Co-authored-by: Abdulfetah Suudi <suudiabdulfetah@gmail.com>
Co-authored-by: Dharmveer <51308779+dharmveer97@users.noreply.github.com>
Co-authored-by: Maxwell <136101+mxswd@users.noreply.github.com>
2026-10-19 10:07:23 +02:00

75 lines
2.4 KiB
JavaScript

// Minimal stand-in for the terminal WebSocket server used by browser tests.
// Built on Node core only (no `ws`), it reproduces how the real server rejects
// authentication so the browser client can be tested end to end.
//
// Usage: node terminal-websocket-rejection-server.mjs <mode>
// close-on-upgrade: complete the handshake, then close with 4401 (session rejected)
// reject-token: on the first client frame, send the legacy text message and close with 4403
// ready: on the first client frame, signal that the PTY is ready
//
// Prints the listening port on stdout. GET /stats returns {"upgrades": n}.
import { createHash } from 'node:crypto';
import http from 'node:http';
const mode = process.argv[2] ?? 'close-on-upgrade';
let upgrades = 0;
function frame(opcode, payload) {
if (payload.length > 125) {
throw new Error('Fixture only supports short frames.');
}
return Buffer.concat([Buffer.from([0x80 | opcode, payload.length]), payload]);
}
function closeFrame(code, reason) {
const payload = Buffer.alloc(2 + Buffer.byteLength(reason));
payload.writeUInt16BE(code, 0);
payload.write(reason, 2);
return frame(0x8, payload);
}
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
res.end(JSON.stringify({ upgrades }));
});
server.on('upgrade', (req, socket) => {
upgrades++;
socket.on('error', () => socket.destroy());
const accept = createHash('sha1')
.update(`${req.headers['sec-websocket-key']}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
.digest('base64');
socket.write([
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
`Sec-WebSocket-Accept: ${accept}`,
'',
'',
].join('\r\n'));
if (mode === 'close-on-upgrade') {
socket.end(closeFrame(4401, 'Unauthorized: Invalid credentials'));
return;
}
socket.once('data', () => {
if (mode === 'ready') {
socket.write(frame(0x1, Buffer.from('pty-ready')));
return;
}
const message = 'Unauthorized: Terminal token was rejected';
socket.write(frame(0x1, Buffer.from(message)));
socket.end(closeFrame(4403, message));
});
});
server.listen(0, '127.0.0.1', () => {
process.stdout.write(`${server.address().port}\n`);
});