BLOG

Next Js - adding a middleware — Well, everyone needs some!!


Next Js is one of the most popular upcoming frameworks in the JavaScript community. It provides an awesome, out of the box, client side routing along with a filesystem api setup. Almost all of the necessary tooling has been done. However, I recently happened to fall upon a very common requirement where the framework failed to match my expectation. If you're reading the blog, chances are, you feel the same way.

Since Next Js provides an awesome alternative to Express.js with it's file directory based routing approach, chances are, you would not want to lose that just to be able to add a middleware. By the end of this article, you should be able to have a simple higher order function that gets the job done.

After a good amount of reading and looking up documentation online, I managed to come up with a simpler solution.

Just do it yourself!!
Just do it yourself!!

Here's what a middleware is supposed to do -

  • Allow the developer peek into, maybe tweak, your request and response objects
  • Pass the req and res to the next handler
  • In some cases, prevent the req from going any further

Middlewares are something that express and connect have done a really good job with. In the case of express, the syntax looks something like this -

app.use((req, res, next) => { // some logic for the middleware next();});

In the case of Next Js, we simply do not have the support for middlewares.

Going through multiple approaches, this is what I concluded served me best -

  • Have a wrapper higher order function that can intercept request and response
  • The function should be able to pass the intercepted req, res objects to the api
  • They should be able to accept multiple combinations and orders middlewares

What I still failed to do was to figure out a way to pass it automatically to the api calls

Here's what the implementation looked like in code

const apply = (api, middlewares = []) => { return async ( req, res ) => { let err = false; for (let i = 0; i < middlewares.length; i++) { const ware = middlewares[i]; const data = await ware(req, res); if (data && data.status === false) { res.json(data); err = true; break; } } if (err) { } await api(req, res); }};

The key idea behind the above implementation is to run all middlewares parallely and continually make changes to the shared req, res objects on the go. If any middleware faces an issue and return a negative status, the request exits immediately. This helps in security related middlewares.

That's one way to do it.

Another way to get the job done would be -

> npm i next-high-order-middleware

The NPM Package does something similar and exposes another higher order function wrapper. This allows the following code to work.

// middlewares/index.js
import logger from "./logger";import bodyparser from "./bodyparser";import verifyAuthToken from "./auth";
import apply from "next-high-order-middleware";
const applyBasicMiddlewares = apply([logger, bodyparser]);const applyAuthMiddlewares = apply([logger, bodyparser, verifyAuthToken]);
export default applyAuthMiddlewares;

// next-js-project/pages/api/endpoint
import applyAuthMiddlewares from "../../middlewares";
export default applyAuthMiddlewares(async (req, res) =>{ ...})
Make NPM do it!!
Make NPM do it!!

Hi! I'm a web developer making assets on the internet. Think you have something to say about the article? Do reach out to me at saranshgupta1995@gmail.com