Skip to content
Merged
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
2 changes: 1 addition & 1 deletion packages/void/src/router/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 + "/")})) {
Expand Down
20 changes: 20 additions & 0 deletions packages/void/test/unit/compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
Loading