Next.js v13代理后Docker环境下多域名重定向至主域名方案
多域名重定向至主域名的解决方案(Next.js 13 + Docker + 代理场景)
问题背景
持有example1.com、example2.com、example3.com等多个域名,需将所有请求301永久重定向到主域名example.com,同时完整保留原请求的路径、查询参数和哈希值。当前使用Next.js v13部署在Docker容器中,且服务处于代理服务器后方,导致Server端获取到的url.host始终是localhost:3000,现有Middleware代码无法触发重定向逻辑。
核心原因
代理服务器转发请求时,Next.js默认读取容器内部的主机地址(localhost:3000),而非用户实际访问的外部域名。原代码中通过url.host判断域名的逻辑自然无法生效,因为永远匹配不到真实访问的域名。
可行解决方案
1. 配置Next.js信任代理并启用转发头解析
在项目根目录的next.config.js中添加配置,让Next.js信任代理服务器,并允许从请求头中读取真实访问域名:
/** @type {import('next').NextConfig} */ const nextConfig = { // 信任代理服务器(生产环境可指定具体代理IP提升安全性) trustHost: true, async headers() { return [ { source: '/(.*)', headers: [ // 允许代理传递真实主机头和协议头 { key: 'X-Forwarded-Host', value: process.env.NEXT_PUBLIC_MAIN_DOMAIN || 'example.com' }, { key: 'X-Forwarded-Proto', value: 'https' }, // 根据实际协议调整为http/https ], }, ]; }, }; module.exports = nextConfig;
2. 修改Middleware代码,从请求头获取真实域名
不再依赖req.nextUrl.host,转而读取代理传递的X-Forwarded-Host头判断当前访问域名:
/* eslint-disable @next/next/no-server-import-in-page */ import { NextResponse, NextRequest } from 'next/server'; // 主域名及需重定向的域名列表 const MAIN_DOMAIN = 'example.com'; const REDIRECT_DOMAINS = ['example1.com', 'example2.com', 'example3.com']; export async function middleware(req: NextRequest) { // 优先从转发头取真实域名, fallback到host头 const realHost = req.headers.get('x-forwarded-host') || req.headers.get('host') || MAIN_DOMAIN; // 判断是否需要重定向:属于指定域名列表,或不是主域名的子域名 if (REDIRECT_DOMAINS.includes(realHost) || !realHost.endsWith(MAIN_DOMAIN)) { const url = req.nextUrl.clone(); // 替换为主域名,自动保留原路径、参数、哈希 url.host = MAIN_DOMAIN; // 返回301永久重定向(SEO友好),可按需改为302临时重定向 return NextResponse.redirect(url, 301); } return NextResponse.next(); } // 指定Middleware对所有路径生效 export const config = { matcher: '/:path*', };
3. 确保代理服务器正确传递转发头
以Nginx为例,需在代理配置中添加以下指令,保证真实域名和协议头被传递到Next.js容器:
location / { proxy_pass http://localhost:3000; # 对应Docker容器内部端口 proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
验证要点
- 重启Next.js服务和代理服务器,确保配置生效
- 访问
example1.com/test?foo=bar#hash,检查是否跳转到example.com/test?foo=bar#hash - 查看服务器日志,确认
realHost变量获取到的是实际访问的域名
内容的提问来源于stack exchange,提问作者Prokop Simek
相关产品推荐
相关产品推荐

