mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-05 21:12:55 +00:00
98 lines
2.5 KiB
JavaScript
98 lines
2.5 KiB
JavaScript
import { readPositiveIntEnv } from "./env-limits.mjs";
|
|
|
|
const DEFAULT_REQUEST_MAX_BYTES = 4 * 1024 * 1024;
|
|
const DEFAULT_REQUEST_LOG_BODY_MAX_BYTES = 256 * 1024;
|
|
const REQUEST_LOG_PREVIEW_CHARS = 4096;
|
|
|
|
export function readMockOpenAiHttpLimits(env = process.env) {
|
|
return {
|
|
requestMaxBytes: readPositiveIntEnv(
|
|
"OPENCLAW_MOCK_OPENAI_REQUEST_MAX_BYTES",
|
|
DEFAULT_REQUEST_MAX_BYTES,
|
|
env,
|
|
),
|
|
requestLogBodyMaxBytes: readPositiveIntEnv(
|
|
"OPENCLAW_MOCK_OPENAI_REQUEST_LOG_BODY_MAX_BYTES",
|
|
DEFAULT_REQUEST_LOG_BODY_MAX_BYTES,
|
|
env,
|
|
),
|
|
};
|
|
}
|
|
|
|
function requestBodyTooLargeError(limit) {
|
|
return Object.assign(new Error(`mock OpenAI request body exceeded ${limit} bytes`), {
|
|
code: "ETOOBIG",
|
|
});
|
|
}
|
|
|
|
export function isRequestBodyTooLargeError(error) {
|
|
return error instanceof Error && error.code === "ETOOBIG";
|
|
}
|
|
|
|
export function readBody(req, limits = readMockOpenAiHttpLimits()) {
|
|
const { requestMaxBytes } = limits;
|
|
return new Promise((resolve, reject) => {
|
|
let body = "";
|
|
let bytes = 0;
|
|
let settled = false;
|
|
req.setEncoding("utf8");
|
|
req.on("data", (chunk) => {
|
|
if (settled) {
|
|
return;
|
|
}
|
|
bytes += Buffer.byteLength(chunk, "utf8");
|
|
if (bytes > requestMaxBytes) {
|
|
settled = true;
|
|
body = "";
|
|
req.resume();
|
|
reject(requestBodyTooLargeError(requestMaxBytes));
|
|
return;
|
|
}
|
|
body += chunk;
|
|
});
|
|
req.on("end", () => {
|
|
if (!settled) {
|
|
settled = true;
|
|
resolve(body);
|
|
}
|
|
});
|
|
req.on("error", (error) => {
|
|
if (!settled) {
|
|
settled = true;
|
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
export function boundedRequestLogBody(value, bodyText, limits = readMockOpenAiHttpLimits()) {
|
|
const { requestLogBodyMaxBytes } = limits;
|
|
const byteLength = Buffer.byteLength(bodyText, "utf8");
|
|
if (byteLength <= requestLogBodyMaxBytes) {
|
|
return value;
|
|
}
|
|
return {
|
|
truncated: true,
|
|
byteLength,
|
|
preview: bodyText.slice(0, REQUEST_LOG_PREVIEW_CHARS),
|
|
};
|
|
}
|
|
|
|
export function writeJson(res, status, body) {
|
|
res.writeHead(status, { "content-type": "application/json" });
|
|
res.end(JSON.stringify(body));
|
|
}
|
|
|
|
export function writeSse(res, events) {
|
|
res.writeHead(200, {
|
|
"content-type": "text/event-stream",
|
|
"cache-control": "no-store",
|
|
connection: "keep-alive",
|
|
});
|
|
for (const event of events) {
|
|
res.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
}
|
|
res.write("data: [DONE]\n\n");
|
|
res.end();
|
|
}
|