Nginx的map模块可在http块中基于$host等变量定义动态映射,再通过proxy_set_header透传至后端;需确保map在http顶层、含default分支,支持字符串/空值/正则匹配,并可通过日志或add_header调试。

Nginx 的 map 模块可以基于请求变量(如 $host)定义动态映射关系,再结合 proxy_set_header 实现按域名差异化透传或改写请求头。关键在于:map 必须在 http 块中定义,且映射结果可被后续的 location 或 server 块引用。
定义基于 host 的头部值映射
在 http 块中使用 map 将不同域名映射为对应的 header 值(支持字符串、空值、变量嵌套):
http {
# 定义 $upstream_api_version 映射,根据 $host 动态取值
map $host $upstream_api_version {
default "v1";
api.example.com "v2";
staging.api.example.com "v1-staging";
beta.api.example.com "v2-beta";
}
<pre class="brush:php;toolbar:false;"># 可选:映射多个字段,比如透传不同的租户标识
map $host $x-tenant-id {
default "";
customer-a.example.com "tenant-a";
customer-b.example.com "tenant-b";
}}
在 proxy 配置中引用映射变量
在 location 或 server 块中,直接用 $变量名 赋值给 proxy_set_header。Nginx 会在每次请求时实时计算该变量值:
server {
listen 80;
server_name ~^(?<domain>.+)$;
<pre class="brush:php;toolbar:false;">location /api/ {
proxy_pass https://backend;
# 动态设置 X-API-Version
proxy_set_header X-API-Version $upstream_api_version;
# 动态设置 X-Tenant-ID(为空时不发送该头)
proxy_set_header X-Tenant-ID $x-tenant-id;
# 保持原始 Host,也可按需覆盖
proxy_set_header Host $host;
# 其他必要代理头
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}}
注意事项与常见技巧
实际使用中需注意以下几点,避免常见陷阱:
- map 必须在 http 块顶层定义,不能放在 server 或 location 内;否则会报错 “map directive is not allowed here”
- default 分支必须存在,否则未匹配域名时变量为空,可能导致 header 被设为空字符串(部分后端会拒绝空值)
-
空字符串值会被透传为真实空头,如需完全不发送某 header,应确保后端能忽略它,或用
map映射为一个特殊标记,再配合if(不推荐)或 Lua(进阶)做条件过滤 -
支持正则匹配 host,但 map 中的 key 不支持正则捕获变量;如需复杂匹配,可用
~*前缀(大小写不敏感正则),例如:~* \.staging\.example\.com$ "v1-staging" -
变量名区分大小写,且不能含短横线(-),建议用下划线命名,如
$x_tenant_id,再在proxy_set_header中转成标准格式X-Tenant-ID
验证与调试方法
可通过日志快速确认映射是否生效:
log_format debug_log '$host → $upstream_api_version | $x_tenant-id'; access_log /var/log/nginx/debug.log debug_log; <h1>或临时加响应头用于测试(仅开发环境)</h1><p>add_header X-Debug-Upstream-Version $upstream_api_version; add_header X-Debug-Tenant $x-tenant-id;
发起请求后检查 access log 或响应头,确认值是否符合预期。注意:add_header 在子请求中不继承,仅主请求可见。


















