From 5aceeb31e7b1fd72a5e05cebc9a2e3d4584d4f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Wed, 16 Jul 2025 01:04:06 +0200 Subject: [PATCH] Return request errors for /streaming in-band instead of in HTTP Closes #591 --- .../server/api/StreamingApiServerService.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 231ba7bfbf..b6b930a434 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -116,6 +116,7 @@ export class StreamingApiServerService implements OnApplicationShutdown { let user: MiLocalUser | null = null; let app: MiAccessToken | null = null; + let dieInstantly: [number, string] | null = null; // https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 // Note that the standard WHATWG WebSocket API does not support setting any headers, @@ -132,21 +133,16 @@ export class StreamingApiServerService implements OnApplicationShutdown { } } catch (e) { if (e instanceof AuthenticationError) { - socket.write([ - 'HTTP/1.1 401 Unauthorized', - 'WWW-Authenticate: Bearer realm="Misskey", error="invalid_token", error_description="Failed to authenticate"', - ].join('\r\n') + '\r\n\r\n'); + dieInstantly = [4000, 'Failed to authenticate']; } else { socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n'); + socket.destroy(); + return; } - socket.destroy(); - return; } if (user?.isSuspended) { - socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); - socket.destroy(); - return; + dieInstantly = [4001, 'User suspended']; } // ServerServices sets `trustProxy: true`, which inside fastify/request.js ends up calling `proxyAddr` in this way, so we do the same. @@ -231,6 +227,11 @@ export class StreamingApiServerService implements OnApplicationShutdown { ws.terminate(); }); + if (dieInstantly !== null) { + ws.close(...dieInstantly); + return; + } + this.#wss.emit('connection', ws, request, { stream, user, app, });