map必须定义在http块顶层,用于将请求参数、请求头等源变量映射为新变量,location中通过proxy_pass http://$variable;引用实现动态路由,且对应upstream须预先声明并严格匹配。

location 块本身不能定义 map,map 必须放在 http 块顶层。真正起作用的是:在 http 中用 map 提前把某个输入(比如参数、请求头、IP 地理信息)映射成一个变量,然后 location 里直接引用这个变量做 proxy_pass。
map 必须定义在 http 块中
map 是全局变量映射机制,只允许出现在 http{} 范围内。它不支持嵌套,也不能写在 server 或 location 里。例如:
- 从 URL 参数提取值:$arg_backend 自动对应 ?backend=xxx 中的 xxx
- 从请求头取值:$http_x_route 对应 X-Route: api_v2 这样的 header
- 从地理 IP 提取:$geoip2_data_country_code(需配合 geoip2 模块和 mmdb 库)
- 映射结果存入新变量,如 $upstream_backend,供后续 location 使用
location 中引用映射变量完成调度
proxy_pass 支持变量形式,但有严格限制:
- ✅ 正确写法:proxy_pass http://$upstream_backend;(注意末尾无路径,且 http:// 后直接跟变量)
- ❌ 错误写法:proxy_pass http://$upstream_backend/api;(加路径会导致原始 URI 被丢弃,变量也不生效)
- 路径由 location 定义决定,比如 location /api/ { ... },Nginx 会自动把 /api/ 后的部分拼接到 upstream 目标后
配套 upstream 必须提前声明
map 中出现的每个值(如 backend_v1、asia_backend),都必须有对应 upstream 块声明,否则会返回 502:
- 每个 upstream 名称要与 map 输出值完全一致(区分大小写)
- 建议为每个 upstream 设置至少一台 server,并配置健康检查或备用节点
- default 映射值(如 backend_default)也必须有对应 upstream,避免未命中时失败
安全与健壮性不能省略
仅靠 map 映射容易被恶意参数绕过,需叠加防护:
- 过滤空值或非法字符:在 map 中添加 "" backend_default; 和 ~*[^\w._-] backend_default;
- 限制调用来源:用 allow/deny 或 valid_referers 控制哪些域名或 IP 可传参
- 开启调试日志:加 log_format 记录 $arg_backend 和 $upstream_backend,便于排查映射是否生效











