mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-25 22:59:32 +00:00
fix(signal): cancel status-only response bodies
This commit is contained in:
@@ -130,6 +130,22 @@ describe("containerCheck", () => {
|
||||
expectFirstFetchCall("http://localhost:8080/v1/about", "GET");
|
||||
});
|
||||
|
||||
it("cancels /v1/about response bodies after simple health checks", async () => {
|
||||
const cancel = vi.fn(async () => undefined);
|
||||
mockFetch.mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
body: { cancel },
|
||||
});
|
||||
|
||||
await expect(containerCheck("http://localhost:8080")).resolves.toEqual({
|
||||
ok: true,
|
||||
status: 200,
|
||||
error: null,
|
||||
});
|
||||
expect(cancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("returns ok:false when /v1/about returns 404", async () => {
|
||||
mockFetch.mockResolvedValue({
|
||||
ok: false,
|
||||
@@ -635,9 +651,11 @@ describe("containerFetchAttachment", () => {
|
||||
});
|
||||
|
||||
it("returns null on non-ok response", async () => {
|
||||
const cancel = vi.fn(async () => undefined);
|
||||
mockFetch.mockResolvedValue({
|
||||
ok: false,
|
||||
status: 404,
|
||||
body: { cancel },
|
||||
});
|
||||
|
||||
const result = await containerFetchAttachment("attachment-123", {
|
||||
@@ -645,6 +663,7 @@ describe("containerFetchAttachment", () => {
|
||||
});
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(cancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("encodes attachment ID in URL", async () => {
|
||||
|
||||
@@ -111,6 +111,12 @@ async function readCappedResponseBuffer(res: Response, maxResponseBytes: number)
|
||||
});
|
||||
}
|
||||
|
||||
async function releaseUnreadResponseBody(res: Response | undefined): Promise<void> {
|
||||
if (res?.bodyUsed !== true) {
|
||||
await res?.body?.cancel().catch(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if bbernhard container REST API is available.
|
||||
*/
|
||||
@@ -120,8 +126,9 @@ export async function containerCheck(
|
||||
account?: string,
|
||||
): Promise<{ ok: boolean; status?: number | null; error?: string | null }> {
|
||||
const normalized = normalizeBaseUrl(baseUrl);
|
||||
let res: Response | undefined;
|
||||
try {
|
||||
const res = await fetchWithTimeout(`${normalized}/v1/about`, { method: "GET" }, timeoutMs);
|
||||
res = await fetchWithTimeout(`${normalized}/v1/about`, { method: "GET" }, timeoutMs);
|
||||
if (!res.ok) {
|
||||
return { ok: false, status: res.status, error: `HTTP ${res.status}` };
|
||||
}
|
||||
@@ -136,6 +143,8 @@ export async function containerCheck(
|
||||
status: null,
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
};
|
||||
} finally {
|
||||
await releaseUnreadResponseBody(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,14 +262,19 @@ export async function containerFetchAttachment(
|
||||
): Promise<Buffer | null> {
|
||||
const baseUrl = normalizeBaseUrl(opts.baseUrl);
|
||||
const url = `${baseUrl}/v1/attachments/${encodeURIComponent(attachmentId)}`;
|
||||
let res: Response | undefined;
|
||||
|
||||
const res = await fetchWithTimeout(url, { method: "GET" }, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
||||
try {
|
||||
res = await fetchWithTimeout(url, { method: "GET" }, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
||||
|
||||
if (!res.ok) {
|
||||
return null;
|
||||
if (!res.ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await readCappedResponseBuffer(res, normalizeMaxResponseBytes(opts.maxResponseBytes));
|
||||
} finally {
|
||||
await releaseUnreadResponseBody(res);
|
||||
}
|
||||
|
||||
return readCappedResponseBuffer(res, normalizeMaxResponseBytes(opts.maxResponseBytes));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user