Skip to content

Commit

Permalink
fix: throw error if rewrite is attempted after body is used (#11258)
Browse files Browse the repository at this point in the history
* fix: throw error if rewrite is attempted after body is used

* Apply suggestions from code review

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

---------

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
  • Loading branch information
ascorbic and sarah11918 authored Jun 14, 2024
1 parent 537e971 commit d996db6
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/healthy-oranges-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Adds a new error `RewriteWithBodyUsed` that throws when `Astro.rewrite` is used after the request body has already been read.
23 changes: 23 additions & 0 deletions packages/astro/src/core/errors/errors-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,29 @@ export const ServerOnlyModule = {
message: (name: string) => `The "${name}" module is only available server-side.`,
} satisfies ErrorData;


/**
* @docs
* @description
* `Astro.rewrite()` cannot be used if the request body has already been read. If you need to read the body, first clone the request. For example:
*
* ```js
* const data = await Astro.request.clone().formData();
*
* Astro.rewrite("/target")
* ```
*
* @see
* - [Request.clone()](https://developer.mozilla.org/en-US/docs/Web/API/Request/clone)
* - [Astro.rewrite](https://docs.astro.build/en/reference/configuration-reference/#experimentalrewriting)
*/

export const RewriteWithBodyUsed = {
name: 'RewriteWithBodyUsed',
title: 'Cannot use Astro.rewrite after the request body has been read',
message: 'Astro.rewrite() cannot be used if the request body has already been read. If you need to read the body, first clone the request.',
} satisfies ErrorData;

/**
* @docs
* @kind heading
Expand Down
3 changes: 3 additions & 0 deletions packages/astro/src/core/render-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ export class RenderContext {
* @param oldRequest The old `Request`
*/
#copyRequest(newUrl: URL, oldRequest: Request): Request {
if(oldRequest.bodyUsed) {
throw new AstroError(AstroErrorData.RewriteWithBodyUsed);
}
return new Request(newUrl, {
method: oldRequest.method,
headers: oldRequest.headers,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
---

<form method="post" action="/post/post-body-used">
<input type="text" name="email" value="example@example.com" />
<input type="submit" />
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
let email = ''
if (Astro.request.method === 'POST') {
try {
const data = await Astro.request.formData();
email = data.get('email');
} catch (e) {
console.log(e)
}
}
---

<h1>Post B</h1>

<h2>{email}</h2>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
let data
if (Astro.request.method === 'POST') {
try {
data = await Astro.request.text();
} catch (e) {
console.log(e)
}
}
return Astro.rewrite('/post/post-b')
---

<h1>Post body used</h1>

<h2>{data}</h2>
27 changes: 27 additions & 0 deletions packages/astro/test/rewrite.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ describe('Dev rewrite, hybrid/server', () => {
assert.match($('h1').text(), /Title/);
assert.match($('p').text(), /some-slug/);
});

it('should display an error if a rewrite is attempted after the body has been consumed', async () => {
const formData = new FormData();
formData.append('email', 'example@example.com');

const request = new Request('http://example.com/post/post-body-used', {
method: 'POST',
body: formData,
});
const response = await fixture.fetch('/post/post-body-used', request);
const html = await response.text();
const $ = cheerioLoad(html);

assert.equal($('title').text(), 'RewriteWithBodyUsed');
});
});

describe('Build reroute', () => {
Expand Down Expand Up @@ -272,6 +287,18 @@ describe('SSR rewrite, hybrid/server', () => {
assert.match($('h1').text(), /Title/);
assert.match($('p').text(), /some-slug/);
});

it('should return a 500 if a rewrite is attempted after the body has been read', async () => {
const formData = new FormData();
formData.append('email', 'example@example.com');

const request = new Request('http://example.com/post/post-body-used', {
method: 'POST',
body: formData,
});
const response = await app.render(request);
assert.equal(response.status, 500);
});
});

describe('Middleware', () => {
Expand Down

0 comments on commit d996db6

Please sign in to comment.