From f59d6d1478e7b8fb31dc8c01a284371edc9b3ee1 Mon Sep 17 00:00:00 2001 From: mptyl Date: Sun, 28 Jun 2026 16:54:30 +0200 Subject: [PATCH] fix(backend): allow PUT in CORS methods so browser can save settings Found via live browser test: PUT /settings preflight was rejected because @fastify/cors default methods omit PUT. GET/POST were unaffected. Co-Authored-By: Claude Opus 4.8 --- backend/src/app.ts | 6 +++++- backend/test/routes-settings.test.ts | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/src/app.ts b/backend/src/app.ts index 94fafc48..ca3b1762 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -23,7 +23,11 @@ export function buildApp(config: AppConfig, deps?: BuildAppDeps): FastifyInstanc const app = Fastify({ logger: false }); // Allow any origin in dev/e2e; tighten in production via config if needed. - app.register(cors, { origin: true, credentials: true }); + app.register(cors, { + origin: true, + credentials: true, + methods: ["GET", "POST", "PUT", "OPTIONS"], + }); const tht = deps?.thtRunner ?? new ThtRunner({ thtBin: config.thtBin, diff --git a/backend/test/routes-settings.test.ts b/backend/test/routes-settings.test.ts index 2103dd9c..2265f4dc 100644 --- a/backend/test/routes-settings.test.ts +++ b/backend/test/routes-settings.test.ts @@ -76,3 +76,20 @@ test("PUT /settings allows any model when model list is empty (Pi unavailable)", rmSync(dir, { recursive: true, force: true }); } }); + +test("CORS preflight allows PUT /settings (browser can save settings)", async () => { + const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), { + thtRunner: {} as any, + listModels: async () => [], + }); + const res = await app.inject({ + method: "OPTIONS", + url: "/settings", + headers: { + origin: "http://localhost:5173", + "access-control-request-method": "PUT", + }, + }); + // @fastify/cors answers the preflight; PUT must be in the allowed methods. + expect(res.headers["access-control-allow-methods"]).toMatch(/PUT/); +});