nginx 通过 map 指令在 http 块顶层定义条件变量,实现 proxy_set_header 的动态设置;map 性能好、语法清晰,可基于 $http_x_forwarded_for、$args 等变量判断,空值 header 自动忽略;禁止在 if 或 location 中直接使用 proxy_set_header。

Nginx 本身不支持在 proxy_set_header 中直接写条件表达式(比如 if 块内使用),但可以通过变量 + map 指令实现安全、高效的动态 header 设置。
用 map 指令预定义条件变量
map 是 Nginx 最推荐的条件映射方式,它在请求处理早期就完成变量赋值,性能好且语法清晰。不能在 location 或 if 中定义 map,必须放在 http 块顶层。
例如:根据请求头 X-Forwarded-For 是否存在,动态设置后端的 X-Real-IP:
http {
map $http_x_forwarded_for $real_ip {
"" $remote_addr; # 空时用客户端真实 IP
default $http_x_forwarded_for; # 非空时用代理链 IP
}
<pre class="brush:php;toolbar:false;">server {
location / {
proxy_pass https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e;
proxy_set_header X-Real-IP $real_ip;
}
}}
结合 $args 或 $request_uri 做路径/参数判断
可以基于 URL 参数或路径前缀控制 header 是否发送,比如只对带 ?debug=1 的请求添加调试头:
map $args $debug_header {
~*debug=1 "1";
default "";
}
<p>server {
location / {
proxy_pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a>;
proxy_set_header X-Debug $debug_header;</p><h1>若 $debug_header 为空字符串,该 header 实际不会发送给上游</h1><pre class="brush:php;toolbar:false;">}}
Nginx 会自动跳过值为空的 proxy_set_header,所以无需额外判断。
避免在 if 块中使用 proxy_set_header
if 在 location 中使用会导致配置不可靠(Nginx 官方明确警告),且 proxy_set_header 在 if 内可能被忽略或行为异常。以下写法不推荐:
# ❌ 错误示例:if + proxy_set_header 组合不可靠
location / {
if ($arg_env = "staging") {
proxy_set_header X-Env "staging"; # 实际不会生效
}
proxy_pass https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e;
}
- 所有 header 设置应统一放在
location顶层 - 条件逻辑全部交给
map处理,保持proxy_set_header干净简洁 - 变量名建议加前缀(如
$upstream_x_env)避免命名冲突
常见动态场景与对应变量
以下变量可直接用于 map 判断:
-
$host/$http_host→ 区分不同域名 -
$scheme→ 判断是 http 还是 https -
$http_user_agent→ 按客户端类型设 header(如移动端标记) -
$sent_http_content_type→ 响应类型相关(仅限post_action场景) -
$request_method→ 对 POST/PUT 请求添加特殊标识
注意:map 只能读取请求阶段变量,不能读取 upstream 响应后的值。











