diff --git a/packages/void/src/router/compile.ts b/packages/void/src/router/compile.ts index 08334e3f4..38addef26 100644 --- a/packages/void/src/router/compile.ts +++ b/packages/void/src/router/compile.ts @@ -1132,7 +1132,7 @@ export function compileWorkerEntry( const assetHelper = ` async function serveWithAssets(request, env, response) { if (response.status !== 404 || !env.ASSETS || (request.method !== "GET" && request.method !== "HEAD")) return response; - const asset = await env.ASSETS.fetch(request); + const asset = await env.ASSETS.fetch(new Request(request.url, { method: request.method, headers: request.headers })); if (asset.status === 404) return response; const res = new Response(asset.body, asset); if (new URL(request.url).pathname.startsWith(${JSON.stringify("/" + assetsDir + "/")})) { diff --git a/packages/void/test/unit/compile.test.ts b/packages/void/test/unit/compile.test.ts index a6afe1639..25778e395 100644 --- a/packages/void/test/unit/compile.test.ts +++ b/packages/void/test/unit/compile.test.ts @@ -400,6 +400,26 @@ describe("compileWorkerEntry", () => { expect(code).not.toContain("cache.put"); }); + it("serveWithAssets skips non-GET/HEAD requests to avoid body-reuse crash", () => { + const code = compileWorkerEntry(); + + // Must guard against POST/PUT/etc — their body is consumed by app.fetch() + // and passing the original request to env.ASSETS.fetch() would throw + // "Cannot reconstruct a Request with a used body" + expect(code).toContain('request.method !== "GET" && request.method !== "HEAD"'); + }); + + it("serveWithAssets creates a fresh Request for ASSETS.fetch to avoid body-reuse", () => { + const code = compileWorkerEntry(); + + // Must not pass the original request to env.ASSETS.fetch() because + // app.fetch() may have marked it as disturbed. Use new Request(url) instead. + expect(code).toContain( + "env.ASSETS.fetch(new Request(request.url, { method: request.method, headers: request.headers }))", + ); + expect(code).not.toMatch(/env\.ASSETS\.fetch\(request\)/); + }); + it("uses custom assetsDir in serveWithAssets path check", () => { const code = compileWorkerEntry(false, undefined, "_astro");