fix(frontend): only send JSON content-type when a body is present
Body-less POSTs (resume, close) sent content-type: application/json with no body, so Fastify rejected them with FST_ERR_CTP_EMPTY_JSON_BODY (400) and clicking an existing session never reopened it. apiFetch now adds the header only when init.body is set. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { http, HttpResponse } from "msw";
|
||||
import { server } from "../test/msw";
|
||||
import { apiFetch } from "./client";
|
||||
|
||||
test("body-less POST omits content-type (avoids Fastify empty-body 400)", async () => {
|
||||
let contentType: string | null = "unset";
|
||||
server.use(
|
||||
http.post("http://localhost:8787/sessions/s1/resume", ({ request }) => {
|
||||
contentType = request.headers.get("content-type");
|
||||
return HttpResponse.json({ id: "s1" });
|
||||
}),
|
||||
);
|
||||
await apiFetch("/sessions/s1/resume", { method: "POST" });
|
||||
expect(contentType).toBeNull();
|
||||
});
|
||||
|
||||
test("POST with a body sends application/json content-type", async () => {
|
||||
let contentType: string | null = null;
|
||||
server.use(
|
||||
http.post("http://localhost:8787/sessions/s1/steer", ({ request }) => {
|
||||
contentType = request.headers.get("content-type");
|
||||
return new HttpResponse(null, { status: 204 });
|
||||
}),
|
||||
);
|
||||
await apiFetch("/sessions/s1/steer", { method: "POST", body: JSON.stringify({ text: "hi" }) });
|
||||
expect(contentType).toContain("application/json");
|
||||
});
|
||||
@@ -1,10 +1,16 @@
|
||||
const BASE = import.meta.env.VITE_BACKEND_URL ?? "http://localhost:8787";
|
||||
|
||||
export async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
headers: { "content-type": "application/json" },
|
||||
...init,
|
||||
});
|
||||
// Only declare a JSON content-type when we actually send a body. Body-less
|
||||
// POSTs (resume, close) would otherwise make Fastify reject the empty body
|
||||
// with FST_ERR_CTP_EMPTY_JSON_BODY (400).
|
||||
const headers: Record<string, string> = {
|
||||
...(init?.headers as Record<string, string> | undefined),
|
||||
};
|
||||
if (init?.body != null && !("content-type" in headers) && !("Content-Type" in headers)) {
|
||||
headers["content-type"] = "application/json";
|
||||
}
|
||||
const res = await fetch(`${BASE}${path}`, { ...init, headers });
|
||||
if (!res.ok) throw new Error(`${res.status} ${await res.text().catch(() => "")}`);
|
||||
return res.status === 204 ? (undefined as T) : ((await res.json()) as T);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user