Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch {

if (context.options.onRequest) {
await callHooks(context, context.options.onRequest);
// A hook may reassign `headers` to a plain object or array (a valid
// `HeadersInit`), so normalize it back to a `Headers` instance before the
// code below calls `.get()`/`.set()`/`.has()` on it.
if (!(context.options.headers instanceof Headers)) {
context.options.headers = new Headers(context.options.headers || {});
}
}

if (typeof context.request === "string") {
Expand Down Expand Up @@ -143,8 +149,6 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch {

// Set Content-Type and Accept headers to application/json by default
// for JSON serializable request bodies.
// Pass empty object as older browsers don't support undefined.
context.options.headers = new Headers(context.options.headers || {});
if (!contentType) {
context.options.headers.set("content-type", "application/json");
}
Expand Down
26 changes: 26 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,32 @@ describe("ofetch", () => {
).toMatchObject({ foo: "2", bar: "3" });
});

it("normalizes headers reassigned in onRequest hook", async () => {
// A `Headers` instance reassigned in the hook is sent as-is.
expect(
await $fetch(getURL("/echo"), {
method: "POST",
body: { num: 42 },
onRequest(ctx) {
ctx.options.headers = new Headers({ "x-foo": "bar" });
},
}).then((r) => r.headers)
).toMatchObject({ "x-foo": "bar" });

// A plain object reassigned in the hook is normalized back to `Headers`
// instead of throwing `headers.get is not a function` before the request.
expect(
await $fetch(getURL("/echo"), {
method: "POST",
body: { num: 42 },
onRequest(ctx) {
// @ts-expect-error backwards compatibility for object headers
ctx.options.headers = { "x-foo": "bar" };
},
}).then((r) => r.headers)
).toMatchObject({ "x-foo": "bar" });
});

it("hook errors", async () => {
// onRequest
await expect(
Expand Down