summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Elliot Dong <dong_yu_hang@126.com> 2025-06-04 17:23:41 +0800
committerGravatar GitHub <noreply@github.com> 2025-06-04 10:23:41 +0100
commit5a7797fdd6ad3f1377e2719c79da9486a232dfcd (patch)
tree5555de427ecae86937b38a62be4fc8d120e053c1
parent66b5edb1c3bef74aac3d372d302edc98183725dd (diff)
downloadastro-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>
-rw-r--r--.changeset/real-mice-joke.md5
-rw-r--r--packages/astro/src/core/middleware/sequence.ts6
-rw-r--r--packages/astro/test/fixtures/middleware-sequence-request-clone/astro.config.mjs8
-rw-r--r--packages/astro/test/fixtures/middleware-sequence-request-clone/package.json8
-rw-r--r--packages/astro/test/fixtures/middleware-sequence-request-clone/src/middleware.js15
-rw-r--r--packages/astro/test/fixtures/middleware-sequence-request-clone/src/pages/index.astro1
-rw-r--r--packages/astro/test/middleware.test.js26
-rw-r--r--pnpm-lock.yaml6
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: