diff --git a/src/crestodian/probes.test.ts b/src/crestodian/probes.test.ts index 8584b227aa8b..c8f92dad5394 100644 --- a/src/crestodian/probes.test.ts +++ b/src/crestodian/probes.test.ts @@ -6,6 +6,7 @@ import { probeGatewayUrl, probeLocalCommand } from "./probes.js"; describe("crestodian probes", () => { afterEach(() => { vi.restoreAllMocks(); + vi.unstubAllGlobals(); }); it("bounds noisy local command probe output", async () => { @@ -54,4 +55,26 @@ describe("crestodian probes", () => { expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); }); + + it("cancels gateway health response bodies", async () => { + const cancel = vi.fn(async () => undefined); + vi.stubGlobal( + "fetch", + vi.fn( + async () => + ({ + ok: false, + statusText: "Service Unavailable", + body: { cancel }, + }) as unknown as Response, + ), + ); + + await expect(probeGatewayUrl("ws://127.0.0.1:1234")).resolves.toEqual({ + reachable: false, + url: "ws://127.0.0.1:1234", + error: "Service Unavailable", + }); + expect(cancel).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/crestodian/probes.ts b/src/crestodian/probes.ts index e17d0839b82c..401e3f98c966 100644 --- a/src/crestodian/probes.ts +++ b/src/crestodian/probes.ts @@ -116,8 +116,9 @@ export async function probeGatewayUrl( const timeoutMs = resolveTimerTimeoutMs(opts.timeoutMs, 900); const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), timeoutMs); + let response: Response | undefined; try { - const response = await fetch(healthUrl, { + response = await fetch(healthUrl, { method: "GET", signal: controller.signal, }); @@ -130,5 +131,6 @@ export async function probeGatewayUrl( }; } finally { clearTimeout(timeout); + await response?.body?.cancel().catch(() => undefined); } }