如何通过 middleware.ts 文件在 Next.js 中使用多个中间件?

问题描述 投票:0回答:1

我正在开发一个 Next.js 项目,并尝试在我的应用程序中实现多个中间件。虽然我发现了使用

next-connect
包在 Next.js 中使用单个中间件的示例,但我更喜欢在不依赖任何外部包的情况下实现这一点。

我有一个

middleware.ts
文件,我想在其中定义和使用多个中间件。这是我的
middleware.ts
文件中的代码片段:

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

export function middleware(request: NextRequest) {

  const userId = request.cookies.get('userId')

  if (!userId) {
    return NextResponse.redirect(new URL('/auth/login', request.nextUrl.origin).href);
  }
  return NextResponse.next();
}

export const config = {
    matcher:'/profile/:path*',
};

她就是我尝试过的:

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

export function profileMiddleware(request: NextRequest) {
  const userId = request.cookies.get("userId");

  if (!userId) {
    return NextResponse.redirect(
      new URL("/auth/login", request.nextUrl.origin).href
    );
  }
  return NextResponse.next();
}

export function authMiddleware(request: NextRequest) {
  const userId = request.cookies.get("userId");

  if (userId) {
    return NextResponse.redirect(
      new URL("/", request.nextUrl.origin).href
    );
  }
  return NextResponse.next();
}

export default {
  middleware: [
    {
      matcher: '/profile/:path*',
      handler: profileMiddleware,
    },
    {
      matcher: '/auth/:path*',
      handler: authMiddleware,
    },
  ],
};
javascript reactjs next.js web-frontend next.js13
1个回答
14
投票

您可以使用中间件链接来实现此目的。以下是实现这一目标的方法:

  1. 在您的
    middlewares
    文件夹中创建一个名为
    src
    的文件夹。
  2. stackHandler.ts
    文件夹中创建一个名为
    middlewares
    的文件并将以下内容粘贴到其中:

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();
}

  1. 创建另一个名为
    withUser.ts
    的文件并将以下内容粘贴到其中:

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);
  };
};

  1. 最后在
    middleware.ts
    文件夹中的
    src
    文件中粘贴以下内容:

import {
  stackMiddlewares
} from "@/middlewares/stackHandler";
import {
  withUser
} from "@/middlewares/withUser";

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

注意

定义 MiddlewareFactory 类型如下(如果不使用 Typescript,请忽略此):

import {
  NextMiddleware
} from "next/server";

export type MiddlewareFactory = (middleware: NextMiddleware) => NextMiddleware;

注意

您可以根据需要创建任意数量的中间件,例如

withUser
,方法是创建它们,然后将它们导入到
middlewares.ts
并将它们推送到
middlewares
数组中。

© www.soinside.com 2019 - 2024. All rights reserved.