export class RequestBodyTooLargeError extends Error { constructor() { super("Request body exceeds the allowed size"); } } function declaredContentLength(request: Request): number | null { const value = request.headers.get("content-length"); if (!value || !/^\d+$/.test(value)) return null; const length = Number(value); return Number.isSafeInteger(length) ? length : null; } /** * Parse multipart data only after constraining the complete wire body. This * bounds chunked requests too, where Content-Length is unavailable or false. */ export async function parseFormDataWithinLimit(request: Request, maxBytes: number): Promise { const declared = declaredContentLength(request); if (declared !== null && declared > maxBytes) { throw new RequestBodyTooLargeError(); } const reader = request.body?.getReader(); if (!reader) return request.formData(); const chunks: BlobPart[] = []; let size = 0; try { while (true) { const { done, value } = await reader.read(); if (done) break; if (size + value.byteLength > maxBytes) { await reader.cancel().catch(() => {}); throw new RequestBodyTooLargeError(); } size += value.byteLength; const chunk = new Uint8Array(value.byteLength); chunk.set(value); chunks.push(chunk); } } finally { reader.releaseLock(); } const contentType = request.headers.get("content-type"); const headers = contentType ? { "content-type": contentType } : undefined; return new Response(new Blob(chunks), { headers }).formData(); }