From 40b0b4d1e4ef1aa95d5e9011652444b855ab0b9c Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jun 2024 13:07:27 +0100 Subject: [PATCH] fix(rewrite): copy body from the request (#11182) * fix(rewrite): copy body from the request * wip * chore: copy body without using it * chore: remove new file --- .changeset/swift-phones-rhyme.md | 5 +++ packages/astro/src/core/render-context.ts | 34 +++++++++++++++++-- .../reroute/src/pages/post/post-a.astro | 8 +++++ .../reroute/src/pages/post/post-b.astro | 15 ++++++++ packages/astro/test/rewrite.test.js | 21 +++++++++++- 5 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 .changeset/swift-phones-rhyme.md create mode 100644 packages/astro/test/fixtures/reroute/src/pages/post/post-a.astro create mode 100644 packages/astro/test/fixtures/reroute/src/pages/post/post-b.astro diff --git a/.changeset/swift-phones-rhyme.md b/.changeset/swift-phones-rhyme.md new file mode 100644 index 0000000000..3675fac14d --- /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 32a3865dba..30b3c73192 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 0000000000..daa1fcb693 --- /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') +--- + +

Post A

+ +

{email}

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 0000000000..cfa2712f60 --- /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) + } +} +--- + +

Post B

+ +

{email}

diff --git a/packages/astro/test/rewrite.test.js b/packages/astro/test/rewrite.test.js index ef6a90e5dc..6f572eb915 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', () => {