oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.62k stars 2.72k forks source link

Bun.serve maxRequestBodySize is not working properly for values larger than 999916545 #6504

Open lastvoidtemplar opened 12 months ago

lastvoidtemplar commented 12 months ago

What version of Bun is running?

1.0.6+969da088f5db3258a803ec186012e30f992829b4

What platform is your computer?

Linux 6.2.0-34-generic x86_64 x86_64

What steps can reproduce the bug?

Bun.serve maxRequestBodySize is not working properly values larger than 999916545. For example:

//max Content-Length: 999916545

export const server = Bun.serve({
    fetch(request, server) {
        return new Response("Hit", { status: 200 });
    },
    port: 3000,
    maxRequestBodySize: Number.MAX_SAFE_INTEGER //9007199254740991 (same issue with 999916545+10000)
  });

If request Content-Length is larger than 999916545 (2048 bytes potential deviation). It returns 413.

What is the expected behavior?

To return status 200

What do you see instead?

No response

Additional information

No response

Hanaasagi commented 12 months ago

I cannot reproduce this issue locally. Could you provide some client code or a curl command for this?

My Env

Test code


- client.ts
```JavaScript
for (const length of [999916545, 999916545 + 1024, 999916545 + 2048]) {
  const response = await fetch("http://127.0.0.1:3000", {
    method: "POST",
    body: "A".repeat(length),
  });
  console.log(response.statusText, await response.text());
}

It printed status 200 for me.

2023-10-15_15-23

And I found that maxRequestBodySize compares with content-length.

https://github.com/oven-sh/bun/blob/a87aa2fafe05c358455173ea65877be5eefcbd63/src/bun.js/api/server.zig#L5671-L5684

lastvoidtemplar commented 12 months ago

Sorry for incomplete information. For example I send request with 1Gb file as Content-Type: multipart/form-data. And returns 413.

image image I talked about Content-Length header.

The screenshot are from insomnia (I tried with Postman and simple html form - same result).

Again sorry for missing information and thank you for your time. Is there anything else I can help me with?

Hanaasagi commented 12 months ago

Thank you for your reply.

Repro

const server = Bun.serve({
  async fetch(request, server) {
    return new Response("Hi", { status: 200 });
  },
  port: 3000,
  maxRequestBodySize: 1000000000 + 1, // any number greater than 1000000000
});
// less than 1000000000 is worked
for (const length of [1000000000 - 1, 1000000000]) {
  const response = await fetch("http://127.0.0.1:3000", {
    method: "POST",
    body: "A".repeat(length),
  });
  console.log(response.statusText);
}

The first request with a body of length 1000000000 - 1 gets a 200 response. This is as expected. However, the second request with a body of length 1000000000 results in a ConnectionClosed error.

Furthermore, I used wireshark to capture packets and found that it didn't return a 413; instead, it closed the connection directly, no response. The following code block was not entered, and the connection was closed at some point later on. I haven't yet located the specific location.

https://github.com/oven-sh/bun/blob/a87aa2fafe05c358455173ea65877be5eefcbd63/src/bun.js/api/server.zig#L5679-L5684

cirospaciari commented 12 months ago

Thank you for your reply.

Repro

  • server.ts
const server = Bun.serve({
  async fetch(request, server) {
    return new Response("Hi", { status: 200 });
  },
  port: 3000,
  maxRequestBodySize: 1000000000 + 1, // any number greater than 1000000000
});
  • client.ts
// less than 1000000000 is worked
for (const length of [1000000000 - 1, 1000000000]) {
  const response = await fetch("http://127.0.0.1:3000", {
    method: "POST",
    body: "A".repeat(length),
  });
  console.log(response.statusText);
}

The first request with a body of length 1000000000 - 1 gets a 200 response. This is as expected. However, the second request with a body of length 1000000000 results in a ConnectionClosed error.

Furthermore, I used wireshark to capture packets and found that it didn't return a 413; instead, it closed the connection directly, no response. The following code block was not entered, and the connection was closed at some point later on. I haven't yet located the specific location.

https://github.com/oven-sh/bun/blob/a87aa2fafe05c358455173ea65877be5eefcbd63/src/bun.js/api/server.zig#L5679-L5684

Looks like is something inside uWS code https://github.com/uNetworking/uWebSockets/issues/1538

cirospaciari commented 11 months ago

@Hanaasagi basically the limit is set here: https://github.com/oven-sh/bun/blob/a87aa2fafe05c358455173ea65877be5eefcbd63/packages/bun-uws/src/HttpParser.h#L202-L227

A workaround is using chunked encoded so each chunk can have up to 1GB actually 999 999 999 bytes

DhifMlak commented 9 months ago

same issue with bun 1.0.18 !