You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中间件中fetch无法正常工作,引发重定向循环错误

问题分析与解决

问题根源

你遇到的重定向死循环,核心原因有两个:

  • req.cookies无法直接修改:Next.js中间件里req.cookies是只读对象,直接调用req.cookies.delete("token")不会真正清除Cookie,无效令牌会一直存在,反复触发重定向逻辑。
  • 重定向后中间件重复执行:你的matcher包含/login,重定向到/login后中间件会再次运行,此时无效令牌仍未被清除,第三个判断块会再次发起fetch请求并失败,继续重定向,形成循环。

修复后的代码

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

export async function middleware(req: NextRequest) {
  const url = req.nextUrl.clone();

  // 已登录用户访问/login,重定向到首页
  if (req.nextUrl.pathname === "/login" && req.cookies.has("token")) {
    url.pathname = "/";
    return NextResponse.redirect(url);
  }

  // 未登录用户访问非公开路由,重定向到/login
  if (
    !req.cookies.has("token") &&
    req.nextUrl.pathname !== "/login" &&
    !req.nextUrl.pathname.startsWith("/_next")
  ) {
    url.pathname = "/login";
    return NextResponse.redirect(url);
  }
  
  // 验证令牌有效性
  if (req.cookies.has("token")) {
    const token = req.cookies.get("token")?.value;
    if (!token) {
      // 令牌格式异常,直接清除并重定向
      url.pathname = "/login";
      const response = NextResponse.redirect(url);
      response.cookies.delete("token");
      return response;
    }

    try {
      const userRes = await fetch(`http://10.129.23.206:8080/api/user`, {
        headers: {
          "Authorization": `Bearer ${token}`,
        }
      });

      if (!userRes.ok) {
        // 令牌无效,清除Cookie并重定向
        url.pathname = "/login";
        const response = NextResponse.redirect(url);
        response.cookies.delete("token");
        return response;
      }
    } catch (err) {
      // 处理后端请求失败的情况(如服务不可用)
      url.pathname = "/login";
      const response = NextResponse.redirect(url);
      response.cookies.delete("token");
      return response;
    }
  }

  // 所有验证通过,放行请求
  return NextResponse.next();
}

export const config = {
  matcher: ["/", "/create", "/search", "/:slug*", "/login"],
};

关键修复点

  • 正确清除Cookie:通过NextResponse对象的cookies.delete("token")操作,才能真正清除客户端的Cookie,确保后续请求不再携带无效令牌。
  • 获取令牌的实际值:req.cookies.get("token")返回的是Cookie对象,必须取value属性才能得到正确的令牌字符串,避免Authorization头格式错误。
  • 添加异常捕获:处理fetch请求失败的场景(比如后端服务宕机),避免中间件抛出未捕获错误导致流程中断。
  • 终止循环:清除Cookie后重定向到/login,再次运行中间件时,req.cookies.has("token")会返回false,第三个判断块不会执行;同时当前路径是/login,第二个判断块也不会触发重定向,循环就此终止。

内容的提问来源于stack exchange,提问作者Loran Maes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:23:27