Trying Next.js Middleware

Novri Anto
4 min readNov 23, 2022

--

Photo by freestocks.org from Pexels

Starting from Nextjs v12.2.0, middleware is stable. Now we have Next.js 13, which introduces a new feature for middleware. In NextJS 13, Middleware can modify request headers, and response headers, and send responses to the page itself.

So, What Middleware is, actually?

According to Vercel, Middleware is a piece of code that runs before the request is completed. What I mean by request is, when you go to a page on the NextJS application. So, before the request from the browser touch your getServerSideProps, orgetStaticProps, the middleware will be executed first. That means, getServerSideProps, orgetStaticProps is executed after middleware.

How to Create Middleware

Generate a NextJS project. You can use npx, pnpm, yarn, or other package managers.

Here I’m using my own boilerplate for NextJS and TailwindCSS projects. If you want to use it, clone this repo on Github.

git clone https://github.com/NovqiGarrix/next-starter-tsc-tailwind <project-name>

Okay, after that. Create a file, called middleware.ts under src directory. If you created the project by using create next-app, that means you don’t have src directory. So, you can create the file in the root folder or the same level where pages directory exists.

Let’s start by creating a simple middleware before we jump into use cases.

// middleware.ts

// import type, means only import the type definitions from next/server
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

export function middleware(req: NextRequest) {

// Since Middleware runs on every request, we can have a condition
// to filter the middleware to only run on specific routes

// In this example:
// 1. Middleware won't run on /api routes
// 2. Middleware wont't run on public folder
// 3. Middleware won't run on static files
if (req.url.startsWith("/api") || req.url.startsWith(".") || req.url.startsWith("/static")) {
return NextResponse.next();
}

// Create response object
const res = NextResponse.next();

// And Set a new custom header
res.headers.set('From-Middleware', 'Hello, From Middleware');
return res;

}

To check if the header is actually being set. I created getServerSideProps to get the response header from middleware.

// src/pages/index.tsx

export const getServerSideProps: GetServerSideProps = async ({ res }) => {
// The value could be undefined, so we need to use nullish coalescing
const headerFromMiddleware = res.getHeader("From-Middleware") ?? null;

return {
props: {
customHeader: headerFromMiddleware,
},
};
};

Then show the value on the page.

<p>{props.customHeader}</p>

Here’s the result

The header value getting rendered by getServerSideProps in the HomePage.

You also can check the header value, by inspecting the page.

The Headers from the network tab.

Middleware Use Cases

Middleware is so useful. So, its use cases depend on how we are trying to solve a problem with it. For example, we can do an authentication check on middleware, redirect a user to the right page, set up some cookies, and much more.

Authentication Middleware

Here’s business logic. Every time users log in, they should have a httpOnly cookie in their browser. Let’s assume, the cookie name is qid. So, to check whether the user is logged in or not, we can use middleware.

Take a look at this code. We add some conditions for the Dashboard pages.

// middleware.ts

export function middleware(req: NextRequest) {

// Protected routes
if (req.nextUrl.pathname.startsWith("/dashboard")) {
// This are dashboard routes. Only logged in user can access this route

// Get the session from cookie
const qid = req.cookies.get("qid");

// If qid is not present, that means the user is not logged in
if (!qid) {
// Redirect to login page
return NextResponse.redirect(new URL("/login", req.url));
}

// Do some check here to verify the qid value

// We can create a custom header here
const response = NextResponse.next();
response.headers.set("is-logged-in", qid);

// And return the response
return response;
}

// Public routes
return NextResponse.next();

}

So, the qid cookie is required now for dashboards pages.

What if the user has the qid cookie? Where is the image/video?

Well, in that case. You have to try to implement the code, and see it yourself.

We can add some conditions as well for the Login and Register Page

    // -- others code

// For Login and Register Page
if (req.nextUrl.pathname.startsWith("/login") || req.nextUrl.pathname.startsWith("/register")) {

const qid = req.cookies.get("qid");
if (!qid) return NextResponse.next();

// If user is already logged in, redirect to dashboard

// Do some check here to verify if the qid value is actually valid

// Set response as redirect
const response = NextResponse.redirect(new URL("/dashboard", req.url));

// We can create a custom header here
response.headers.set("is-logged-in", qid);

// And return the response
return response;

}

// -- others code

Redirect the user to dashboard pages, if the user is already logged in, a.k.a has the qid cookie.

That’s It, Folks!

Hope you learn something useful from this article. Of course, if you have any questions, feel free to ask me, I’ll try to answer your questions ASAP.

Source Code: https://github.com/NovqiGarrix/trying-next-middleware

Follow Me

Twitter: NovqiGarrix

GitHub: NovqiGarrix

--

--