fix: hijack upgrade event before WsAdapter can consume the socket

WsAdapter registered its upgrade handler first and destroyed sockets
for non-matching paths. Now we remove all existing upgrade listeners,
install ours first, and forward non-terminal/sftp upgrades to the
original WsAdapter handlers for RDP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-13 23:28:54 -04:00
parent 55b944bfc5
commit 8207b78b36

View File

@ -18,7 +18,6 @@ async function bootstrap() {
await app.listen(3000);
console.log('Wraith backend running on port 3000');
// Manual WebSocket handling — bypasses NestJS WsAdapter entirely
const server = app.getHttpServer();
const terminalGateway = app.get(TerminalGateway);
const sftpGateway = app.get(SftpGateway);
@ -27,30 +26,39 @@ async function bootstrap() {
const sftpWss = new WebSocketServer({ noServer: true });
terminalWss.on('connection', (ws, req) => {
console.log(`[WS] Terminal connection from ${req.url}`);
console.log(`[WS] Terminal connection established`);
terminalGateway.handleConnection(ws, req);
});
sftpWss.on('connection', (ws, req) => {
console.log(`[WS] SFTP connection from ${req.url}`);
console.log(`[WS] SFTP connection established`);
sftpGateway.handleConnection(ws, req);
});
// Remove ALL existing upgrade listeners (WsAdapter's) so we handle upgrades first
const existingListeners = server.listeners('upgrade');
server.removeAllListeners('upgrade');
// Our handler runs first — routes terminal/sftp, passes everything else to WsAdapter
server.on('upgrade', (req: any, socket: any, head: any) => {
const pathname = req.url?.split('?')[0];
console.log(`[HTTP-UPGRADE] path=${pathname}`);
console.log(`[HTTP-UPGRADE] path=${pathname} socket.destroyed=${socket.destroyed}`);
if (pathname === '/api/ws/terminal') {
terminalWss.handleUpgrade(req, socket, head, (ws) => {
console.log(`[WS] Terminal upgrade complete`);
terminalWss.emit('connection', ws, req);
});
} else if (pathname === '/api/ws/sftp') {
sftpWss.handleUpgrade(req, socket, head, (ws) => {
console.log(`[WS] SFTP upgrade complete`);
sftpWss.emit('connection', ws, req);
});
} else {
console.log(`[HTTP-UPGRADE] Unknown WS path: ${pathname}, destroying socket`);
socket.destroy();
// Pass to WsAdapter's original handlers (for RDP etc)
for (const listener of existingListeners) {
listener.call(server, req, socket, head);
}
}
});
}