Files
openclaw/scripts/e2e/lib/bounded-response-text.mjs
Peter Steinberger 509f5d3409 fix: bound npm fixture upstream response bodies (#108960)
* test: bound npm fixture upstream responses

* test: auto-clean npm fixture temp dirs

* style: format npm fixture assertion test

* test: simplify plugin fixture temp cleanup
2026-07-16 04:53:43 -07:00

73 lines
2.1 KiB
JavaScript

// Bounded response body reader used by E2E HTTP fixture clients.
function bodyTooLargeError(label, byteLimit) {
return Object.assign(new Error(`${label} response body exceeded ${byteLimit} bytes`), {
code: "ETOOBIG",
});
}
function cancelReaderSoon(reader) {
void Promise.resolve()
.then(() => reader.cancel())
.catch(() => {});
}
function parseContentLengthHeader(headers) {
const raw = headers.get("content-length");
if (!raw || !/^\d+$/u.test(raw)) {
return undefined;
}
const parsed = Number(raw);
return Number.isSafeInteger(parsed) ? parsed : Number.POSITIVE_INFINITY;
}
export async function readBoundedResponseBytes(response, label, byteLimit, timeoutPromise) {
const contentLength = parseContentLengthHeader(response.headers);
if (contentLength !== undefined && contentLength > byteLimit) {
await response.body?.cancel().catch(() => {});
throw bodyTooLargeError(label, byteLimit);
}
if (!response.body) {
return Buffer.alloc(0);
}
const reader = response.body.getReader();
const chunks = [];
let byteCount = 0;
let canceled = false;
try {
while (true) {
const read = reader.read();
const readWithTimeout = timeoutPromise
? Promise.race([
read,
timeoutPromise.catch((error) => {
canceled = true;
cancelReaderSoon(reader);
throw error;
}),
])
: read;
const { done, value } = await readWithTimeout;
if (done) {
return Buffer.concat(chunks, byteCount);
}
byteCount += value.byteLength;
if (byteCount > byteLimit) {
canceled = true;
await reader.cancel().catch(() => {});
throw bodyTooLargeError(label, byteLimit);
}
chunks.push(Buffer.from(value));
}
} finally {
if (!canceled) {
reader.releaseLock();
}
}
}
export async function readBoundedResponseText(response, label, byteLimit, timeoutPromise) {
const bytes = await readBoundedResponseBytes(response, label, byteLimit, timeoutPromise);
return new TextDecoder().decode(bytes);
}