diff --git a/src/proxy.ts b/src/proxy.ts index ec17d7c..d29f90b 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -54,9 +54,11 @@ export async function handleProxy(targetUrl: string, request: Request): Promise< let targetResponse: Response; try { + const hasBody = request.method !== "GET" && request.method !== "HEAD"; targetResponse = await fetch(targetUrl, { method: request.method, headers: forwardHeaders(request), + body: hasBody ? request.body : undefined, redirect: "manual", }); } catch { diff --git a/src/rewriter.test.ts b/src/rewriter.test.ts index 30f1f90..0ed5b62 100644 --- a/src/rewriter.test.ts +++ b/src/rewriter.test.ts @@ -138,4 +138,20 @@ describe("HTMLRewriter integration", () => { const allProxied = dataSrcMatches.every((m) => m.includes("/browse/")); expect(allProxied).toBe(true); }); + + it("forwards POST body and content-type header", async () => { + const resp = await worker.fetch("/browse/https://httpbin.org/post", { + method: "POST", + headers: { "content-type": "application/x-www-form-urlencoded" }, + body: "query=test&page=1", + }); + if (resp.status !== 200) return; + const data = (await resp.json()) as { + form: Record; + headers: Record; + }; + expect(data.form.query).toBe("test"); + expect(data.form.page).toBe("1"); + expect(data.headers["Content-Type"]).toContain("application/x-www-form-urlencoded"); + }); }); diff --git a/src/utils.ts b/src/utils.ts index 783cb9d..a7f1352 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -64,7 +64,15 @@ export function stripHeaders(headers: Headers): Headers { export function forwardHeaders(request: Request): HeadersInit { const forwarded: Record = {}; - const pass = ["user-agent", "accept", "accept-language", "accept-encoding", "cookie", "referer"]; + const pass = [ + "user-agent", + "accept", + "accept-language", + "accept-encoding", + "cookie", + "referer", + "content-type", + ]; pass.forEach((h) => { const v = request.headers.get(h); if (v) forwarded[h] = v;