[Solved] multiple middleware in nextjs 13 app directory not working – Middleware

by
Ali Hasan
middleware next.js next.js13 node.js reactjs

The Problem:

I’m using Next.js 13 and want to set up multiple middleware functions for my app. I have one middleware for setting the language and another for redirecting a specific page. The issue is, the second middleware is not working as expected. I’ve checked the code, but I can’t find any syntax errors. It simply doesn’t execute, and I’m not receiving any error messages.

The Solutions:

Solution 1: Create a middleware folder and config file

Create a middleware folder in the root directory and add a config.ts file with this code:

import {NextRequest, NextResponse} from "next/server";
import {default as Authentication, matcher as AuthenticationMatcher} from "@/middleware/authentication";
// import {default as Logging, matcher as LoggingMatcher} from "@/middleware/localization";

interface middlewareType {
    middleware: (req: NextRequest) => Promise<NextResponse>
    matcher?: string | null | undefined
}

export const middleware: middlewareType[] = [
    {
        middleware: Authentication,
        matcher: AuthenticationMatcher
    },
    // {
    //     middleware: Logging,
    //     matcher: AuthenticationMatcher
    // },
]    

This file defines the middleware functions and their matchers (paths they apply to).

Solution 2: Move middleware logic into a single exported function

In Next.js 13, only one middleware function can be exported. Therefore, you need to combine the logic from both middleware and middleware2 into a single exported middleware function. Here’s a modified version of your code:

import { NextResponse, NextRequest } from 'next/server';

import acceptLanguage from 'accept-language';
import { fallbackLng, languages } from './app/i18n/settings';

acceptLanguage.languages(languages);

const cookieName = 'i18next';

export function middleware(request: NextRequest) {
  // Logic from middleware2
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.redirect(new URL('/home', request.url));
  }

  // Logic from middleware

  let lng;
  if (request.cookies.has(cookieName)) {
    lng = acceptLanguage.get(request.cookies.get(cookieName).value);
  }

  // automatic detect language with browser
  // if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'));

  if (!lng) lng = fallbackLng;

  // Redirect if lng in path is not supported
  if (
    !languages.some((loc) => request.nextUrl.pathname.startsWith(`/${loc}`)) &&
    !request.nextUrl.pathname.startsWith('/_next')
  ) {
    return NextResponse.redirect(new URL(`/${lng}${request.nextUrl.pathname}`, request.url));
  }

  if (request.headers.has('referer')) {
    const refererUrl = new URL(request.headers.get('referer'));
    const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`));
    const response = NextResponse.next();
    if (lngInReferer) response.cookies.set(cookieName, lngInReferer);
    return response;
  }

  return NextResponse.next();
}

Solution 3: Separate Middleware Functions into Different Files

In Next.js, only one exported middleware function per file is supported. To use multiple middleware functions, create separate files for each function. For example, you can have `middleware1.js` and `middleware2.js` files.

middleware1.js:

import { NextResponse, NextRequest } from 'next/server';
import acceptLanguage from 'accept-language';
import { fallbackLng, languages } from './app/i18n/settings';

acceptLanguage.languages(languages);
const cookieName = 'i18next';

export function middleware(req: any) {
  let lng;
  if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value);
  if (!lng) lng = fallbackLng;
  const response = NextResponse.next();
  if (lngInReferer) response.cookies.set(cookieName, lngInReferer);
  return response;
}

export const config = {
  api: {
    bodyParser: false,
  },
  matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)'],
};

middleware2.js:

import { NextResponse, NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.redirect(new URL('/home', request.url));
  }
}

Remember to import and use these middleware functions in the appropriate places in your application.

Video Explanation:

The following video, titled "Next.js Middleware & Cors | Nextjs 13 tutorial - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

Web Dev Roadmap for Beginners (Free!): https://bit.ly/DaveGrayWebDevRoadmap Learn how to apply Next.js middleware in Nextjs 13.