diff options
author | 2025-06-04 17:23:41 +0800 | |
---|---|---|
committer | 2025-06-04 10:23:41 +0100 | |
commit | 5a7797fdd6ad3f1377e2719c79da9486a232dfcd (patch) | |
tree | 5555de427ecae86937b38a62be4fc8d120e053c1 | |
parent | 66b5edb1c3bef74aac3d372d302edc98183725dd (diff) | |
download | astro-5a7797fdd6ad3f1377e2719c79da9486a232dfcd.tar.gz astro-5a7797fdd6ad3f1377e2719c79da9486a232dfcd.tar.zst astro-5a7797fdd6ad3f1377e2719c79da9486a232dfcd.zip |
fix: request should be properly cloned first then copy to modified in middleware (#13877)
* fix: Cloneing request in middleware would cause RewriteWithBodyUsed error
* fix test case
* commit changeset
* fix: lock file
* Apply suggestions from code review
---------
Co-authored-by: Matt Kane <m@mk.gg>
8 files changed, 73 insertions, 2 deletions
diff --git a/.changeset/real-mice-joke.md b/.changeset/real-mice-joke.md new file mode 100644 index 000000000..43af36d7e --- /dev/null +++ b/.changeset/real-mice-joke.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes a bug that caused `Astro.rewrite` to fail when used in `sequence`d middleware diff --git a/packages/astro/src/core/middleware/sequence.ts b/packages/astro/src/core/middleware/sequence.ts index 341b8c1e7..8d7513ba0 100644 --- a/packages/astro/src/core/middleware/sequence.ts +++ b/packages/astro/src/core/middleware/sequence.ts @@ -40,11 +40,13 @@ export function sequence(...handlers: MiddlewareHandler[]): MiddlewareHandler { if (payload instanceof Request) { newRequest = payload; } else if (payload instanceof URL) { - newRequest = new Request(payload, handleContext.request); + // Cloning the original request ensures that the new Request gets its own copy of the body stream + // Without this it will throw an error if they both try to consume the stream, which will happen in a rewrite + newRequest = new Request(payload, handleContext.request.clone()); } else { newRequest = new Request( new URL(payload, handleContext.url.origin), - handleContext.request, + handleContext.request.clone(), ); } const oldPathname = handleContext.url.pathname; diff --git a/packages/astro/test/fixtures/middleware-sequence-request-clone/astro.config.mjs b/packages/astro/test/fixtures/middleware-sequence-request-clone/astro.config.mjs new file mode 100644 index 000000000..0c1b887d0 --- /dev/null +++ b/packages/astro/test/fixtures/middleware-sequence-request-clone/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + vite: { + plugins: [], + } +}); diff --git a/packages/astro/test/fixtures/middleware-sequence-request-clone/package.json b/packages/astro/test/fixtures/middleware-sequence-request-clone/package.json new file mode 100644 index 000000000..f9aacd4d7 --- /dev/null +++ b/packages/astro/test/fixtures/middleware-sequence-request-clone/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/middleware-sequence-request-clone", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/middleware-sequence-request-clone/src/middleware.js b/packages/astro/test/fixtures/middleware-sequence-request-clone/src/middleware.js new file mode 100644 index 000000000..a7f0498f9 --- /dev/null +++ b/packages/astro/test/fixtures/middleware-sequence-request-clone/src/middleware.js @@ -0,0 +1,15 @@ +import { sequence, defineMiddleware } from 'astro/middleware'; + +const middleware1 = defineMiddleware((_, next) => next('/')); + +const middleware2 = defineMiddleware(async ({ request }, next) => { + console.log(await request.clone().text()); + return next(); +}); + +const middleware3 = defineMiddleware(async ({ request }, next) => { + await request.clone(); + return next(); +}); + +export const onRequest = sequence(middleware1, middleware2, middleware3);
\ No newline at end of file diff --git a/packages/astro/test/fixtures/middleware-sequence-request-clone/src/pages/index.astro b/packages/astro/test/fixtures/middleware-sequence-request-clone/src/pages/index.astro new file mode 100644 index 000000000..8dbcc65c4 --- /dev/null +++ b/packages/astro/test/fixtures/middleware-sequence-request-clone/src/pages/index.astro @@ -0,0 +1 @@ +<h1>Hello Sequence and Request Clone</h1>
\ No newline at end of file diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js index 199128ebd..1400ae668 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.test.js @@ -388,3 +388,29 @@ describe('Middleware with tailwind', () => { assert.equal(bundledCSS.includes('--tw'), true); }); }); + +describe('Middleware should support clone request', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + let devServer; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/middleware-sequence-request-clone/', + }); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('should correctly render page', async () => { + const res = await fixture.fetch('/', { + method: 'POST', + body: 'TEST BODY' + }); + const html = await res.text(); + assert.equal(html.includes('Hello Sequence and Request Clone'), true); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8c5fd637..8abea2875 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3411,6 +3411,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/middleware-sequence-request-clone: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/middleware-ssg: dependencies: astro: |