Skip to content

Commit 0058128

Browse files
authored
Encode the request body if Content-Type set (#2096)
1 parent 63b715e commit 0058128

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

docs/openapi-fetch/api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,22 @@ or when instantiating the client.
192192

193193
:::
194194

195+
### URL-encoded body
196+
197+
To send a body request in `application/x-www-form-urlencoded` format, which is commonly used to transmit key-value pairs in APIs like OAuth 2.0, pass the appropriate header and body as an object. `openapi-fetch` will automatically encode the body to the correct format.
198+
199+
```ts
200+
const { data, error } = await client.POST("/tokens", {
201+
body: {
202+
clientId: "someClientId",
203+
clientSecret: "someClientSecret",
204+
},
205+
headers: {
206+
"Content-Type": "application/x-www-form-encoded",
207+
},
208+
});
209+
```
210+
195211
## Path serialization
196212

197213
openapi-fetch supports path serialization as [outlined in the 3.1 spec](https://swagger.io/docs/specification/serialization/#path). This happens automatically, based on the specific format in your OpenAPI schema:

packages/openapi-fetch/src/index.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default function createClient(clientOptions) {
7373
});
7474
}
7575

76-
const serializedBody = body === undefined ? undefined : bodySerializer(body);
76+
const serializedBody = body === undefined ? undefined : bodySerializer(body, headers);
7777

7878
const defaultHeaders =
7979
// with no body, we should not to set Content-Type
@@ -578,10 +578,19 @@ export function defaultPathSerializer(pathname, pathParams) {
578578
* Serialize body object to string
579579
* @type {import("./index.js").defaultBodySerializer}
580580
*/
581-
export function defaultBodySerializer(body) {
581+
export function defaultBodySerializer(body, headers) {
582582
if (body instanceof FormData) {
583583
return body;
584584
}
585+
if (headers) {
586+
const contentType =
587+
headers.get instanceof Function
588+
? (headers.get("Content-Type") ?? headers.get("content-type"))
589+
: (headers["Content-Type"] ?? headers["content-type"]);
590+
if (contentType === "application/x-www-form-urlencoded") {
591+
return new URLSearchParams(body).toString();
592+
}
593+
}
585594
return JSON.stringify(body);
586595
}
587596

packages/openapi-fetch/test/common/request.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,19 @@ describe("request", () => {
265265
expect(bodyUsed).toBe(true);
266266
expect(bodyText).toBe("0");
267267
});
268+
269+
test("`application/x-www-form-urlencoded` body", async () => {
270+
const { bodyUsed, bodyText } = await fireRequestAndGetBodyInformation({
271+
method: "POST",
272+
fetchOptions: {
273+
body: { key1: "value1", key2: "value2" },
274+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
275+
},
276+
});
277+
278+
expect(bodyUsed).toBe(true);
279+
expect(bodyText).toBe("key1=value1&key2=value2");
280+
});
268281
});
269282

270283
test("cookie header is preserved", async () => {

0 commit comments

Comments
 (0)