Next.js API routes default response on error or no HTTP method match

I’m working on API Routes in Next.js with every path is structured like this:

import { NextApiRequest, NextApiResponse } from "next";

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const { query } = req;

  try {
    switch (req.method) {
      case "GET":
        // Do some GET stuff
        res.status(200).send(result);
        break;

      case "POST":
        // Do some POST stuff
        res.status(200).send(result);
        break;

      default:
        // No Matched Method
        res.status(405).send("Method Not Allowed");
        break;
    }
  } catch (e) {
    // Unprocessable Entity
    res.status(422).send(e);
  }
};

As you can see the default case and catch part will be duplicated all over the files. So, I wanted to know:

  • Does Next.js has a built-in supports default response when there’s no matched method or there’s an error in processing the request?
  • (If there’s no built-in support) How can it be done?

Here’s my idea of a solution if there’s no built-in support:

  • Use a middleware
  • Create a function to wrap the API call before export default. I’ve tried to implement this but stuck at accessing req and res objects as in the code block below.
const wrapAPICall = async (
  fn: (req: NextApiRequest, res: NextApiResponse) => void
) => {
  try {
    await fn(req, res); // Can't access req, res here
  } catch (e) {
    res.status(422).send(e); // Also can't access req, res here
  } finally {
    if (!res.headersSent) res.status(405).send("Method Not Allowed");
  }
};

const apiCall = async (req: NextApiRequest, res: NextApiResponse) => {
  // Does some API stuff
};

export default wrapAPICall(apiCall);

Answer

I think your wrapper solution is sound. To make it work you just need to return a function from the wrapper.

const wrapAPICall = (
    fn: (req: NextApiRequest, res: NextApiResponse) => void
) => {
    return async (req: NextApiRequest, res: NextApiResponse) => {
        try {
            await fn(req, res);
        } catch (e) {
            res.status(422).send(e);
        } finally {
            if (!res.headersSent) res.status(405).send("Method Not Allowed");
        }
    }
};

Leave a Reply

Your email address will not be published. Required fields are marked *