map指令配合add_header可实现基于请求特征的条件式响应头添加:map在http块中定义变量映射,add_header引用该变量动态注入响应头,支持域名、请求头、user-agent等匹配,并需注意覆盖规则、同名头冲突及特殊字符处理。

直接用 map 指令配合 add_header,就能根据请求特征(比如域名、路径、请求头、IP段等)动态决定是否加、加什么值的响应头。关键在于:map 本身不输出内容,只做变量映射;而 add_header 支持引用这个变量——两者结合,就实现了“条件式加头”。
map 的作用是生成运行时变量
map 块在 Nginx 初始化阶段就加载,它把某个输入(如 $http_user_agent 或 $host)映射为一个自定义变量(如 $api_version),后续所有指令(包括 add_header)都能安全引用它。
- map 必须定义在
http块内,不能写在 server 或 location 里 - 匹配支持精确字符串、正则(用波浪线
~)、忽略大小写的正则(~*),也支持默认值(default) - 被映射的源变量必须是 Nginx 内置变量或已定义的变量,不能是任意字符串
常见请求特征的 map 映射示例
以下是在 http 块中定义的典型映射,用于支撑后续 add_header 动态策略:
- 按 Host 域名区分灰度环境:
map $host $env_label {<br> default "prod";<br> ~^staging\. example\.com$ "staging";<br> ~^beta\.example\.com$ "beta";<br>} - 按请求头识别 AB 测试分组:
map $http_x_ab_test_group $ab_flag {<br> default "";<br> "v2" "true";<br> "control" "false";<br>} - 按 User-Agent 判断客户端类型:
map $http_user_agent $client_type {<br> default "web";<br> ~*android "android";<br> ~*iphone|ios "ios";<br> ~*curl|httpie "cli";<br>}
在 location 中用 add_header 引用 map 变量
map 定义好后,在具体 location 里就可以用 add_header 动态注入响应头。注意两点:一是变量为空时不生效(Nginx 自动跳过);二是若需对非 200 响应也加头,记得加 always 参数。
- 给不同环境打标记:
location /api/ {<br> proxy_pass http://backend;<br> add_header X-Env $env_label;<br>} - 向 AB 测试用户返回分组标识:
location /feature/ {<br> proxy_pass http://feature_service;<br> add_header X-AB-Group $ab_flag always;<br>} - 按客户端类型提供差异化提示:
location /status {<br> return 200 "OK";<br> add_header X-Client $client_type;<br>}
注意事项与避坑点
实际部署时容易忽略几个细节,导致策略不生效或行为异常:
- add_header 在同一作用域内重复出现会覆盖前一个,不是追加;如需多个值,建议用单个 map 合并逻辑,或拆到不同 location
- map 不支持嵌套或复杂表达式,复杂判断(如同时满足 header + IP + path)建议改用 Lua(OpenResty)或在后端处理
- 如果后端本身也返回同名响应头(如 Server、X-Powered-By),Nginx 的 add_header 会和它共存,浏览器收到两个同名头——这可能触发兼容性问题;可用
proxy_hide_header先隐藏后端头,再用 add_header 统一输出 - map 变量值若含空格或特殊字符,add_header 会原样输出,无需额外引号;但作为 header 值,仍需符合 HTTP 规范(避免控制字符)










