fix(discord): Activity OAuth no longer holds failed Discord connections (#109869)

* fix(discord): avoid Activity OAuth stalls after API rejection

* test(discord): preserve status on cancel failure

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
mushuiyu886
2026-07-18 00:24:40 +01:00
committed by GitHub
co-authored by Peter Steinberger
parent 8c292ccd7d
commit b42dc72851
2 changed files with 63 additions and 0 deletions
@@ -0,0 +1,62 @@
import type { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
import { describe, expect, it, vi } from "vitest";
import { fetchDiscordJson } from "./discord-api.js";
describe("Discord Activity API", () => {
it("cancels non-OK response bodies before releasing the dispatcher", async () => {
const lifecycle: string[] = [];
const response = new Response(
new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode("unauthorized"));
},
cancel() {
lifecycle.push("cancel");
},
}),
{ status: 401 },
);
const fetchGuard = vi.fn(async () => ({
response,
release: async () => {
lifecycle.push("release");
},
})) as unknown as typeof fetchWithSsrFGuard;
await expect(
fetchDiscordJson({
fetchGuard,
url: "https://discord.com/api/v10/users/@me",
init: { headers: { Authorization: "Bearer test-token" } },
auditContext: "discord.activities.oauth.user",
}),
).resolves.toEqual({ ok: false, status: 401 });
expect(lifecycle).toEqual(["cancel", "release"]);
});
it("preserves the HTTP status when response cancellation fails", async () => {
const response = new Response(
new ReadableStream({
cancel() {
throw new Error("cancel failed");
},
}),
{ status: 429 },
);
const release = vi.fn(async () => undefined);
const fetchGuard = vi.fn(async () => ({
response,
release,
})) as unknown as typeof fetchWithSsrFGuard;
await expect(
fetchDiscordJson({
fetchGuard,
url: "https://discord.com/api/v10/users/@me",
init: { headers: { Authorization: "Bearer test-token" } },
auditContext: "discord.activities.oauth.user",
}),
).resolves.toEqual({ ok: false, status: 429 });
expect(release).toHaveBeenCalledOnce();
});
});
@@ -43,6 +43,7 @@ export async function fetchDiscordJson(params: {
});
try {
if (!response.ok) {
await response.body?.cancel().catch(() => undefined);
return { ok: false, status: response.status };
}
return {