Next.js中间件获取URL与预期不符,无法提取acct参数求助
Next.js中间件无法获取正确URL查询参数的问题解决
问题场景与现象
- 用户验证通过后会被重定向到带
acct(JWT格式)查询参数的目标URL,需要在Next.js中间件中提取该参数验证JWT是否过期。 - 中间件中使用
req.nextUrl.searchParams.get('acct')返回undefined,排查发现中间件获取的URL为http://localhost:6550/_next/webpack-hmr,与浏览器地址栏显示的statdev.smarti.me/?acct={jwt}不符。 - 首页组件中使用
useRouter()钩子可正常获取该查询参数,应用部署在公司服务器,通过SSH在VSCode或终端访问。
现有中间件代码
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; const { URL_OLOGIN, APP_CLIENT_ID } = process.env; export function middleware(req: NextRequest) { const acct = req.nextUrl.searchParams.get("acct"); if (acct) { console.log(acct); } else { return NextResponse.redirect(`${URL_OLOGIN}/?cli=${APP_CLIENT_ID}`); } return NextResponse.next(); }
问题原因分析
- 中间件拦截范围过大:Next.js中间件默认会拦截所有请求,包括Webpack热更新(
/_next/webpack-hmr)、静态资源加载等非业务请求,这类请求本身不带acct参数,导致触发错误的重定向逻辑。 - 服务器代理配置问题:公司服务器的反向代理(如Nginx)可能未正确传递原始请求的URL和查询参数,导致中间件拿到的是内部转发的本地URL,而非用户实际访问的外部地址。
解决办法
1. 过滤非业务请求
在中间件中添加路径判断,只处理目标业务路由(比如首页/),跳过其他资源请求:
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; const { URL_OLOGIN, APP_CLIENT_ID } = process.env; export function middleware(req: NextRequest) { // 仅处理首页请求,跳过热更新、静态资源等请求 if (req.nextUrl.pathname !== '/') { return NextResponse.next(); } const acct = req.nextUrl.searchParams.get("acct"); if (acct) { console.log(acct); // 此处添加JWT过期验证逻辑 } else { return NextResponse.redirect(`${URL_OLOGIN}/?cli=${APP_CLIENT_ID}`); } return NextResponse.next(); }
2. 配置中间件匹配规则
在next.config.js中设置matcher,限定中间件仅作用于特定路由,避免全局拦截:
// next.config.js module.exports = { middleware: { matcher: ['/'], // 仅匹配首页路由 }, };
3. 检查服务器反向代理配置
如果是部署环境的问题,确认服务器的反向代理(如Nginx)配置是否正确传递原始请求信息,示例Nginx配置需添加:
proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme;
确保Next.js能获取到用户实际访问的外部URL和查询参数。
内容的提问来源于stack exchange,提问作者Bátorfalvi Géza
相关产品推荐
相关产品推荐

