#cannot read from req.body in serverless function

1 messages · Page 1 of 1 (latest)

inland garden
#

I have a very simple express server hosted on vercel using serverless functions. You can follow this guide to get to where I am: https://vercel.com/guides/using-express-with-vercel#standalone-express

I then added 2 endpoints of my own.

I added this route which works perfectly, does not read from req.body though:

app.get('/create-room', function (req, res) {
res.end(JSON.stringify(
{ "room_id": Math.random().toString(36).slice(-6) }
));
});

The route having issues is this:

app.post('/auth', function (req, res) {
const { body } = req;
return res.end(Hello ${body.name}, you just parsed the request body!);
});

My vercel.json is this, I changed the source value on purpose, no bigge:
{
"rewrites": [{ "source": "/(.*)", "destination": "/api" }]
}

My deployed url to the broken endpoint is this: https://meeting-backend-vercel.vercel.app/auth, you can curl to it with curl -X POST "https://meeting-backend-vercel.vercel.app/auth" -H "Content-Type: application/json" -d '{ "name": "Reader" }'. You can curl to the /create-room endpoint which works fine with this: curl -X GET https://meeting-backend-vercel.vercel.app/create-room. The logs say every time I do the curl to /auth there is a internal server error as it can't read req.body. Why?

Vercel Documentation

Learn how to deploy an Express.js application to Vercel using Serverless Functions.

hexed gardenBOT
#

Hi @inland garden. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The issue you're experiencing might be due to the way serverless functions handle request bodies in Next.js. According to the Next.js documentation (https://nextjs.org/docs/api-routes/introduction), any file inside the pages/api folder is treated as an API endpoint instead of a page. These API routes provide built-in middlewares which parse the incoming request (req).

The req.body middleware is an object containing the body parsed by content-type, or null if no body was sent. If you're trying to access req.body in your POST request and it's returning null, it might be because no body was sent or it wasn't parsed correctly.

If you need to get the raw body of a serverless function, you can follow this guide (https://vercel.com/guides/how-do-i-get-the-raw-body-of-a-serverless-function). It provides an example of how to buffer the readable stream from the request to get the raw body.

Here's the example code from the guide:

import type { VercelRequest, VercelResponse } from '@vercel/node';
import type { Readable } from 'node:stream';

export const config = { api: { bodyParser: false, },};

async function buffer(readable: Readable) { 
  const chunks = []; 
  for await (const chunk of readable) { 
    chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk); 
  } 
  return Buffer.concat(chunks);
}

export default async function (req: VercelRequest, res: VercelResponse) { 
  if (req.method === 'POST') { 
    const buf = await buffer(req); 
    const rawBody = buf.toString('utf8');
    res.json({ rawBody }); 
  } else { 
    res.setHeader('Allow', 'POST'); 
    res.status(405).end('Method Not Allowed'); 
  }
}

This code creates a buffer from the readable stream of the request and then converts it to a string. This way, you can get the raw body of the request.

#

Remember to replace VercelRequest and VercelResponse with NextApiRequest and NextApiResponse when using Next.js API Routes.

Also, note that Express.js can swallow errors that can put the main function into an undefined state unless properly handled. They'll render their own error pages (500), which prevents Vercel from discarding the function and resetting its state. This is mentioned in the Vercel guide (https://vercel.com/guides/using-express-with-vercel#drawbacks-and-edge-cases).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@inland garden kapa.ai is still learning and improving, please let us know how it did by reacting below

inland garden
#

I am using express

#

@hexed garden how do I do this iwth a express endpoint on vercel

hexed gardenBOT
#

Let me check the knowledge base for you. One moment! :books:

#

To handle raw request bodies in Express.js on Vercel, you need to disable the automatic body parsing provided by Vercel. This can be done by setting bodyParser: false in the config object for your serverless function.

Here's an example of how you can do this:

import { VercelRequest, VercelResponse } from '@vercel/node';
import express from 'express';

const app = express();

app.use(express.raw({ type: '*/*' }));

app.post('/auth', function (req, res) {
  const body = req.body.toString(); // Convert raw body to string
  res.end(`Hello ${body.name}, you just parsed the request body!`);
});

export const config = {
  api: {
    bodyParser: false,
  },
};

export default function (req: VercelRequest, res: VercelResponse) {
  return app(req, res);
}

In this example, express.raw({ type: '*/*' }) is used to parse all incoming requests as raw bodies, regardless of their content type. The raw body is then converted to a string before being used.

Please note that this is a workaround and might not be the best solution for all use cases. It's generally recommended to use Next.js API routes when working with Vercel and Next.js, as they are designed to work seamlessly with serverless functions.

For more information, you can refer to the Vercel documentation (https://vercel.com/docs/functions/serverless-functions/runtimes/node-js#disabling-helpers-for-node.js) and the Express.js documentation (https://expressjs.com/en/api.html#express.raw).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: