Next.js Discord

Discord Forum

Help to use multiples middlewares (next-auth and next-intl)

Unanswered
Tomistoma posted this in #help-forum
Open in Discord
TomistomaOP
How i can use two middlewares?

import createMiddleware from 'next-intl/middleware';
import { auth } from "@/auth"

export default createMiddleware({
    locales: ['en', 'pt'],
    defaultLocale: 'pt',
})  

export default auth;

7 Replies

Hey!
I'm new here, and when I was researching what's interesting, I came across this project in #community-content. It seems to be exactly what you need.
https://discord.com/channels/752553802359505017/1270380568974065725/1270380568974065725
TomistomaOP
Hi, tk for this
Spectacled bear
please don't tell me you are trying to have middleware for auth and localization
IF you are, you could use a package for this, but if you don't wanna add more and more unnecessary dependencies to your project, "chaining middleware" actually isn't that hard
-- and this comes from a dude that swore it was the hardest thing to figure out in nextjs like up to a couple days ago 😛
Spectacled bear
So, taking info from the top answer on this SO post and making it even more easy to understand and implement:
https://stackoverflow.com/questions/76603369/how-to-use-multiple-middlewares-in-next-js-using-the-middleware-ts-file

Step 1) create a middlewares directory in /src (or in the root of your project if not using the /src directory)
Step 2) create a stackHandler.ts (or .js if not using TypeScript) file in /middlewares and add the following code inside:
// skip this import if not using typescript
import { MiddlewareFactory } from "@/lib/definitions";
import {
  NextMiddleware,
  NextResponse
} from "next/server";

// remove types if not using typescript
export function stackMiddlewares(functions: MiddlewareFactory[] = [], index = 0): NextMiddleware {
  const current = functions[index];
  if (current) {
    const next = stackMiddlewares(functions, index + 1);
    return current(next);
  }
  return () => NextResponse.next();
}

Step 3) create a file called localeMiddleware.ts (or .js) in /middlewares and add the following code inside:
import {
  NextFetchEvent,
  NextRequest,
  NextResponse
} from "next/server";

// skip if not using ts. also don't forget to remove all types if not using TS.
import { MiddlewareFactory } from "@/lib/definitions";

function getSearchParam(param: string, url: any) {
  return url.searchParams.get(param);
}

export const localeMiddleware: MiddlewareFactory = (next) => {
  return async(request: NextRequest, _next: NextFetchEvent) => {
    const pathname = request.nextUrl.pathname;

    if (["/"]?.some((path) => pathname.startsWith(path))) {
      // middleware code goes here

    }
    return next(request, _next);
  };
};
Step 4) In your existing middleware.ts(or .js) file, add the following code:
import { stackMiddlewares } from "@/middlewares/stackHandler";
import { localeMiddleware } from "@/middlewares/localeMiddleware";

const middlewares = [localeMiddleware];
export default stackMiddlewares(middlewares);

export const config = {
    matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};


Step 5) Skip this if not using TypeScript :: inside your src directory or, if not using it, at the root of your project, create a directory called lib, and inside of it create a file called definitions.ts and add the following code in it:
import {
  NextMiddleware
} from "next/server";

export type MiddlewareFactory = (middleware: NextMiddleware) => NextMiddleware;
Essentially, whenever you need to add a middleware to your project (for authentication, for example) you simply:
1) Create a file for your middleware in /middlewares - i like the naming convention of somethingMiddleware but it's not mandatory - adding the code above (for localeMiddleware.ts/js) and the code for the middleware below the appropriate comment
2) Import the new middleware in middleware.ts/js and it should work!
That's what I've done, at least, and it works almost perfectly, the issues are most likely my fault, not the code's 😛