























@@ -11,6 +11,10 @@ const CLICKCLACK_HTTP_TIMEOUT_MS = readPositiveInt(
1111process.env.OPENCLAW_RELEASE_USER_JOURNEY_HTTP_TIMEOUT_MS,
12125000,
1313);
14+const CLICKCLACK_HTTP_BODY_MAX_BYTES = readPositiveInt(
15+process.env.OPENCLAW_RELEASE_USER_JOURNEY_HTTP_BODY_MAX_BYTES,
16+1024 * 1024,
17+);
14181519function readJson(file) {
1620return JSON.parse(fs.readFileSync(file, "utf8"));
@@ -38,6 +42,55 @@ async function withClickClackFixtureResponse(url, init, consume, options = {}) {
3842}
3943}
404445+function bodyTooLargeError(label, byteLimit) {
46+return Object.assign(new Error(`${label} response body exceeded ${byteLimit} bytes`), {
47+code: "ETOOBIG",
48+});
49+}
50+51+async function readBoundedResponseText(
52+response,
53+label,
54+byteLimit = CLICKCLACK_HTTP_BODY_MAX_BYTES,
55+) {
56+const contentLength = response.headers.get("content-length");
57+if (contentLength) {
58+const parsedLength = Number(contentLength);
59+if (Number.isSafeInteger(parsedLength) && parsedLength > byteLimit) {
60+await response.body?.cancel().catch(() => {});
61+throw bodyTooLargeError(label, byteLimit);
62+}
63+}
64+if (!response.body) {
65+return "";
66+}
67+68+const reader = response.body.getReader();
69+const decoder = new TextDecoder();
70+let byteCount = 0;
71+let text = "";
72+try {
73+while (true) {
74+const { done, value } = await reader.read();
75+if (done) {
76+return text + decoder.decode();
77+}
78+byteCount += value.byteLength;
79+if (byteCount > byteLimit) {
80+await reader.cancel().catch(() => {});
81+throw bodyTooLargeError(label, byteLimit);
82+}
83+text += decoder.decode(value, { stream: true });
84+}
85+} finally {
86+reader.releaseLock();
87+}
88+}
89+90+async function readBoundedResponseJson(response, label) {
91+return JSON.parse(await readBoundedResponseText(response, label));
92+}
93+4194function resolveHomePath(value) {
4295if (value === "~") {
4396return process.env.HOME;
@@ -242,7 +295,8 @@ async function postClickClackInbound() {
242295body: JSON.stringify({ body }),
243296},
244297async (response) => {
245-assert(response.ok, `fixture inbound failed: ${response.status} ${await response.text()}`);
298+const text = response.ok ? "" : await readBoundedResponseText(response, "ClickClack inbound");
299+assert(response.ok, `fixture inbound failed: ${response.status} ${text}`);
246300},
247301);
248302}
@@ -256,7 +310,10 @@ async function waitClickClackSocket() {
256310const state = await withClickClackFixtureResponse(
257311`${baseUrl}/fixture/state`,
258312{},
259-async (response) => (response.ok ? await response.json() : undefined),
313+async (response) =>
314+response.ok
315+ ? await readBoundedResponseJson(response, "ClickClack fixture state")
316+ : undefined,
260317{
261318timeoutMs: Math.min(CLICKCLACK_HTTP_TIMEOUT_MS, remainingMs),
262319},
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。