Nginx location
多条件匹配
1. 概述
在 Nginx 中,location
指令用于匹配请求的 URI,并根据匹配结果执行相应的逻辑。虽然 location
本身是基于单一匹配规则的,但可以通过多种方式实现多个条件的匹配逻辑。
2. 实现多条件匹配的方式
2.1 使用多个 location
块
Nginx 支持定义多个 location
块,每个 location
块可以匹配不同的条件。Nginx 会根据优先级选择最匹配的 location
。
示例:
server {
listen 80;
# 匹配 /xianyang/ 路径
location /xianyang/ {
proxy_pass http://10.175.12.236:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
# 匹配 /api/ 路径
location /api/ {
proxy_pass http://10.175.12.237:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
# 默认匹配
location / {
root html;
index index.html;
}
}
优先级规则:
- 精确匹配(
location = /path
)优先级最高。 - 正则表达式匹配(
location ~ /path
)次之。 - 前缀匹配(
location /path
)优先级最低。
2.2 使用正则表达式匹配多个条件
如果需要在一个 location
块中匹配多个路径,可以使用正则表达式。
示例:
server {
listen 80;
# 匹配 /xianyang/ 或 /api/ 路径
location ~ ^/(xianyang|api)/ {
proxy_pass http://10.175.12.236:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
# 默认匹配
location / {
root html;
index index.html;
}
}
说明:
~
表示启用正则表达式匹配。^/(xianyang|api)/
表示匹配以/xianyang/
或/api/
开头的路径。
2.3 使用 map
指令动态选择后端
如果需要根据路径或其他条件动态选择后端服务器,可以使用 map
指令。
示例:
http {
# 定义 $backend 变量,根据路径动态选择后端
map $uri $backend {
default http://default-backend:8080;
"~^/xianyang/" http://10.175.12.236:8080;
"~^/api/" http://10.175.12.237:8080;
}
server {
listen 80;
location / {
proxy_pass $backend; # 使用动态选择的 $backend
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
说明:
map $uri $backend
:- 根据
$uri
的值动态设置$backend
。 ~^/xianyang/
匹配以/xianyang/
开头的路径。~^/api/
匹配以/api/
开头的路径。
- 根据
2.4 使用 if
条件实现多个条件
虽然不推荐过度使用 if
,但在某些场景下可以通过 if
实现多个条件的匹配。
示例:
server {
listen 80;
location / {
# 根据路径动态选择后端
if ($uri ~* "^/xianyang/") {
proxy_pass http://10.175.12.236:8080;
}
if ($uri ~* "^/api/") {
proxy_pass http://10.175.12.237:8080;
}
# 默认后端
if ($uri !~* "^/xianyang/" && $uri !~* "^/api/") {
root html;
index index.html;
}
}
}
注意事项:
if
的性能较低,尽量避免在location
中过度使用。if
条件中不能直接使用proxy_pass
和其他指令的组合,需要小心使用。
2.5 使用 try_files
实现多条件匹配
如果需要根据文件或路径的存在性来选择不同的处理逻辑,可以使用 try_files
。
示例:
server {
listen 80;
location / {
# 尝试匹配文件,如果不存在则转发到后端
try_files $uri @backend;
}
location @backend {
# 根据路径选择后端
if ($uri ~* "^/xianyang/") {
proxy_pass http://10.175.12.236:8080;
}
if ($uri ~* "^/api/") {
proxy_pass http://10.175.12.237:8080;
}
# 默认后端
proxy_pass http://default-backend:8080;
}
}
说明:
try_files $uri @backend
:- 尝试匹配文件路径
$uri
。 - 如果文件不存在,则跳转到
@backend
命名位置。
- 尝试匹配文件路径
2.6 使用 include
分离多个 location
配置
如果需要管理多个 location
块,可以将它们分离到单独的文件中,并通过 include
指令引入。
示例:
主配置文件:
server {
listen 80;
include /etc/nginx/conf.d/*.conf; # 引入所有 .conf 文件
}
/etc/nginx/conf.d/xianyang.conf
:
location /xianyang/ {
proxy_pass http://10.175.12.236:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
/etc/nginx/conf.d/api.conf
:
location /api/ {
proxy_pass http://10.175.12.237:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
说明:
- 使用
include
可以将配置文件模块化,便于管理和维护。
2.7 综合示例:多条件匹配
以下是一个综合示例,结合了前缀匹配、正则表达式和默认后端:
server {
listen 80;
# 精确匹配 /xianyang/
location = /xianyang/ {
proxy_pass http://10.175.12.236:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
# 匹配 /xianyang/ 或 /api/ 路径(正则表达式)
location ~ ^/(xianyang|api)/ {
proxy_pass http://10.175.12.236:8080;
add_header 'Access-Control-Allow-Origin' '*';
}
# 默认匹配
location / {
root html;
index index.html;
}
}
3. 总结
- 多个
location
块:适合简单的条件匹配,Nginx 会根据优先级选择最匹配的location
。 - 正则表达式:适合需要匹配多个路径的场景。
map
指令:适合动态选择后端服务器。if
条件:可以实现复杂的逻辑,但性能较低,应谨慎使用。try_files
:适合根据文件存在性选择不同的处理逻辑。include
:适合将配置模块化,便于管理。
根据具体需求选择合适的方式。如果需要更复杂的逻辑,通常推荐使用 map
或正则表达式来实现多条件匹配。
参考资料: