bun
bun copied to clipboard
[Bun + Express] Error: request size did not match content length.
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?
- Make an express app
- Add a GET endpoint and run the app with
bun run server.js - Access to that GET endpoint via any REST API clients (e.g. Postman, Insomnia, ThunderClient)
- Add any Form-Encode data to that endpoint and send request.
- 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¶m2=value2"
Please give this another try in Bun v0.7.1 and leave a comment if there's still issues. @Hanaasagi fixed this in #3853.
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.
Still having this error:
@mavyfaby Hello, can you provide more information, thanks?
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}`);
});
Try adding:
app.use(express.urlencoded({ extended: true }));
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¶m2=value2"
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:
-
https://github.com/expressjs/express/blob/3531987844e533742f1159b0c3f1e07fad2e4597/lib/express.js#L83
-
https://github.com/expressjs/body-parser/blob/ee91374eae1555af679550b1d2fb5697d9924109/lib/read.js#L79
-
https://github.com/stream-utils/raw-body/blob/4203bba9eb3e989bf36fd7067e58725d55126cd1/index.js#L272-L282
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¶m2=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 🤔
None, I'm simply curious as to why it fails when native Node.js just work fine.
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
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?
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¶m2=value2"
express.text() is also affected. I've got another repro in #7939
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:
- Bun v1.1.2
- express v4.18.3 with the following middlewares: Helmet(v7.1.0), cors(v2.8.5), express.json and express-rate-limit The error I get is the same as shown in https://github.com/oven-sh/bun/issues/3842#issuecomment-1728611862 response.
This didn't happen with node