oven-sh / bun

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

[Bun + Express] Error: request size did not match content length. #3842

Open mavyfaby opened 11 months ago

mavyfaby commented 11 months ago

What version of Bun is running?

0.7.0

What platform is your computer?

Linux 6.2.0-26-generic x86_64 x86_64

What steps can reproduce the bug?

  1. Make an express app
  2. Add a GET endpoint and run the app with bun run server.js
  3. Access to that GET endpoint via any REST API clients (e.g. Postman, Insomnia, ThunderClient)
  4. Add any Form-Encode data to that endpoint and send request.
  5. You should see the error: Error: request size did not match content length

What is the expected behavior?

It shouldn't trigger the error even when using GET.

What do you see instead?

Error: request size did not match content length

Additional information

Minimum reproducable code

const express = require("express");
const app = express();
const port = 3000;

app.use(express.urlencoded({ extended: true })); // cause

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Execute

curl -X GET http://127.0.0.1:3000 \
   -H "Content-Type: application/x-www-form-urlencoded" \
   -d "param1=value1&param2=value2" 
Jarred-Sumner commented 11 months ago

Please give this another try in Bun v0.7.1 and leave a comment if there's still issues. @Hanaasagi fixed this in #3853.

Hanaasagi commented 11 months ago

You should see the error: Error: request size did not match content length

This looks like another issue. In issue https://github.com/oven-sh/bun/issues/3668, "Content-Length" and the body size are both missing 1 byte, but they are equal.

mavyfaby commented 11 months ago

Still having this error: image

Hanaasagi commented 11 months ago

@mavyfaby Hello, can you provide more information, thanks?

2023-07-31_23-29

I used the example code from express demo.

const express = require("express");
const app = express();
const port = 3000;

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
mavyfaby commented 11 months ago

Try adding:

app.use(express.urlencoded({ extended: true }));
Hanaasagi commented 11 months ago

Ok, thanks.

Minimum reproducible code

const express = require("express");
const app = express();
const port = 3000;

app.use(express.urlencoded({ extended: true }));
app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Execute

curl -X GET http://127.0.0.1:3000 \
   -H "Content-Type: application/x-www-form-urlencoded" \
   -d "param1=value1&param2=value2" 
Hanaasagi commented 11 months ago

I think I found the root cause for the issue. express.urlencoded uses the body-parser package to parse the request body. The body-parser package relies on raw-body to read the request body. The calling process is as follows:


The problematic code is the following snippet: onData is not called in Bun, so received remains 0.

https://github.com/stream-utils/raw-body/blob/4203bba9eb3e989bf36fd7067e58725d55126cd1/index.js#L254-L289

We can verify this by using the following code:

const http = require("http");

const server = http.createServer((req, res) => {
  let requestBody = "";

  req.on("data", chunk => {
    console.log("onData is called");
    requestBody += chunk;
  });

  req.on("end", () => {
    console.log("requestBody is", requestBody);
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end(`Received the following data: ${requestBody}\n`);
  });
});

const port = 3000;
server.listen(port, () => {
  console.log(`Server is running and listening on port ${port}`);
});

In bun 0.7.0, we got following output

>>​ curl -X GET http://127.0.0.1:3000 \
   -H "Content-Type: application/x-www-form-urlencoded" \
   -d "param1=value1&param2=value2"
Received the following data:

Updated:

If change the HTTP method to POST, it works. It looks like it's not being called in GET requests. I have a question: in what scenarios would you need to add form-data in a GET request 🤔

mavyfaby commented 11 months ago

None, I'm simply curious as to why it fails when native Node.js just work fine.

Hanaasagi commented 11 months ago

Hi, @mavyfaby If you want to see the relevant implementation, you can refer to this.

https://github.com/oven-sh/bun/blob/7a8f57c4e527f7fc84b85a4757723bb97540ebc3/src/js/node/http.ts#L593-L601

birkskyum commented 9 months ago

I don't get the Error: request size did not match content length, but simply an empty requestBody when using GET. @mavyfaby do you still get the error?

mavyfaby commented 9 months ago

Yep, still having those error

Minimum reproducible code

const express = require("express");
const app = express();
const port = 3000;

app.use(express.urlencoded({ extended: true }));
app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Execute

curl -X GET http://127.0.0.1:3000 \
   -H "Content-Type: application/x-www-form-urlencoded" \
   -d "param1=value1&param2=value2" 
  • express@4.18.2

image

noway commented 6 months ago

express.text() is also affected. I've got another repro in #7939

Shompi commented 2 months ago

Hello. Sorry beforehand if the information I provide lacks technicalities.

I recently stumbled upon this same error using bun + express and sending requests to the API through ThunderClient. After some testing I noticed that this error arises when I try to make a GET request to the API passing any kind of data inside the body of the request, if I leave the request body empty then the error does not happen, and the API responds as it should.

Relevant dependencies:

This didn't happen with node

itorz7 commented 1 month ago

bump + i got this error with Bun 1.1.8

AMV1909 commented 1 month ago

I notice that the error in my case only happens when I make a get request with something in the body, if clear the body, the error doesn't happen, try it, and tell us the results

Version: Bun 1.1.8

Serlych commented 1 month ago

If anyone is looking for an answer to this error:

It is possible that the issue arises from sending body data via a GET request. To resolve this, modify your endpoint to handle a POST request instead. This adjustment should address the problem. ❤️