next-api-route-middleware v1.0.2
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
reqobject (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!' });
}
};