Open lennartkerkvliet opened 1 week ago
I can't reproduce with 14.2.4 and node 22.1.0.
I used a request bin: https://public.requestbin.com/r/enhaa8qwmvxi7/2hpuXZ1mqrzZs3xYQrlXRux6jny
And as you can see, content length was always respected, when using:
export default async function Home() {
const body = JSON.stringify({ information: "test-abc" });
const url = "https://enhaa8qwmvxi7.x.pipedream.net";
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: body,
};
// await fetch(url, options);
await fetch(new Request(url, options));
return <div>Hi</div>;
}
I also tested with 14.2.3 - does it have to be within a server action?
Indeed, it has to be using a server action...
Hi there, Apparently reproducing your code throws the following error:
Error: Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.
This is because in Next.js in order to protect client-server boundary, Next.js restricts passing Non-serializable value from client to server and since Request() object is non-serializable your code throws an error. Upon refactoring your code within "use server" block, everything works as expected and the server returns status 200 upon POST request.
Working Code:
const body = JSON.stringify({ username: "test", password: "password" });
async function brokenAction() {
"use server"
// Refactored the Request Object within "use-server" scope
const request = new Request("https://www.my-site.com/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: body
});
// this will *not* include the body in the request
await fetch(request)
}
Kindly let me know if this helps or if I missed anything.
@icyJoseph You're correct. When rewriting, I forgot to add the context that this only happens in the server environment, which is where NodeJS Undici is being used. This behavior is internally changed by next and that seems to be causing this issue.
@MahadAdil Did you check out the included sample code? Route requests (in the App Router) do allow chunked encoding so unlike my custom server it's not broken, but you can see that the two server actions which should send the same Request, send different ones. The screenshot of the diff in my description comes from that sample code as well.
@lennartkerkvliet not quite, you see, it also works fine, if you make a request as you render, in the server. At least from what I remember testing yesterday.
The issue happens, when the request is made within a server action, not exactly the same thing as above.
@icyJoseph you mean it works fine when using SSR but not when using Server Actions? I didn't test it, but it would make sense as the patch applied by next only happens in the server action environment AFAIK.
Link to the code that reproduces this issue
https://github.com/lennartkerkvliet/next-fetch-request-bug
To Reproduce
When sending a request body using the
Request
object in a Next.js application while using server actions, the content-length parameter is not included in the request and instead chunked transfer encoding is used. This behavior differs from the expected functionality of the Fetch API, which internally is also constructing aRequest
object.Steps to reproduce the behavior:
Request
object with a body.Request
object to thefetch
function.Example code:
Current vs. Expected behavior
I would expect the parameters in
Request
to be identical to when using the more traditional use of fetch API:but instead will return the latter
Provide environment information
Which area(s) are affected? (Select all that apply)
Not sure, Runtime
Which stage(s) are affected? (Select all that apply)
next dev (local), Vercel (Deployed), Other (Deployed)
Additional context
It seems to be somewhat related to the changes NextJS is making to the
Response
object and in particular theduplex
option. The Django server I am using for my own project does not supporttransfer-encoding
, and will mark the request as a "Bad request syntax".