我可以在自托管环境中运行新的Next.js中间件吗?

monwx1rj  于 2022-11-29  发布在  其他
关注(0)|答案(2)|浏览(159)

我正在使用Next.js构建一个应用程序,然后将它们重定向到我们的主Web应用程序。在Next.js版本12发布之前,我已经使用next-connect对每个API请求运行一个中间件函数,以从令牌反序列化用户,或者在刷新令牌过期时刷新访问令牌。我现在想从next-connect迁移到新的api middleware,但首先我不确定这些函数在自托管环境中如何执行,因为使用Vercel时,它们将作为边缘函数部署,但它们在自托管环境中如何工作?是否与普通的Express中间件一样?
我还得到了eval not allowed in Middleware pages/api/_middleware错误,因为标准的jsonwebtoken包不允许在边缘函数中使用。这个问题表明我必须使用轻量级包@tsndr/cloudflare-worker-jwt,即使我不打算使用边缘函数,而是自己部署应用程序。
这是我尝试在每个api请求上通过_middleware文件运行的中间件:

export async function middleware(req: NextApiRequestWithUser) {
  const { access_token, refresh_token } = req.cookies;

  if (!access_token) {
    return NextResponse.next();
  }

  try {
    // Verify token
    const { payload, expired } = verifyAccessToken(access_token);

    if (payload) {
      if (!payload.userId) {
        return new Response("User id is missing in JWT payload.", {
          status: 401,
        });
      }
      const currentUser = await User.findById(payload.userId).lean();
      if (!currentUser) {
        return new Response(
          "The user belonging to this token no longer exist.",
          {
            status: 401,
          }
        );
      }
      req.user = currentUser;
    }

    const { payload: refreshPayload } = verifyRefreshToken(refresh_token);

    if (!refreshPayload) return NextResponse.next();

    const user = await User.findOne({ _id: refreshPayload.userId });

    if (user?.refreshToken === refresh_token && expired) {
      console.log("Refreshing access token");
      const newAccessToken = generateAccessToken(refreshPayload.userId);
      NextResponse.next().cookie(access_token, newAccessToken, {
        domain: "localhost",
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        path: "/",
      });
      return NextResponse.next();
    }

    return NextResponse.next();
  } catch (error) {
    console.log(error);
    return NextResponse.next();
  }
}
bf1o4zei

bf1o4zei1#

是的,你可以在一个自托管的环境中运行Next.js中间件。你提到的eval not allowed错误实际上只是一个警告。关于它的更多细节可以在this Github issue中找到。用户gustavo-dev对Edge Functions和中间件之间的区别给出了深刻的解释:
边缘功能与CDN类似(但不同)。
CDN(Content Delivery Network,内容交付网络)用于快速提供静态内容,因此需要将其放置在靠近客户端的位置。例如,这种方法的缺点是无法根据客户端的位置向不同的客户端交付自定义内容。
另一个解决这个问题的方法是在服务器上处理每个请求(SSR)。然而,现在的缺点是速度,因为处理这些请求的服务器不一定靠近最终用户。
这就是Edge Functions的用武之地!它们的工作方式与CDN类似,但它们允许您在Edge上运行服务器端逻辑,靠近您的客户端,这使我们能够同时实现速度和动态性。
另一方面,中间件是一个在请求完成之前运行的函数。如果你以前使用过ExpressJ,你应该熟悉这个概念。它们可以修改请求/响应对象,在身份验证等方面很有用。
因此,中间件不一定是边缘函数,边缘函数也不一定是中间件。但是,当部署到Vercel时,中间件是在边缘函数中运行的唯一代码。

ycggw6v2

ycggw6v22#

内容:

我遇到了这个问题,花了几个小时来寻找解决方案,现在开始共享,所以next-js中间件是一种叫做边缘函数的东西,不用担心,我对这个也不了解,整个事情是你不能运行中间件的依赖性,因为它包含了叫做动态代码的东西,而不是“eval”,

**案例1:**您JWT依赖项或任何其他依赖项与next-js中间件之间存在问题。

  • 使用另一个依赖项,您必须为您的用例找到另一个依赖项,例如对于“jsonwebtoken”,有另一个依赖项称为jose
    **case 2:**编写类似“eval”的动态代码的可能性很低。
  • 只需找到一种方法来绕过您正在编写的动态代码

相关问题