From 070a3336099b3bffa0f47d276fb3b56c0d6acb43 Mon Sep 17 00:00:00 2001 From: HotelSync Date: Wed, 1 Apr 2026 21:11:40 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20agent-ws=20=E2=80=94=20safe=20socket.clo?= =?UTF-8?q?se()=20for=20non-WebSocket=20requests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HEAD/GET requests without WS upgrade caused 'socket.close is not a function' crash → 500 errors in logs. Wrap close() in try-catch. Co-Authored-By: Claude Sonnet 4.6 --- backend/src/agent-ws.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/src/agent-ws.ts b/backend/src/agent-ws.ts index 3845c26..064f2d8 100644 --- a/backend/src/agent-ws.ts +++ b/backend/src/agent-ws.ts @@ -97,17 +97,22 @@ export const setupAgentWsRoute: FastifyPluginAsync = async (fastify) => { fastify.get('/ws/agent', { websocket: true }, async (connection: SocketStream, req) => { const socket = connection.socket as AgentSocket + // Если соединение не WebSocket (HEAD/GET без Upgrade) — просто закрываем + const safeClose = (code: number, reason: string) => { + try { socket.close(code, reason) } catch { /* HTTP-сокет — игнорируем */ } + } + // Аутентификация по токену из заголовка try { const authHeader = req.headers.authorization ?? '' const token = authHeader.replace('Bearer ', '') - if (!token) { socket.close(1008, 'Unauthorized'); return } + if (!token) { safeClose(1008, 'Unauthorized'); return } const payload = fastify.jwt.verify(token) as { sub: string; role: string; workstation_id: string; hotel_slug: string } - if (payload.role !== 'agent') { socket.close(1008, 'Forbidden'); return } + if (payload.role !== 'agent') { safeClose(1008, 'Forbidden'); return } socket.agentId = payload.sub socket.workstationId = payload.workstation_id @@ -115,7 +120,7 @@ export const setupAgentWsRoute: FastifyPluginAsync = async (fastify) => { socket.isAlive = true } catch { - socket.close(1008, 'Invalid token') + safeClose(1008, 'Invalid token') return }