From a5f7a5365dd17ea0b6f8184a410075ab9cf444cd Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Sat, 13 Jun 2026 23:28:51 -0700 Subject: [PATCH] fix(api): allow CORS PUT DELETE preflights --- src/api/routes.ts | 2 +- test/integration/api.test.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/api/routes.ts b/src/api/routes.ts index 68dfaba75f..a74f2b5bd2 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -629,7 +629,7 @@ export function createApp() { c.header("Access-Control-Allow-Origin", allowedOrigin); c.header("Access-Control-Allow-Credentials", "true"); c.header("Access-Control-Allow-Headers", "authorization, content-type, mcp-session-id, mcp-protocol-version"); - c.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + c.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); c.header("Access-Control-Expose-Headers", "x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, retry-after"); c.header("Access-Control-Max-Age", "600"); c.header("Vary", "Origin", { append: true }); diff --git a/test/integration/api.test.ts b/test/integration/api.test.ts index fdfee8ed67..3fdbb2266b 100644 --- a/test/integration/api.test.ts +++ b/test/integration/api.test.ts @@ -66,6 +66,15 @@ describe("api routes", () => { const preflight = await app.request("/v1/repos", { method: "OPTIONS", headers: { origin: "https://gittensory.aethereal.dev" } }, env); expect(preflight.status).toBe(204); expect(preflight.headers.get("access-control-allow-origin")).toBe("https://gittensory.aethereal.dev"); + expect(preflight.headers.get("access-control-allow-methods")).toBe("GET, POST, PUT, DELETE, OPTIONS"); + + const aiReviewPreflight = await app.request("/v1/repos/acme/widgets/ai-review", { method: "OPTIONS", headers: { origin: "https://gittensory.aethereal.dev", "access-control-request-method": "PUT" } }, env); + expect(aiReviewPreflight.status).toBe(204); + expect(aiReviewPreflight.headers.get("access-control-allow-methods")).toContain("PUT"); + + const aiKeyDeletePreflight = await app.request("/v1/repos/acme/widgets/ai-key", { method: "OPTIONS", headers: { origin: "https://gittensory.aethereal.dev", "access-control-request-method": "DELETE" } }, env); + expect(aiKeyDeletePreflight.status).toBe(204); + expect(aiKeyDeletePreflight.headers.get("access-control-allow-methods")).toContain("DELETE"); const dynamicOriginEnv = createTestEnv({ PUBLIC_SITE_ORIGIN: "https://preview.gittensory.test/app", PUBLIC_API_ORIGIN: "not a url" }); const dynamicPreflight = await app.request("/v1/repos", { method: "OPTIONS", headers: { origin: "https://preview.gittensory.test" } }, dynamicOriginEnv);