You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:45:34