refactor: share request body chunk accounting

This commit is contained in:
Peter Steinberger
2026-03-13 21:11:00 +00:00
parent 8f852ef82f
commit ef15600b3e

View File

@@ -84,6 +84,12 @@ type RequestBodyLimitValues = {
timeoutMs: number; timeoutMs: number;
}; };
type RequestBodyChunkProgress = {
buffer: Buffer;
totalBytes: number;
exceeded: boolean;
};
function resolveRequestBodyLimitValues(options: { function resolveRequestBodyLimitValues(options: {
maxBytes: number; maxBytes: number;
timeoutMs?: number; timeoutMs?: number;
@@ -98,6 +104,20 @@ function resolveRequestBodyLimitValues(options: {
return { maxBytes, timeoutMs }; return { maxBytes, timeoutMs };
} }
function advanceRequestBodyChunk(
chunk: Buffer | string,
totalBytes: number,
maxBytes: number,
): RequestBodyChunkProgress {
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
const nextTotalBytes = totalBytes + buffer.length;
return {
buffer,
totalBytes: nextTotalBytes,
exceeded: nextTotalBytes > maxBytes,
};
}
export async function readRequestBodyWithLimit( export async function readRequestBodyWithLimit(
req: IncomingMessage, req: IncomingMessage,
options: ReadRequestBodyOptions, options: ReadRequestBodyOptions,
@@ -155,9 +175,9 @@ export async function readRequestBodyWithLimit(
if (done) { if (done) {
return; return;
} }
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); const progress = advanceRequestBodyChunk(chunk, totalBytes, maxBytes);
totalBytes += buffer.length; totalBytes = progress.totalBytes;
if (totalBytes > maxBytes) { if (progress.exceeded) {
const error = new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" }); const error = new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" });
if (!req.destroyed) { if (!req.destroyed) {
req.destroy(); req.destroy();
@@ -165,7 +185,7 @@ export async function readRequestBodyWithLimit(
fail(error); fail(error);
return; return;
} }
chunks.push(buffer); chunks.push(progress.buffer);
}; };
const onEnd = () => { const onEnd = () => {
@@ -313,9 +333,9 @@ export function installRequestBodyLimitGuard(
if (done) { if (done) {
return; return;
} }
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); const progress = advanceRequestBodyChunk(chunk, totalBytes, maxBytes);
totalBytes += buffer.length; totalBytes = progress.totalBytes;
if (totalBytes > maxBytes) { if (progress.exceeded) {
trip(new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" })); trip(new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" }));
} }
}; };