From b033c3324f2ea488ee87c3d628f5430e656d52aa Mon Sep 17 00:00:00 2001 From: Shirish Kamath Date: Sat, 17 Feb 2024 12:26:59 +0530 Subject: [PATCH 1/3] Unset Content-Type for FormData as request body before Request() const. call. Fixes #1548 content-type header with multipart boundary set by Request() is retained --- packages/openapi-fetch/src/index.js | 8 ++++---- packages/openapi-fetch/test/index.test.ts | 4 +--- packages/openapi-fetch/test/v7-beta.test.ts | 4 +--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/openapi-fetch/src/index.js b/packages/openapi-fetch/src/index.js index c2d5b7e24..b9a1bcc37 100644 --- a/packages/openapi-fetch/src/index.js +++ b/packages/openapi-fetch/src/index.js @@ -65,14 +65,14 @@ export default function createClient(clientOptions) { if (requestInit.body) { requestInit.body = bodySerializer(requestInit.body); } + // remove `Content-Type` if serialized body is FormData; browser will correctly set Content-Type & boundary expression + if (requestInit.body instanceof FormData) { + requestInit.headers.delete("Content-Type"); + } let request = new Request( createFinalURL(url, { baseUrl, params, querySerializer }), requestInit, ); - // remove `Content-Type` if serialized body is FormData; browser will correctly set Content-Type & boundary expression - if (requestInit.body instanceof FormData) { - request.headers.delete("Content-Type"); - } // middleware (request) const mergedOptions = { baseUrl, diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 9d8c27f5c..9fa10e5d8 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -937,9 +937,7 @@ describe("client", () => { const req = fetchMocker.mock.calls[0][0]; // note: this is FormData, but Node.js doesn’t handle new Request() properly with formData bodies. So this is only in tests. expect(req.body).toBeInstanceOf(Buffer); - - // TODO: `vitest-fetch-mock` does not add the boundary to the Content-Type header like browsers do, so we expect the header to be null instead - expect(req.headers.get("Content-Type")).toBeNull(); + expect((req.headers as Headers).get("Content-Type")).toBe("text/plain;charset=UTF-8"); }); // Node Requests eat credentials (no cookies), but this works in frontend diff --git a/packages/openapi-fetch/test/v7-beta.test.ts b/packages/openapi-fetch/test/v7-beta.test.ts index 06a96489b..3e3ad7520 100644 --- a/packages/openapi-fetch/test/v7-beta.test.ts +++ b/packages/openapi-fetch/test/v7-beta.test.ts @@ -946,9 +946,7 @@ describe("client", () => { const req = fetchMocker.mock.calls[0][0]; // note: this is FormData, but Node.js doesn’t handle new Request() properly with formData bodies. So this is only in tests. expect(req.body).toBeInstanceOf(Buffer); - - // TODO: `vitest-fetch-mock` does not add the boundary to the Content-Type header like browsers do, so we expect the header to be null instead - expect((req.headers as Headers).get("Content-Type")).toBeNull(); + expect((req.headers as Headers).get("Content-Type")).toBe("text/plain;charset=UTF-8"); }); // Node Requests eat credentials (no cookies), but this works in frontend From b5183e9114f87d5fa8bbe131e584046b61ebb4fe Mon Sep 17 00:00:00 2001 From: Shirish Kamath Date: Sat, 17 Feb 2024 21:26:05 +0530 Subject: [PATCH 2/3] Added changeset --- .changeset/nasty-squids-collect.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/nasty-squids-collect.md diff --git a/.changeset/nasty-squids-collect.md b/.changeset/nasty-squids-collect.md new file mode 100644 index 000000000..1a85c0057 --- /dev/null +++ b/.changeset/nasty-squids-collect.md @@ -0,0 +1,5 @@ +--- +"openapi-fetch": patch +--- + +Fix 'Content-Type' header being removed from requests with multipart/form-data body From 40ddad6c48785741bf01a53e4c56e4d1239b5762 Mon Sep 17 00:00:00 2001 From: Shirish Kamath Date: Sun, 18 Feb 2024 09:49:56 +0530 Subject: [PATCH 3/3] Fix lint:prettier errors --- packages/openapi-fetch/test/index.test.ts | 4 +++- packages/openapi-fetch/test/v7-beta.test.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 9fa10e5d8..5fe7506b3 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -937,7 +937,9 @@ describe("client", () => { const req = fetchMocker.mock.calls[0][0]; // note: this is FormData, but Node.js doesn’t handle new Request() properly with formData bodies. So this is only in tests. expect(req.body).toBeInstanceOf(Buffer); - expect((req.headers as Headers).get("Content-Type")).toBe("text/plain;charset=UTF-8"); + expect((req.headers as Headers).get("Content-Type")).toBe( + "text/plain;charset=UTF-8", + ); }); // Node Requests eat credentials (no cookies), but this works in frontend diff --git a/packages/openapi-fetch/test/v7-beta.test.ts b/packages/openapi-fetch/test/v7-beta.test.ts index 3e3ad7520..7900dc30b 100644 --- a/packages/openapi-fetch/test/v7-beta.test.ts +++ b/packages/openapi-fetch/test/v7-beta.test.ts @@ -946,7 +946,9 @@ describe("client", () => { const req = fetchMocker.mock.calls[0][0]; // note: this is FormData, but Node.js doesn’t handle new Request() properly with formData bodies. So this is only in tests. expect(req.body).toBeInstanceOf(Buffer); - expect((req.headers as Headers).get("Content-Type")).toBe("text/plain;charset=UTF-8"); + expect((req.headers as Headers).get("Content-Type")).toBe( + "text/plain;charset=UTF-8", + ); }); // Node Requests eat credentials (no cookies), but this works in frontend