withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.8k stars 2.49k forks source link

Experimental rewriting of POST request does not work (reopened) #11247

Closed gersomvg closed 5 months ago

gersomvg commented 5 months ago

Astro Info

Astro                    v4.10.2
Node                     v20.12.2
System                   macOS (arm64)
Package Manager          pnpm
Output                   server
Adapter                  @astrojs/node
Integrations             @astrojs/tailwind

If this issue only occurs in one browser, which browser is a problem?

Not specific to a browser

Describe the Bug

Duplicate of this previous issue that I can't reopen: https://github.com/withastro/astro/issues/11127

It is supposed to be fixed in Astro 4.10 but the exact same stackblitz repro still doesn't work.

I get the error Response body object should not be disturbed or locked

What's the expected result?

I'd expect /page-b to render and receive the email field in FormData

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-oyssmw?file=src%2Fpages%2Findex.astro

ascorbic commented 5 months ago

The issue here is that even though the body is copied, you have already read it. When you call request.formData() it consumes the body, so when you try to rewrite it it can't read the body again. The fix is to change the code to: const data = await Astro.request.clone().formData(), so the original request body is not disturbed. This is what Astro Actions do. I'm not sure if this is something that Astro should do automatically for everyone, because it's a rare case, but maybe it could at least handle the error better. Perhaps if Astro.rewrite is called when the body has been consumed we could explain that you should clone the body if you intend to rewrite the request afterwards.

ematipico commented 5 months ago

I think this must be done in userland. Using a body after it's been consumed (or read) is most of the time invalid.

ascorbic commented 5 months ago

I'll see if I can make it give a more helpful error

gersomvg commented 5 months ago

@ascorbic good catch. I didn't realise that something that's a read action – in my mind at least –, could cause something like this. Thanks for also providing the proper way to do this.

ascorbic commented 5 months ago

@gersomvg yeah, it's because all read actions on a request (or response) are actually stream methods, and once you've consumed a stream you can't "unstream" it. The clone() method is neat, because it splits the stream (using tee()), so the original stream is then piped to both the original and new body streams. You have to clone it before you read the original body though.

gersomvg commented 4 months ago

@ascorbic Learned something new today 🎊