export class RequestBodyTooLargeError extends Error { status = 413; constructor(max_bytes) { super(`Request body exceeds ${max_bytes} bytes`); this.name = "RequestBodyTooLargeError"; } } /** * Reads the whole request body, aborting as soon as it grows past * `max_bytes` so oversized (or chunked, length-less) bodies are never fully * buffered. Returns `undefined` when the request has no body. */ export default async function readRequestBody({ req, max_bytes, }) { if (req.method == "GET" || req.method == "HEAD" || !req.body) { return undefined; } const content_length = Number(req.headers.get("content-length")); if (content_length > max_bytes) { throw new RequestBodyTooLargeError(max_bytes); } const reader = req.body.getReader(); const chunks = []; let total = 0; while (true) { const { done, value } = await reader.read(); if (done) break; total += value.byteLength; if (total > max_bytes) { await reader.cancel(); throw new RequestBodyTooLargeError(max_bytes); } chunks.push(value); } const body = new Uint8Array(total); let offset = 0; for (const chunk of chunks) { body.set(chunk, offset); offset += chunk.byteLength; } return body; }