Skip to content

Commit

Permalink
fix(readRawBody): always return buffer without encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Mar 28, 2023
1 parent 8a92bcd commit 19d133d
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
8 changes: 6 additions & 2 deletions src/utils/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ export function readRawBody<E extends Encoding = "utf8">(
(event.node.req as any)[RawBodySymbol] ||
(event.node.req as any).body; /* unjs/unenv #8 */
if (_rawBody) {
const promise = Promise.resolve(_rawBody);
return encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
const promise = Promise.resolve(
Buffer.isBuffer(_rawBody) ? _rawBody : Buffer.from(_rawBody)

This comment has been minimized.

Copy link
@dvanmali

dvanmali Mar 30, 2023

@pi0 Shouldn't this be?

Buffer.isBuffer(_rawBody) ? Buffer.from(_rawBody) : _rawBody

Currently getting this error when yarn upgraded to v1.6.4

[nuxt] [request error] [unhandled] [500] The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Promise

This comment has been minimized.

Copy link
@pschnyder

pschnyder Apr 3, 2023

Getting this error two after the new update.

This comment has been minimized.

Copy link
@naisonsouza

naisonsouza Apr 5, 2023

Getting same error after update

This comment has been minimized.

Copy link
@snsxn

snsxn Apr 19, 2023

I'm currently getting this error while deploying to Firebase functions:
[nuxt] [request error] [unhandled] [500] The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object

This comment has been minimized.

Copy link
@sisou

sisou Apr 19, 2023

Contributor

As a workaround, before calling readBody(event), check if event.node.req.body is already set and the object you are looking for:

// @ts-expect-error - req.body is not defined in the type definitions
const body = await (event.node.req.body || readBody(event));

I think it's because the body is already parsed by unenv, meaning event.node.req[RawBodySymbol] is emptied, so _rawBody falls back to event.node.req.body (which is already parsed into an object), but here it's now trying to be parsed into a buffer, which fails.

This comment has been minimized.

Copy link
@snsxn

snsxn Apr 19, 2023

As a workaround, before calling readBody(event), check if event.node.req.body is already set and the object you are looking for:

// @ts-expect-error - req.body is not defined in the type definitions
const body = await (event.node.req.body || readBody(event));

I think it's because the body is already parsed by unenv, meaning event.node.req[RawBodySymbol] is emptied, so _rawBody falls back to event.node.req.body (which is already parsed into an object), but here it's now trying to be parsed into a buffer, which fails.

It works, thank you!!

is this a temporary workaround or it's how it works?

This comment has been minimized.

Copy link
@Eckhardt-D

Eckhardt-D Apr 27, 2023

Contributor

@pi0 Just encountered this snag in firebase preset with Nuxt / Nitro. Is there not a way to handle the already deserialized object in readBody itself instead of checking node req body first?

);
return encoding
? promise.then((buff) => buff.toString(encoding))
: (promise as Promise<any>);
}

if (!Number.parseInt(event.node.req.headers["content-length"] || "")) {
Expand Down
19 changes: 18 additions & 1 deletion test/body.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ describe("", () => {
expect(result.text).toBe("200");
});

it("handle raw body with buffer type (unenv)", async () => {
it("handle readBody with buffer type (unenv)", async () => {
app.use(
"/",
eventHandler(async (event) => {
Expand All @@ -194,6 +194,23 @@ describe("", () => {
expect(result.text).toBe("200");
});

it("handle readRawBody with array buffer type (unenv)", async () => {
app.use(
"/",
eventHandler(async (event) => {
// Emulate unenv
// @ts-ignore
event.node.req.body = new Uint8Array([1, 2, 3]);
const body = await readRawBody(event, false);
expect(body).toBeInstanceOf(Buffer);
expect(body).toMatchObject(Buffer.from([1, 2, 3]));
return "200";
})
);
const result = await request.post("/api/test").send();
expect(result.text).toBe("200");
});

it("parses multipart form data", async () => {
app.use(
"/",
Expand Down

0 comments on commit 19d133d

Please sign in to comment.