Next.js Redirect场景下req.headers.referer缺失,如何获取原始请求URL
解决方案
依赖referer头获取原始URL本身是不可靠的,该头由客户端主动发送,不属于HTTP协议强制要求的字段,你生产环境请求中的okhttp/4.9.1客户端默认就不会携带该字段,同时生产环境的安全策略、反向代理规则也可能会剥离该字段,建议改用以下可靠方案实现:
方案1:修改重定向规则透传路径参数
直接在next.config.ts的重定向配置中,把匹配到的原始路径作为查询参数传递给API路由,再拼接协议、域名即可得到完整原始URL,改造成本最低。
修改后的next.config.ts配置:
{ source: '/user/:path*', // 把完整原始路径作为查询参数传递,保留/user前缀避免拼接错误 destination: '/api/forward/forward?originalPath=/user/:path*', permanent: true, }
API路由中拼接原始URL的示例:
// pages/api/forward/forward.ts 示例 export default function handler(req, res) { const protocol = req.headers['x-forwarded-proto'] || 'http' const host = req.headers.host const originalPath = req.query.originalPath as string const fullOriginalUrl = `${protocol}://${host}${originalPath}` // 后续使用fullOriginalUrl完成转发逻辑 }
方案2:使用Next.js Middleware处理转发
如果需要获取更完整的原始请求信息,建议放弃next.config.ts的静态重定向规则,改用Next.js中间件处理路由转发,中间件中可以直接拿到完整的原始请求URL,还可以自由透传自定义请求头。
根目录新增middleware.ts文件示例:
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { // 匹配/user开头的所有路径 if (request.nextUrl.pathname.startsWith('/user/')) { // 直接获取完整原始请求URL const originalUrl = request.nextUrl.href // 重写到API路由 const forwardDestination = new URL('/api/forward/forward', request.url) const rewriteResponse = NextResponse.rewrite(forwardDestination) // 把原始URL写入自定义请求头传递给API路由 rewriteResponse.headers.set('X-Original-Url', originalUrl) return rewriteResponse } } export const config = { matcher: '/user/:path*', }
API路由中直接读取自定义头即可:
const originalUrl = req.headers['x-original-url'] as string
方案3:反向代理层注入原始请求头
如果不想修改Next.js侧的逻辑,可以在生产环境的反向代理(你请求头中出现的sozu-id说明你使用了Sozu反向代理)中添加配置,将原始请求URI写入自定义请求头,API路由直接读取该头拼接原始URL即可。
内容的提问来源于stack exchange,提问作者Jeulin-L Michael
相关产品推荐
相关产品推荐

