mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 13:26:04 -06:00
fix(signal): release connections after failed CLI downloads (#109442)
* fix(signal): cancel failed CLI download responses * fix(signal): close all failed installer responses Co-authored-by: wahaha1223 <0668001153@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -264,6 +264,20 @@ describe("pickAsset", () => {
|
||||
});
|
||||
|
||||
describe("downloadToFile", () => {
|
||||
it("cancels non-success response bodies before rejecting", async () => {
|
||||
const response = new Response("service unavailable", { status: 503 });
|
||||
const cancel = vi.spyOn(response.body!, "cancel").mockRejectedValueOnce(new Error("closed"));
|
||||
fetchWithSsrFGuardMock.mockResolvedValue({ response, release: vi.fn() });
|
||||
|
||||
await withTempFile(async (filePath) => {
|
||||
await expect(downloadToFile("https://example.com/signal-cli.tgz", filePath)).rejects.toThrow(
|
||||
"HTTP 503",
|
||||
);
|
||||
});
|
||||
|
||||
expect(cancel).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("downloads through the SSRF guard with an explicit timeout", async () => {
|
||||
const fetchResult = okDownloadResponse("archive");
|
||||
fetchWithSsrFGuardMock.mockResolvedValue(fetchResult);
|
||||
@@ -344,6 +358,23 @@ describe("downloadToFile", () => {
|
||||
});
|
||||
|
||||
describe("installSignalCliFromRelease", () => {
|
||||
it("cancels non-success release metadata before returning the fetch error", async () => {
|
||||
const response = new Response("service unavailable", { status: 503 });
|
||||
const cancel = vi.spyOn(response.body!, "cancel").mockRejectedValueOnce(new Error("closed"));
|
||||
const release = vi.fn().mockResolvedValue(undefined);
|
||||
fetchWithSsrFGuardMock.mockResolvedValue({ response, release });
|
||||
|
||||
await expect(
|
||||
installSignalCliFromRelease({ log: vi.fn() } as unknown as RuntimeEnv),
|
||||
).resolves.toEqual({
|
||||
ok: false,
|
||||
error: "Failed to fetch release info (503)",
|
||||
});
|
||||
|
||||
expect(cancel).toHaveBeenCalledOnce();
|
||||
expect(release).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("returns an installer error when GitHub release metadata is malformed JSON", async () => {
|
||||
const fetchResult = okDownloadResponse("{not json", {
|
||||
headers: { "content-type": "application/json" },
|
||||
|
||||
@@ -83,6 +83,10 @@ function chunkByteLength(chunk: unknown): number {
|
||||
return Buffer.byteLength(String(chunk));
|
||||
}
|
||||
|
||||
async function cancelUnusedResponseBody(response: Response): Promise<void> {
|
||||
await response.body?.cancel().catch(() => undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a native release asset from the official GitHub releases.
|
||||
*
|
||||
@@ -149,6 +153,7 @@ export async function downloadToFile(
|
||||
});
|
||||
try {
|
||||
if (!response.ok || !response.body) {
|
||||
await cancelUnusedResponseBody(response);
|
||||
throw new Error(`HTTP ${response.status || "?"} downloading file`);
|
||||
}
|
||||
|
||||
@@ -313,6 +318,7 @@ export async function installSignalCliFromRelease(
|
||||
let payload: ReleaseResponse;
|
||||
try {
|
||||
if (!response.ok) {
|
||||
await cancelUnusedResponseBody(response);
|
||||
return {
|
||||
ok: false,
|
||||
error: `Failed to fetch release info (${response.status})`,
|
||||
|
||||
Reference in New Issue
Block a user