diff --git a/packages/better-fetch/src/test/fetch.test.ts b/packages/better-fetch/src/test/fetch.test.ts index 83a08da..5043b48 100644 --- a/packages/better-fetch/src/test/fetch.test.ts +++ b/packages/better-fetch/src/test/fetch.test.ts @@ -114,6 +114,18 @@ describe("fetch", () => { expect(data?.body).to.deep.eq(message); }); + it("stringifies body when content-type is explicitly application/json", async () => { + const payload = { foo: "bar" }; + const { data } = await $echo("/echo", { + method: "POST", + body: payload, + headers: { "Content-Type": "application/json" }, + }); + + expect(data?.body).toEqual(payload); + expect(data?.headers).to.include({ "content-type": "application/json" }); + }); + it("Bypass URLSearchParams body", async () => { const data = new URLSearchParams({ foo: "bar" }); const { data: res } = await betterFetch(getURL("post"), { diff --git a/packages/better-fetch/src/utils.ts b/packages/better-fetch/src/utils.ts index fb05686..26eb2b1 100644 --- a/packages/better-fetch/src/utils.ts +++ b/packages/better-fetch/src/utils.ts @@ -212,19 +212,27 @@ export function getBody(options?: BetterFetchOption) { if (!options?.body) { return null; } - - let hasContentType = false; + let contentType: string | undefined = undefined; if (options?.headers) { if (options.headers instanceof Headers) { - hasContentType = options.headers.has("content-type"); + contentType = options.headers.get("content-type") ?? undefined; } else if (typeof options.headers === "object") { - hasContentType = "content-type" in options.headers && - options.headers["content-type"] !== null && - options.headers["content-type"] !== undefined; + if ( + "content-type" in options.headers && + options.headers["content-type"] !== null && + options.headers["content-type"] !== undefined + ) { + contentType = options.headers["content-type"]; + } } } - - if (isJSONSerializable(options.body) && !hasContentType) { + + const hasContentType = contentType !== undefined; + const isJSONContentType = contentType !== undefined && JSON_RE.test(contentType); + if ( + isJSONSerializable(options.body) && + (!hasContentType || isJSONContentType) + ) { for (const [key, value] of Object.entries(options?.body)) { if (value instanceof Date) { options.body[key] = value.toISOString();