Next.js API Route Handler Utility Function
Originally published on 4/21/2023
TLDR; - get the utility from this gist.
Next.js provides a built-in API routes feature that allows you to easily create serverless API endpoints. It makes handling API requests with different HTTP methods and error handling straightforward. In this blog post, we'll create a reusable utility function called handleApiRequest
to further simplify and standardize our API route handlers.
Getting Started
Let's say you've already set up a Next.js project and you're ready to create API route handlers. We'll create a utility function handleApiRequest
that simplifies the process of handling different request methods, executing the actual request logic, and handling errors.
Creating the handleApiRequest
Utility
First, create a utils
folder in your project's root directory and add a new file called api-utils.ts
. Inside this file, we'll create the handleApiRequest
function along with an error handling utility called handleErrorResponse
.
// utils/api-utils.tsimport { NextApiRequest, NextApiResponse } from "next";export async function handleApiRequest(req: NextApiRequest,res: NextApiResponse,expectedReqMethod: string,handleRequest: (body: any) => Promise<any>): Promise<void> {if (req.method === expectedReqMethod) {try {const responseData = await handleRequest(req.body);res.status(200).json(responseData);} catch (error: unknown) {handleErrorResponse(res, error);}} else {res.status(405).json({ error: "Method not allowed" });}}export function handleErrorResponse(res: NextApiResponse,error: unknown): void {if (error instanceof Error) {res.status(500).json({ error: error.message });} else {res.status(500).json({ error: "An unknown error occurred" });}}
How Does It Work?
The handleApiRequest
function accepts four parameters:
req
: The NextApiRequest object.res
: The NextApiResponse object.expectedReqMethod
: The expected HTTP method for the API route handler (e.g., "GET", "POST", "PUT", etc.).handleRequest
: A function that handles the actual request logic and returns a promise.
It checks if the request method matches the expected method. If it does, it executes the handleRequest
function and sends the response. If an error occurs, it calls handleErrorResponse
to handle the error and send the appropriate response. If the request method does not match the expected method, it returns a 405 status code with a "Method not allowed" error message.
Using the handleApiRequest
Utility
Here’s example with a simple API route handler that accepts user messages and stores them in an array. The API route will have two endpoints: one for creating messages (POST) and another for fetching messages (GET).
First, create a file called messages.ts
in the pages/api
folder. We'll use the handleApiRequest
utility to handle both GET and POST requests.
// pages/api/messages.tsimport { NextApiRequest, NextApiResponse } from "next";import { handleApiRequest } from "@/utils/api-utils";// This array will store messages for demonstration purposes.// In a real application, you should store messages in a database.const messages: string[] = [];async function handleGetMessages() {return { messages };}async function handleCreateMessage(body: any) {const { message } = body;if (!message || typeof message !== "string") {throw new Error("Invalid message");}messages.push(message);return { success: true };}export default async function handler(req: NextApiRequest,res: NextApiResponse) {if (req.method === "GET") {await handleApiRequest(req, res, "GET", handleGetMessages);} else if (req.method === "POST") {await handleApiRequest(req, res, "POST", handleCreateMessage);} else {res.status(405).json({ error: "Method not allowed" });}}
Now, when a GET request is sent to /api/messages
, the API will return the array of messages. When a POST request is sent to /api/messages
with a message in the request body, it will add the message to the array and return a success status.
The handleApiRequest
utility simplifies the process of handling different request methods and errors by wrapping the actual request logic in a standardized way.