Next.js中间件返回NextResponse.next()抛出TypeError如何解决
问题描述
我在Next.js 12.1.6版本中尝试为鉴权路由实现简易中间件,预期功能为校验认证请求头、验证令牌并根据校验结果执行对应处理逻辑。
参考公开示例的规则:
- 放行请求需要返回
NextResponse.next(),行为类似Express框架中调用next() - 终止请求则返回
new Response()
目前返回new Response()的拦截逻辑可正常运行,但调用NextResponse.next()时会抛出TypeError: resolver is not a function错误。
现有中间件代码
// _middleware.ts import { NextFetchEvent, NextRequest, NextResponse } from "next/server" const authMiddleware = async (req: NextRequest, ev: NextFetchEvent) => { if (validated) { return NextResponse.next() } else { return new Response("Unauthorized") } } export default authMiddleware
已尝试方案
- 基于
req.page.name调用NextResponse.rewrite()方法:动态URL场景下无法生效 - 调用
NextResponse.redirect():触发无限重定向循环
错误与环境信息
错误调用栈
Call Stack Object.apiResolver file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/api-utils/node.js (185:15) runMicrotasks <anonymous> processTicksAndRejections node:internal/process/task_queues (96:5) async DevServer.runApi file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/next-server.js (395:9) async Object.fn file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/base-server.js (496:37) async Router.execute file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/router.js (226:36) async DevServer.run file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/base-server.js (606:29) async DevServer.run file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/dev/next-dev-server.js (450:20) async DevServer.handleRequest file:/Users/adk/Projects/myproject/nextjs/node_modules/next/dist/server/base-server.js (321:20)
版本信息
- Next.js版本:12.1.6
- Node版本:16.15.1
项目文件结构
nextjs ├── package.json ├── next.config.js ├── tsconfig.json ├── pages │ ├── _app.tsx │ ├── api │ │ └── auth │ │ ├── _middleware.ts │ │ └── login.tsx │ └── index.tsx
根本原因
这个报错是Next.js 12.1.x版本的已知缺陷,和鉴权逻辑本身无关:
- 该版本中
NextResponse.next()的运行逻辑存在路径判断漏洞,仅能在普通页面路由层级的_middleware.ts中正常执行 - 放在
pages/api/**路径下的中间件调用NextResponse.next()时,运行时会错误进入API路由的处理器校验流程,找不到对应resolver函数就抛出当前错误 - 你把鉴权中间件放在
pages/api/auth/_middleware.ts路径下,刚好触发了这个bug。
修复方案
推荐方案(符合版本设计规范)
- 将中间件文件从
pages/api/auth/目录移动到pages/根目录,或使用Next.js 12.x正式支持的根目录middleware.ts位置,该位置的中间件可以同时拦截页面路由和API路由,不会触发resolver校验错误 - 配置路径匹配规则,只拦截需要鉴权的接口,精准跳过login等白名单路径,避免重定向循环、动态路由rewrite失效问题。调整后的参考代码如下:
// 若使用根目录middleware.ts,需额外导出matcher配置限定作用范围 export const config = { matcher: '/api/auth/:path*', } // 中间件逻辑 import { NextFetchEvent, NextRequest, NextResponse } from "next/server" const authMiddleware = async (req: NextRequest, ev: NextFetchEvent) => { // 跳过登录接口等不需要鉴权的路径 if (req.nextUrl.pathname === '/api/auth/login') { return NextResponse.next() } // 替换为实际的令牌校验逻辑 const validated = true if (validated) { return NextResponse.next() } return new Response("Unauthorized", { status: 401 }) } export default authMiddleware
- 删除原
pages/api/auth/路径下的旧中间件文件,重启本地开发服务即可正常运行。
临时兼容方案(不推荐)
如果不想移动中间件位置,可以在放行逻辑中不返回NextResponse.next(),直接隐式返回undefined,12.1.x版本运行时会自动继续执行后续API处理逻辑,不会触发报错。但该写法不符合Next.js中间件的标准规范,后续版本升级会直接失效。
内容的提问来源于stack exchange,提问作者ADK
相关产品推荐
相关产品推荐

