1.0.2 • Published 2 years ago

next-api-route-middleware v1.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Introduction

Middleware functions allows us to abstract reusable code that runs before the api handler is invoked. They have access to the req, res, and the next middleware function.

Example uses:
  • Add data to the req object (without TypeScript complaining!)
  • Reject wrong request methods
  • Capture errors
  • Validate body/query data

Getting started

1. Install'r

npm i next-api-route-middleware

2. Create your middleware

Your middleware is a function that accepts req, res, and next. It should call next() when done, or send a response.

export type NextApiRequestWithUser = NextApiRequest & User;

export const withUser: Middleware<NextApiRequestWithUser> = async (req, res, next) => {
  const authCookie = await getUserByCookie();

  if (authCookie) {
    req.userId = authCookie.userId;
    next();
  } else {
    res.status(401).send({ message: 'Invalid auth cookie.' });
  }
};
3. Export the use function. Include an array of middlewares in the order you want them to execute, along with your handler as the last item in the array.
import { use } from 'next-api-route-middleware';

const handler = async (req: NextApiRequestWithUser, res: NextApiResponse<User>) => {
  res.status(200).json({ userId: req.userId });
};

export default use(captureErrors, allowMethods(['GET']), addhUser, handler);

Examples

addUser

You can add data to the req object, and it will be available in your handler. In this example we get a userId from an http cookie, if the cookie isn't valid we return a 401.

export const addUser: Middleware<NextApiRequestWithUser> = async (req, res, next) => {
  const authCookie = await getUserByCookie();

  if (authCookie) {
    req.userId = authCookie.userId;
    next();
  } else {
    res.status(401).send({ message: 'Invalid auth cookie.' });
  }
};

allowMethods

You may find that you need to add args to a middleware. To achieve this we make use of a factory pattern. The allowMethods function bellow accepts an array of allowed methods, and returns a middleware. We can make use of this factory by calling the function: allowMethods(['GET', 'POST'])

import { Middleware } from 'next-api-route-middleware';

export const allowMethods = (allowedMethods: string[]): Middleware => {
  return async function (req, res, next) {
    if (allowedMethods.includes(req.method!) || req.method == 'OPTIONS') {
      next();
    } else {
      res.status(405).send({ message: 'Method not allowed.' });
    }
  };
};

captureErrors

We can also perform actions with inner middleware functions. In this example we wrap the inner middleware functions in a try catch, allowing us to catch any errors that bubble up.

import { Middleware } from 'next-api-route-middleware';

export const captureErrors: Middleware = async (req, res, next) => {
  try {
    await next();
  } catch (error) {
    console.error(error);
    res.status(500).send({ message: 'Server error!' });
  }
};