如何在Next.js中间件修改Request对象并让API路由访问新增属性?
在Next.js中间件中传递自定义属性到API路由的解决方案
直接在中间件的Request对象上挂载属性无法传递到API路由,因为两者属于独立的请求实例,属性不会自动同步。以下是几种可行的实现方式:
方法一:通过自定义请求头传递(推荐用于字符串/序列化数据)
中间件中克隆请求并添加自定义请求头,API路由从请求头中读取对应值:
// middleware.js import { NextResponse } from 'next/server'; export function middleware(request) { // 创建请求头副本,避免修改原对象 const requestHeaders = new Headers(request.headers); requestHeaders.set('x-custom-name', 'foo'); return NextResponse.next({ request: { headers: requestHeaders, }, }); }
API路由代码:
// pages/api/hello.js export default async function handler(req, res) { // HTTP头不区分大小写,但Node.js会统一转小写 const name = req.headers['x-custom-name']; console.log(name); // 输出 "foo" res.status(200).json({ name }); }
方法二:通过URL查询参数传递(适合简单数据)
中间件修改请求URL的查询参数,API路由从req.query中读取:
// middleware.js import { NextResponse } from 'next/server'; export function middleware(request) { const url = request.nextUrl.clone(); // 添加自定义查询参数 url.searchParams.set('customName', 'foo'); return NextResponse.rewrite(url); }
API路由代码:
// pages/api/hello.js export default async function handler(req, res) { const name = req.query.customName; console.log(name); // 输出 "foo" res.status(200).json({ name }); }
方法三:传递复杂对象(需序列化)
如果要传递对象等复杂数据,可先序列化为JSON字符串再通过请求头传递:
// middleware.js import { NextResponse } from 'next/server'; export function middleware(request) { const customData = { name: 'foo', role: 'admin' }; const requestHeaders = new Headers(request.headers); // 序列化为JSON字符串避免编码问题 requestHeaders.set('x-custom-data', JSON.stringify(customData)); return NextResponse.next({ request: { headers: requestHeaders, }, }); }
API路由代码:
// pages/api/hello.js export default async function handler(req, res) { const dataStr = req.headers['x-custom-data']; const customData = JSON.parse(dataStr); console.log(customData.name); // 输出 "foo" res.status(200).json(customData); }
类型扩展(TypeScript项目可选)
如果使用TypeScript,可扩展类型定义以获得类型提示:
在项目根目录创建types/next.d.ts文件:
import type { NextRequest } from 'next/server'; import type { IncomingMessage } from 'http'; declare module 'next/server' { interface NextRequest { customName?: string; } } declare module 'http' { interface IncomingMessage { customName?: string; } }
注意:类型扩展仅用于类型提示,实际属性传递仍需依赖上述请求头/查询参数的方式。
内容的提问来源于stack exchange,提问作者YulePale
相关产品推荐
相关产品推荐

