nginx路由配置进阶=location+map
在 Nginx 中,
map
是一个非常有用的指令,主要用于
根据某个变量的值映射出另一个变量的值。它通常用在
http
上下文中,用来创建自定义变量,这些变量的值是基于其他变量(通常是
$http_*
、
$args
、
$host
等)的值动态决定的。
一、基本语法
map $source_variable $target_variable {
default default_value;
value1 result1;
value2 result2;
...
}
参数说明:
map
:指令名称。$source_variable
:源变量,即你希望根据它的值来进行匹配的变量,比如$http_user_agent
、$arg_type
、$host
等。$target_variable
:目标变量,即 map 映射后生成的新变量,可以在后续的配置中引用,如$proxy_pass
、$log_format
等。default
(可选):当$source_variable
的值不匹配任何 case 时使用的默认值。value1
,value2
, …:源变量的可能取值,可以是字符串或正则表达式。result1
,result2
, …:对应匹配成功后,$target_variable
被设置的值。
二、使用场景示例
示例 1:根据 User-Agent 判断设备类型
http {
map $http_user_agent $is_mobile {
default 0;
"~*Android" 1;
"~*iPhone" 1;
"~*iPad" 1;
"~*Mobile" 1;
}
server {
listen 80;
server_name example.com;
location / {
if ($is_mobile) {
# 移动端逻辑
add_header X-Device "Mobile";
}
# 其它逻辑
add_header X-Device "Desktop";
}
}
}
🔍 解释:
- 我们通过检测
$http_user_agent
的内容,判断访问者是否使用移动设备。 - 如果匹配到 Android、iPhone、iPad 或 Mobile 关键字,则
$is_mobile
为1
,否则为0
。 - 然后在
server
或location
中可以根据$is_mobile
做不同的处理。
示例 2:根据请求参数设置变量
http {
map $arg_type $content_type {
default "application/json";
"xml" "application/xml";
"html" "text/html";
"json" "application/json";
}
server {
listen 80;
server_name api.example.com;
location /data {
add_header Content-Type $content_type;
return 200 "Content type is $content_type";
}
}
}
🔍 解释:
- 用户访问
http://api.example.com/data?type=xml
时,$arg_type
的值是xml
,那么$content_type
就会被映射为"application/xml"
。 - 如果没有传
type
或者传了未定义的值,默认是"application/json"
。
示例 3:基于域名设置不同后端
http {
map $host $backend {
hostnames;
default backend_default;
example.com backend_prod;
staging.example.com backend_staging;
dev.example.com backend_dev;
}
upstream backend_prod { server 10.0.0.1; }
upstream backend_staging { server 10.0.0.2; }
upstream backend_dev { server 10.0.0.3; }
upstream backend_default { server 10.0.0.99; }
server {
listen 80;
server_name _;
location / {
proxy_pass http://$backend;
}
}
}
🔍 解释:
hostnames;
表示允许使用通配或简化的主机名匹配(如不写www.
前缀等),但在此例中未用到高级功能。- 根据
$host
(即客户端请求的域名),选择不同的upstream
后端服务。 - 这种方式非常适合多租户、多环境部署。
三、注意事项
map
指令必须放在http
块中,不能放在server
或location
中。map
是在 Nginx 启动时解析的,运行时不会重新加载映射关系(除非重启或重载配置)。- 匹配优先级:按照书写顺序从上到下匹配,一旦匹配到就不会继续往下匹配,所以把更具体的值放前面。
- 正则表达式匹配:以
~
开头表示区分大小写的正则,~*
表示不区分大小写的正则。 default
是可选的,如果不指定,未匹配到的值会导致$target_variable
为空。
四、正则匹配示例
http {
map $http_referer $referer_type {
default "direct";
"~*google\.com" "google";
"~*baidu\.com" "baidu";
"~*yandex\.ru" "yandex";
}
server {
listen 80;
server_name example.com;
location / {
add_header X-Referer-Type $referer_type;
}
}
}
🔍 解释:
- 根据
$http_referer
(来源页面),判断访客是从 Google、百度还是 Yandex 搜索引擎跳转过来的,分别标记为google
、baidu
、yandex
,否则为direct
。
五、总结
功能 | 说明 |
---|---|
作用 | 根据一个变量的值,动态生成另一个变量 |
使用位置 | 仅能在 http 块中使用 |
常见用途 | 设备检测、A/B测试、多环境路由、日志分类、权限控制等 |
变量类型 | 源变量和目标变量都是 Nginx 变量(如 $http_xxx , $arg_xxx , $host 等) |
匹配方式 | 支持精确匹配、正则匹配,支持 default 默认值 |