Nginx 的 map 指令仅支持基于静态值的映射,不可动态变更,但可通过组合 set、rewrite 和内置变量实现参数提取与标准化;例如用 $arg_utm_source 映射渠道码,或用正则匹配 $arg_app_version 实现 API 版本路由,亦可处理 Header 与 Cookie 变量,但不支持嵌套、函数调用或外部数据访问。
在 Nginx 中,map 指令本身不支持“动态参数映射”——它只能基于变量的**静态值**做一对一或一对多的映射,且映射关系在配置加载时就已确定,运行时不可变。但你可以通过组合 map 与其它模块(如 set、rewrite、内置变量)来实现**看似动态的参数解析效果**,比如从 URL、Header 或 Cookie 中提取并映射关键字段。
map 最常用场景是从 $args 或 $query_string 中匹配特定参数值,并映射为新变量。注意:map 只能作用于字符串变量,不能直接解析 query 参数键值对,需配合正则提取(通常用 set + if 预处理,或借助 ngx_http_map_module 的模糊匹配能力)。
例如,想把不同来源的 utm_source 值统一映射为内部渠道码:
map $arg_utm_source $channel { default "unknown"; "google" "search_google"; "baidu" "search_baidu"; "~^wechat.*" "social_wechat"; "~^dy.*" "social_douyin";}
这里 $arg_utm_source 是 Nginx 内置变量,自动提取 URL 中 utm_source=xxx 的值;~^ 表示大小写敏感正则匹配,可覆盖带后缀的变体(如 wechat_app、wechat_mini)。
当需要先解析再映射(比如从 /api/v1/user?id=123&type=admin 中提取 id 并判断是否为数字),map 本身无法做数值校验或复杂逻辑,但可以分步走:
set + if(慎用)或 map 的正则能力初步清洗map 对清洗后的结果做归类proxy_set_header、fastcgi_param 或 location 路由示例:根据 app_version 参数映射 API 版本路由前缀
map $arg_app_version $api_prefix { "~^1.0." "/v1"; "~^2.[0-9]" "/v2"; "~^3..*" "/v3"; default "/v1";}location /api/ { proxy_pass https://backend$api_prefix$request_uri;}
map 支持任意变量,包括 $http_x_client_type、$cookie_device_id 等。例如,按设备类型 header 设置后端分组:
map $http_x_device_type $backend_group { "" "default"; "mobile" "mobile_pool"; "desktop" "web_pool"; "tablet" "mobile_pool"; default "default";}upstream mobile_pool { server 10.0.1.10:8080; }upstream web_pool { server 10.0.1.20:8080; }proxy_pass http://$backend_group;
注意:map 不支持嵌套或条件链式调用,所有映射必须在同一层完成;空字符串 "" 可匹配缺失 header,default 是兜底项。
map 是高效、无副作用的变量转换工具,但它不是编程语言:
$arg_id + 1)若真需运行时动态计算(如 JWT 解析、签名验证、AB 测试分流),应交给应用层(如 Lua via OpenResty)或上游服务处理,Nginx map 更适合作为轻量级、声明式的路由/标签预处理层。