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

Next.js中间件报错:NextResponse需用new调用+角色路由保护咨询

问题1:「Class constructor NextResponse cannot be invoked without 'new'」报错原因及修复

报错原因

你直接把NextResponse当成普通函数调用(NextResponse(new URL("/", request.url))),但NextResponse是一个类,必须通过它的静态方法(比如redirect、rewrite)来创建响应,不能直接调用类本身。

修复后的核心代码

把所有返回响应的语句替换为NextResponse.redirect:

// 替换原return语句
return NextResponse.redirect(new URL("/", request.url));
问题2:角色路由保护的优化方案

1. 修正路由匹配逻辑(关键bug修复)

你当前的el.startsWith(path)逻辑写反了,应该是path.startsWith(el)。比如要保护/profile下的所有子路由(如/profile/edit),需要判断当前路径是否以保护路由前缀开头,而非反过来。

2. 优化路由匹配效率

用Array.some替代find(some找到匹配项就停止遍历,性能更优),如果是精确匹配路由,也可以用Set存储提升查找速度:

// 精确匹配用Set
const customerProtectedRoutes = new Set(["/profile"]);
// 前缀匹配用数组+some
const adminProtectedRoutes = ["/admin", "/dashboard"];

// 前缀匹配判断示例
const isAdminPath = adminProtectedRoutes.some(route => path.startsWith(route));

3. 修复用户信息获取的环境适配问题

在middleware中不能使用客户端的getCookie方法,要通过request.cookies获取token,修改getLoginUserDetail函数:

// 修改函数,接收request参数
export const getLoginUserDetail = async (request) => {
  try {
    // 从middleware的request对象中获取cookie
    const auth_token = request.cookies.get("auth_token")?.value;
    if (!auth_token) return null;

    const headers = new Headers();
    headers.append("Content-Type", "application/json");
    headers.append("authorization", auth_token);
    
    const response = await fetch(`${baseUrl}/api/v1/auth/account`, {
      method: "GET",
      headers: headers,
    });

    if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
    const data = await response.json();
    return data.user;
  } catch (error) {
    console.log({ error });
    return null;
  }
};

// 在middleware中调用时传入request
const user = await getLoginUserDetail(request);

4. 利用matcher减少middleware执行次数

通过config.matcher限定middleware只处理需要权限校验的路由,避免无意义的执行:

export const config = {
  matcher: [
    /*
     * 匹配所有路径,排除:
     * 1. API路由(若无需保护API可排除)
     * 2. 静态资源文件
     * 3. /favicon.ico等静态文件
     */
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

5. 优化权限判断的代码结构

把权限判断拆分为独立函数,提升代码可读性和可维护性:

function isCustomerProtected(path) {
  return ["/profile"].some(route => path.startsWith(route));
}

function isAdminProtected(path) {
  return ["/admin"].some(route => path.startsWith(route));
}

function isDisallowedForLoggedIn(path) {
  return ["/login", "/signup"].includes(path);
}

export async function middleware(request) {
  const user = await getLoginUserDetail(request);
  const path = request.nextUrl.pathname;

  // 避免已在目标路径时重复重定向
  if (path === "/") return NextResponse.next();

  if (!user && (isCustomerProtected(path) || isAdminProtected(path))) {
    return NextResponse.redirect(new URL("/", request.url));
  }

  if (user && isDisallowedForLoggedIn(path)) {
    return NextResponse.redirect(new URL("/", request.url));
  }

  if (user?.role !== "super-admin" && isAdminProtected(path)) {
    return NextResponse.redirect(new URL("/", request.url));
  }

  return NextResponse.next();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:55:34