如何修改Next.js中间件Rewrite/Proxy的响应Header?
解决Next.js Middleware重写后302重定向Location头域名替换问题
你的核心需求是拦截被代理服务器返回的302/301重定向响应,把Location头里的目标域名替换成自己的域名。由于无法修改目标服务器配置,最可靠的方案是自己发起请求并手动处理响应头,下面是具体实现:
// Assume all of this is running at `https://www.website.com` // This middleware is applied to: `/some-path*` export async function middleware(request: NextRequest) { const targetHost = 'www.otherwebsite.com'; const originHost = 'www.website.com'; // 构造目标请求URL const targetUrl = new URL(request.url); targetUrl.host = targetHost; targetUrl.protocol = 'https'; targetUrl.port = ''; // 复制并调整请求头,适配目标服务器 const headers = new Headers(request.headers); headers.set('Origin', `https://${targetHost}`); headers.set('Host', targetHost); try { // 发起请求到目标服务器,禁用自动跟随重定向 const response = await fetch(targetUrl.toString(), { method: request.method, headers: headers, body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined, redirect: 'manual', }); // 复制响应头准备修改 const responseHeaders = new Headers(response.headers); const location = responseHeaders.get('Location'); // 处理3xx重定向,替换Location中的域名 if ([301, 302, 303, 307, 308].includes(response.status) && location) { const locationUrl = new URL(location); locationUrl.host = originHost; locationUrl.protocol = request.nextUrl.protocol; responseHeaders.set('Location', locationUrl.toString()); } // 返回修改后的响应给用户 return new NextResponse(response.body, { status: response.status, statusText: response.statusText, headers: responseHeaders, }); } catch (error) { // 请求失败时返回错误页 return new NextResponse('Proxy error', { status: 500 }); } };
关键细节说明
- 禁用自动重定向:通过
redirect: 'manual'让fetch不自动跟随3xx跳转,这样才能拿到原始的重定向响应并修改Location头。 - 完整转发请求信息:复制原请求的方法、头信息和请求体,确保目标服务器能正确处理请求。
- 精准替换域名:解析Location头为URL对象,直接替换主机名,避免字符串替换可能带来的错误(比如路径中包含目标域名的情况)。
关于你提到的两个方案
- 手动发起fetch的方案:思路完全正确,上面的代码就是这个方案的完整实现,解决了你可能遇到的细节问题(比如请求体转发、响应头复制等)。
- 依赖目标服务器额外头的方案:由于你无法修改被代理主机,这个方案直接不可行,不用考虑。
内容的提问来源于stack exchange,提问作者Daniel Brown
相关产品推荐
相关产品推荐

