You can use middleware chaining for this purpose. Here’s how you can achieve this:
- Create a folder called
middlewares
in yoursrc
folder. - Create a file called
stackHandler.ts
in themiddlewares
folder and paste this content into it:
import {
NextMiddleware,
NextResponse
} from "next/server";
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();
}
- Create another file called
withUser.ts
and paste this content into it:
import {
NextFetchEvent,
NextRequest,
NextResponse
} from "next/server";
function getSearchParam(param: string, url: any) {
return url.searchParams.get(param);
}
export const withUser: MiddlewareFactory = (next) => {
return async(request: NextRequest, _next: NextFetchEvent) => {
const pathname = request.nextUrl.pathname;
if (["/profile"]?.some((path) => pathname.startsWith(path))) {
const userId = request.cookies.get("userId");
if (!userId) {
const url = new URL(`/auth/login`, request.url);
return NextResponse.redirect(url);
}
}
return next(request, _next);
};
};
- Finally in your
middleware.ts
file in thesrc
folder paste this content:
import {
stackMiddlewares
} from "@/middlewares/stackHandler";
import {
withUser
} from "@/middlewares/withUser";
const middlewares = [withUser];
export default stackMiddlewares(middlewares);
Note
Define the MiddlewareFactory type as below (ignore this if not using Typescript):
import {
NextMiddleware
} from "next/server";
export type MiddlewareFactory = (middleware: NextMiddleware) => NextMiddleware;
Note
You can create as many middlewares like withUser
as you want by creating them and then importing them into middlewares.ts
and pushing them in the middlewares
array.