diff --git a/.changeset/swift-phones-rhyme.md b/.changeset/swift-phones-rhyme.md
new file mode 100644
index 000000000000..3675fac14df6
--- /dev/null
+++ b/.changeset/swift-phones-rhyme.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes an issue where `Astro.rewrite` wasn't carrying over the body of a `Request` in on-demand pages.
diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts
index 32a3865dba8c..30b3c7319257 100644
--- a/packages/astro/src/core/render-context.ts
+++ b/packages/astro/src/core/render-context.ts
@@ -224,7 +224,7 @@ export class RenderContext {
 				if (reroutePayload instanceof Request) {
 					this.request = reroutePayload;
 				} else {
-					this.request = new Request(
+					this.request = this.#copyRequest(
 						new URL(routeData.pathname ?? routeData.route, this.url.origin),
 						this.request
 					);
@@ -416,7 +416,7 @@ export class RenderContext {
 				if (reroutePayload instanceof Request) {
 					this.request = reroutePayload;
 				} else {
-					this.request = new Request(
+					this.request = this.#copyRequest(
 						new URL(routeData.pathname ?? routeData.route, this.url.origin),
 						this.request
 					);
@@ -533,4 +533,34 @@ export class RenderContext {
 		if (!i18n) return;
 		return (this.#preferredLocaleList ??= computePreferredLocaleList(request, i18n.locales));
 	}
+
+	/**
+	 * Utility function that creates a new `Request` with a new URL from an old `Request`.
+	 *
+	 * @param newUrl The new `URL`
+	 * @param oldRequest The old `Request`
+	 */
+	#copyRequest(newUrl: URL, oldRequest: Request): Request {
+		return new Request(newUrl, {
+			method: oldRequest.method,
+			headers: oldRequest.headers,
+			body: oldRequest.body,
+			referrer: oldRequest.referrer,
+			referrerPolicy: oldRequest.referrerPolicy,
+			mode: oldRequest.mode,
+			credentials: oldRequest.credentials,
+			cache: oldRequest.cache,
+			redirect: oldRequest.redirect,
+			integrity: oldRequest.integrity,
+			signal: oldRequest.signal,
+			keepalive: oldRequest.keepalive,
+			// https://fetch.spec.whatwg.org/#dom-request-duplex
+			// @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request
+			duplex: "half"
+		})
+	}
+
 }
+
+
+
diff --git a/packages/astro/test/fixtures/reroute/src/pages/post/post-a.astro b/packages/astro/test/fixtures/reroute/src/pages/post/post-a.astro
new file mode 100644
index 000000000000..daa1fcb693d1
--- /dev/null
+++ b/packages/astro/test/fixtures/reroute/src/pages/post/post-a.astro
@@ -0,0 +1,8 @@
+---
+let email = ''
+return Astro.rewrite('/post/post-b')
+---
+
+<h1>Post A</h1>
+
+<h2>{email}</h2>
diff --git a/packages/astro/test/fixtures/reroute/src/pages/post/post-b.astro b/packages/astro/test/fixtures/reroute/src/pages/post/post-b.astro
new file mode 100644
index 000000000000..cfa2712f600b
--- /dev/null
+++ b/packages/astro/test/fixtures/reroute/src/pages/post/post-b.astro
@@ -0,0 +1,15 @@
+---
+let email = ''
+if (Astro.request.method === 'POST') {
+	try {
+		const data = await Astro.request.json();
+		email = data.email?.toString().trim();
+	} catch (e) {
+		console.log(e)
+	}
+}
+---
+
+<h1>Post B</h1>
+
+<h2>{email}</h2>
diff --git a/packages/astro/test/rewrite.test.js b/packages/astro/test/rewrite.test.js
index ef6a90e5dcc0..6f572eb915e2 100644
--- a/packages/astro/test/rewrite.test.js
+++ b/packages/astro/test/rewrite.test.js
@@ -61,6 +61,7 @@ describe('Dev reroute', () => {
 
 		assert.equal($('h1').text(), '404:  Not found');
 	});
+	
 });
 
 describe('Build reroute', () => {
@@ -112,7 +113,7 @@ describe('Build reroute', () => {
 
 	it('should render the 404 built-in page', async () => {
 		try {
-			const html = await fixture.readFile('/spread/oops/index.html');
+			await fixture.readFile('/spread/oops/index.html');
 			assert.fail('Not found');
 		} catch {
 			assert.ok;
@@ -187,6 +188,24 @@ describe('SSR reroute', () => {
 		const html = await response.text();
 		assert.equal(html, 'Not found');
 	});
+
+	it('should pass the POST data from one page to another', async () => {
+		const request = new Request('http://example.com/post/post-a', {
+			method: "POST",
+			body: JSON.stringify({
+				email: "example@example.com",
+			}),
+			headers: {
+				"content-type": "application/json"
+			}
+		});
+		const response = await app.render(request);
+		const html = await response.text();
+		const $ = cheerioLoad(html);
+
+		assert.equal($('h1').text(), 'Post B');
+		assert.match($('h2').text(), /example@example.com/);
+	});
 });
 
 describe('Middleware', () => {