fix(gateway): enforce request body size limits

This commit is contained in:
William Valentin
2026-02-15 21:44:36 -08:00
parent 22959ea3aa
commit d93c1c9f8d
13 changed files with 270 additions and 22 deletions
+14 -9
View File
@@ -41,6 +41,7 @@ import type { CommandRegistry } from '../commands/index.js';
import type { ComponentRegistry } from '../intents/index.js';
import type { RoutingPolicy } from '../routing/index.js';
import type { ChannelRegistry } from '../channels/index.js';
import { RequestBodyTooLargeError, readRequestBody } from '../utils/httpBody.js';
export interface GatewayServerConfig {
port: number;
@@ -67,6 +68,8 @@ export interface GatewayServerConfig {
gmailHandler?: GmailWatcher;
/** Optional callback to retrieve per-session token usage data for the dashboard. */
getTokenUsage?: () => TokenUsageEntry[];
/** Maximum allowed request body size for inbound HTTP POST bodies. */
maxRequestBodyBytes?: number;
/** Optional pairing manager for DM pairing code management via gateway. */
pairingManager?: PairingManager;
memoryStore?: MemoryStore;
@@ -76,6 +79,7 @@ export interface GatewayServerConfig {
}
export class GatewayServer {
private static readonly DEFAULT_MAX_REQUEST_BODY_BYTES = 1_048_576; // 1 MiB
private wss: WebSocketServer | null = null;
private httpServer: HttpServer | null = null;
private router: Router;
@@ -348,9 +352,14 @@ export class GatewayServer {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true }));
} catch (err) {
console.error('Gmail push handler error:', err instanceof Error ? err.message : err);
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid request' }));
if (err instanceof RequestBodyTooLargeError) {
res.writeHead(413, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Payload too large' }));
} else {
console.error('Gmail push handler error:', err instanceof Error ? err.message : err);
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid request' }));
}
}
return;
}
@@ -444,11 +453,7 @@ export class GatewayServer {
/** Read the full request body as a string. */
private readRequestBody(req: IncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
req.on('data', (chunk: Buffer) => chunks.push(chunk));
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
req.on('error', reject);
});
const maxBytes = this.config.maxRequestBodyBytes ?? GatewayServer.DEFAULT_MAX_REQUEST_BODY_BYTES;
return readRequestBody(req, { maxBytes });
}
}