From ad3c30329b3633826be597ca63b69f9d51a8e1ea Mon Sep 17 00:00:00 2001 From: mktbsh Date: Sat, 14 Mar 2026 11:12:40 +0900 Subject: [PATCH 1/2] Fix fetch RequestInit override handling --- src/fetch.test.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/fetch.ts | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/fetch.test.ts b/src/fetch.test.ts index 919f788..933a5d6 100644 --- a/src/fetch.test.ts +++ b/src/fetch.test.ts @@ -21,6 +21,31 @@ describe("createFetchRequest", () => { expect(await clonedRequest.text()).toBe("hello"); }); + it("applies init overrides to Request inputs without consuming the original body", async () => { + const originalRequest = new Request("https://example.com/base", { + body: "original-body", + headers: { + "x-original": "1", + }, + method: "POST", + }); + + const request = createFetchRequest(originalRequest, { + body: "override-body", + headers: { + "x-override": "1", + }, + method: "PUT", + }); + + expect(request.method).toBe("PUT"); + expect(request.headers.get("x-original")).toBeNull(); + expect(request.headers.get("x-override")).toBe("1"); + expect(await request.text()).toBe("override-body"); + expect(originalRequest.bodyUsed).toBe(false); + expect(await originalRequest.text()).toBe("original-body"); + }); + it("creates a Request from fetch arguments", async () => { const request = createFetchRequest("https://example.com/from-args", { body: JSON.stringify({ hello: "world" }), @@ -35,6 +60,40 @@ describe("createFetchRequest", () => { }); describe("createFetchInterceptorHandler", () => { + it("matches against the effective Request when fetch receives Request and init", async () => { + const onIntercept = vi.fn(); + const originalFetch = vi.fn(async () => new Response("ok")); + const interceptedFetch = createFetchInterceptorHandler(originalFetch, { + matcher: (request) => request.method === "POST", + onIntercept, + }); + const baseRequest = new Request("https://example.com/base", { + headers: { + "x-original": "1", + }, + method: "PUT", + }); + + await interceptedFetch(baseRequest, { + body: "override-body", + headers: { + "x-override": "1", + }, + method: "POST", + }); + + expect(originalFetch).toHaveBeenCalledOnce(); + expect(onIntercept).toHaveBeenCalledOnce(); + + const [request] = onIntercept.mock.calls[0]; + + expect(request.method).toBe("POST"); + expect(request.headers.get("x-original")).toBeNull(); + expect(request.headers.get("x-override")).toBe("1"); + expect(await request.text()).toBe("override-body"); + expect(baseRequest.bodyUsed).toBe(false); + }); + it("intercepts matching requests with a cloned response", async () => { const onIntercept = vi.fn(); const originalFetch = vi.fn(async () => { diff --git a/src/fetch.ts b/src/fetch.ts index fa1e6e5..5739a8a 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -11,7 +11,7 @@ export function createFetchRequest( const [input, init] = args; if (input instanceof Request) { - return input.clone(); + return new Request(input.clone(), init); } return new Request(input, init); From aded3479bb66bd6237655cbb4f6609454e509981 Mon Sep 17 00:00:00 2001 From: mktbsh Date: Sat, 14 Mar 2026 11:12:49 +0900 Subject: [PATCH 2/2] Add changeset for fetch request override fix --- .changeset/effective-fetch-request.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/effective-fetch-request.md diff --git a/.changeset/effective-fetch-request.md b/.changeset/effective-fetch-request.md new file mode 100644 index 0000000..20be3a8 --- /dev/null +++ b/.changeset/effective-fetch-request.md @@ -0,0 +1,5 @@ +--- +"@hsblabs/fetch-interceptor": patch +--- + +Preserve `RequestInit` overrides when intercepting `fetch(request, init)` calls.