nginx 多域名跳转应统一用 $request_uri 保留完整查询参数;推荐 return 302 配独立 server 块或 map 集中映射,目标 url 必带协议,禁用 $uri?$args 拼接及 if 中 return。

Nginx 中处理多域名跳转并保留原始查询参数,核心是统一使用 $request_uri 变量,它天然包含路径和完整查询字符串(如 /path?utm_source=ad&v=2),无需手动拼接,避免空 ?、参数丢失或编码异常。
用 return 指令配多域名 302 跳转
适合多个旧域名临时指向同一新目标,语义清晰、执行高效、无正则开销:
- 在每个对应
server块中单独配置,server_name写明要匹配的旧域名 -
return 302后跟完整目标 URL(含协议 + 新域名)+$request_uri - 示例:将
promo.a.com、offer.b.net都临时跳到https://event.new.org
server {
listen 80;
server_name promo.a.com;
return 302 https://event.new.org$request_uri;
}
server {
listen 80;
server_name offer.b.net;
return 302 https://event.new.org$request_uri;
}
用 map 实现集中管理多域名映射
当旧域名数量较多、目标地址有差异(比如按域名分发到不同活动页),可用 map 提前定义跳转关系,再在通用 server 块中复用:
-
map块写在http级,不参与请求处理,只做变量映射 - 目标值必须加双引号(尤其含特殊字符或变量时)
- 示例:
http {
map $host $target_url {
default "";
promo.a.com "https://event.new.org";
offer.b.net "https://campaign.new.org";
test.c.dev "https://staging.new.org";
}
server {
listen 80;
server_name promo.a.com offer.b.net test.c.dev;
# 只对有映射的域名生效,避免空跳转
if ($target_url = "") {
return 444;
}
return 302 $target_url$request_uri;
}
}
关键细节不能漏
- ✅ 目标 URL 必须带协议(
https://或http://),否则变成站内相对跳转 - ✅
$request_uri不加引号也能用,但若目标中混用其他变量(如$scheme),整个 URL 需用双引号包裹 - ❌ 不要用
$uri?$args拼接:$args为空时会留下孤立?,部分 CDN 或客户端处理异常 - ❌ 避免把
return放在if块里(Nginx 官方不推荐),优先用map或独立server块
上线前务必验证
- 用
curl -I测试带参请求:curl -I http://promo.a.com/2024?ref=test&x=1
输出中应含HTTP/1.1 302 Found和Location: https://event.new.org/2024?ref=test&x=1 - 检查浏览器无痕模式下是否跳转正常,防止本地缓存干扰判断











