Next.js API routes provide a powerful way to handle backend logic within a Next.js application. But if you're coming from Express.js, you might be wondering—where's my trusty next() function? Well, We've got a work around.
In Express.js, next() is used to pass control to the next middleware function. Next.js does not provide next() by default in API routes, but we could create a similar middleware pattern. Let us see how.
Basic Example of Middleware in Next.js
export default function handlerFunction(req, res) {
middleware(req, res, () => {
res.status(200).json({ message: "Success!" });
});
}
const middleware = (req, res, next) => {
console.log("Middleware execution starts");
next(); // Passing control to the main handler
};
How This Works
- A request comes in.
- The middleware function executes and logs a message.
- The next() function is called, allowing execution to continue.
- The handler function runs and sends a JSON response.
Implementing Multiple Middleware Functions in Next.js
To handle multiple middleware functions, we can create a function to chain them.
export function applyMiddleware(...middlewares) {
return (handler) => (req, res, next) => {
// Keep track of middleware index
let index = 0;
const dispatch = (err) => {
if (err) {
// Pass errors to Express's error handler
return next(err);
}
if (index < middlewares.length) {
const middleware = middlewares[index++];
try {
// Call middleware with the new dispatch
middleware(req, res, dispatch);
} catch (e) {
dispatch(e);
}
} else {
// Call the final handler
handler(req, res, next);
}
};
// Start the middleware chain
dispatch();
};
}
const logMiddleware = (req, res, next) => {
console.log(`Request received!`);
next();
};
const authMiddleware = (req, res, next) => {
if (!req.headers.authorization) {
return res.status(401).json({ error: "Unauthorized" });
}
next();
};
How This Works
- Accepts multiple middleware functions as arguments (...middlewares).
- Returns a function that wraps an API route handler.
- It keeps track of the middleware execution order using an index (let index = 0).
-
Uses a function dispatch to:
- Call the next middleware in the list.
- Handle errors.
- Invoke the final API route handler once all middleware functions are executed.
Use Cases
Using next()-like middleware in Next.js API routes is useful for:
- Authentication Middleware
- Rate Limiting
- Logging & Error Handling
Conclusion
Turns out, Next.js doesn’t need next() to play nice with middleware—you just have to get a little creative! By wrapping your API handlers in middleware functions, you can recreate Express-style flow, making your code cleaner, more reusable, and way more powerful. Checkout the code snippet here.