Bun request body
Environment
bun
Reproduction
https://github.com/b7nan/nitro_bun_body
Describe the bug
In dev body is object, undefined, string, but in prod is ArrayBuffer. That work with composables, but break app that use other node packages or frameworks on top of nitro.
That example show me in dev undefined body (huh in my real app it is an object, another strange thing), in prod show ArrayBuffer what is decoded to object what i send with curl
Additional context
bun run build bun run .output/server/index.mjs
curl -H "Content-Type: application/json" -X POST http://localhost:3000 -d '{"email":"", "password":""}'
or
curl -H "Content-Type: multipart/form-data" -X POST http://localhost:3000 -d '{"email":"", "password":""}'
undefined req.body in dev, array buffer in prod.
I know about readMultipartFormData and readBody, I don't need that, it's not about that.
Logs
It's because of body = await req.arrayBuffer(); in build, and not such thing for dev.
const server = Bun.serve({
port: process.env.NITRO_PORT || process.env.PORT || 3e3,
websocket: void 0,
async fetch(req, server2) {
const url = new URL(req.url);
let body;
if (req.body) {
body = await req.arrayBuffer();
}
return nitroApp.localFetch(url.pathname + url.search, {
host: url.hostname,
protocol: url.protocol,
headers: req.headers,
method: req.method,
redirect: req.redirect,
body
});
}
});
But if a request has a body, in 99% it will be used in app (api endpoint) and can be decoded here and not in composables like readBody and readMultiparFormData. Two composables for one work (readBody need to be smart)
const server = Bun.serve({
port: process.env.NITRO_PORT || process.env.PORT || 3e3,
websocket: void 0,
async fetch(req, server2) {
const url = new URL(req.url);
let body;
if (req.body) {
const text = await req.text();
if (!text) {
body = undefined;
} else {
const contentType = req.headers.get("content-type") || "";
if (contentType.startsWith("application/x-www-form-urlencoded")) {
const form = new URLSearchParams(text);
const EmptyObject = /* @__PURE__ */ (() => {
const C = function () {};
C.prototype = Object.create(null);
return C;
})();
const parsedForm = new EmptyObject();
for (const [key, value] of form.entries()) {
if (hasProp(parsedForm, key)) {
if (!Array.isArray(parsedForm[key])) {
parsedForm[key] = [parsedForm[key]];
}
parsedForm[key].push(value);
} else {
parsedForm[key] = value;
}
}
body = parsedForm;
} else {
try {
body = JSON.parse(text);
} catch {
throw createError({
statusCode: 400,
statusMessage: "Bad Request",
message: "Invalid JSON body",
});
}
}
}
}
return nitroApp.localFetch(url.pathname + url.search, {
host: url.hostname,
protocol: url.protocol,
headers: req.headers,
method: req.method,
redirect: req.redirect,
body
});
}
});
And that deviation from express/connect/node http or what it is, it's very bad. it is not clear where the body is(for me, int that point of time), in re.body, in event.context in req.rawSomething, in other place. Is object, is undefined, isa array buffer...
readMultiparFormData return data in an less util form, that need additional manipulations if i remember correct