import type { IncomingMessage, ServerResponse } from 'node:http'; export const MAX_BODY_SIZE = 1024 * 1024; // 1 MB export function sendJSON(res: ServerResponse, status: number, data: unknown): void { res.writeHead(status, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); } export function sendText(res: ServerResponse, status: number, text: string, contentType = 'text/plain'): void { res.writeHead(status, { 'Content-Type': contentType }); res.end(text); } export function parseBody(req: IncomingMessage): Promise { return new Promise((resolveP, reject) => { const chunks: Buffer[] = []; let size = 0; req.on('data', (c: Buffer) => { size += c.length; if (size > MAX_BODY_SIZE) { req.destroy(); reject(new Error('Request body too large')); return; } chunks.push(c); }); req.on('end', () => resolveP(Buffer.concat(chunks).toString())); req.on('error', reject); }); } export async function parseJSONBody(req: IncomingMessage): Promise { const body = await parseBody(req); return JSON.parse(body) as T; } export function parseCookies(req: IncomingMessage): Record { const cookies: Record = {}; const header = req.headers.cookie || ''; for (const pair of header.split(';')) { const eq = pair.indexOf('='); if (eq === -1) continue; cookies[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim(); } return cookies; } export function clientIp(req: IncomingMessage): string { const xff = (req.headers['x-forwarded-for'] as string | undefined)?.split(',')[0]?.trim(); return xff || req.socket.remoteAddress || 'unknown'; }