Nginx Location匹配与Proxy_pass
1. Location 匹配规则
1.1 基本语法
bash
location [修饰符] 匹配模式 {
# 配置指令
}
1.2 匹配模式类型
1.2.1 精确匹配 (=)
bash
location = /api {
# 只匹配 /api,不匹配 /api/ 或 /api/xxx
}
1.2.2 前缀匹配 (无修饰符)
带斜杠的匹配:
bash
location /prefix/ {
# 匹配以 /prefix/ 开头的 URI
# 示例:/prefix/user → 匹配 ✅
# 示例:/prefixother → 不匹配 ❌
}
不带斜杠的匹配:
bash
location /prefix {
# 匹配任何以 /prefix 开头的 URI
# 示例:/prefix/user → 匹配 ✅
# 示例:/prefixother → 匹配 ✅ (可能产生意外匹配)
}
1.2.3 正则匹配 (~, ~*)
bash
location ~ \.php$ {
# 匹配以 .php 结尾的 URI (区分大小写)
}
location ~* \.(jpg|png)$ {
# 匹配以 jpg 或 png 结尾的 URI (不区分大小写)
}
1.3 匹配优先级
= 精确匹配 (最高优先级)
^~ 前缀匹配
~ 和 ~* 正则匹配 (按配置顺序)
普通前缀匹配 (最长匹配优先)
2. Proxy_pass 代理规则
2.1 Proxy_pass 基本语法
bash
proxy_pass http://backend_server;
2.2 路径替换规则
2.2.1 Proxy_pass 以 / 结尾会替换 location 匹配的部分
bash
#配置 A
location /app/ {
proxy_pass http://192.168.1.10:8080/;
}
#请求:/app/user/list
#转发:http://192.168.1.10:8080/user/list
#location 匹配部分 /app/ 被替换为 /
bash
# 配置 B
location /app {
proxy_pass http://192.168.1.10:8080/;
}
# 请求:/app/user/list
# 转发:http://192.168.1.10:8080//user/list
# location 匹配部分 /app 被替换为 /,产生双斜杠
2.2.2 Proxy_pass 不以 / 结尾会保留完整路径
bash
# 配置 C
location /api/ {
proxy_pass http://192.168.1.11:3000;
}
# 请求:/api/v1/users
# 转发:http://192.168.1.11:3000/api/v1/users
# 完整路径被保留
bash
# 配置 D
location /api {
proxy_pass http://192.168.1.11:3000;
}
# 请求:/api/v1/users
# 转发:http://192.168.1.11:3000/api/v1/users
# 完整路径被保留
2.3 完整示例对比
示例 1:正确的路径处理
bash
location /gateway/ {
proxy_pass http://192.168.1.20:9000/;
# 请求:/gateway/auth/login
# 转发:http://192.168.1.20:9000/auth/login
# ✅ 路径处理正确
}
示例 2:产生双斜杠问题
bash
location /gateway {
proxy_pass http://192.168.1.20:9000/;
# 请求:/gateway/auth/login
# 转发:http://192.168.1.20:9000//auth/login
# ❌ 产生双斜杠,可能导致 404
}
示例 3:保留前缀路径
bash
location /external/ {
proxy_pass http://192.168.1.30:8000;
# 请求:/external/service/data
# 转发:http://192.168.1.30:8000/external/service/data
# ✅ 完整路径保留
}
3. 常见场景与最佳实践
3.1 场景 1:去除前缀代理
bash
# 前端使用 /proxy/api,后端期望 /api
location /proxy/ {
proxy_pass http://192.168.1.40:7000/;
# 请求:/proxy/api/users
# 转发:http://192.168.1.40:7000/api/users
}
3.2 场景 2:路径重写代理
bash
location /v1/ {
rewrite ^/v1/(.*)$ /api/v1/$1 break;
proxy_pass http://192.168.1.50:6000;
# 请求:/v1/users
# 转发:http://192.168.1.50:6000/api/v1/users
}
3.3 场景 3:多路径代理
bash
# 使用正则匹配多个路径
location ~ ^/(auth|api|admin)/ {
proxy_pass http://192.168.1.60:5000;
# 请求:/auth/login → http://192.168.1.60:5000/auth/login
# 请求:/api/data → http://192.168.1.60:5000/api/data
}
4. 总结表格
| Location 模式 | Proxy_pass 格式 | 请求路径 | 转发路径 | 效果 |
|---|---|---|---|---|
| location /app/ | proxy_pass http://backend/; | /app/user | http://backend/app/user | 保留前缀 ✅ |
| location /app/ | proxy_pass http://backend/; | /app/user | http://backend/user | 去除前缀 ✅ |
| location /app | proxy_pass http://backend/; | /app/user | http://backend//user | 双斜杠 ❌ |
| location /app | proxy_pass http://backend; | /app/user | http://backend/app/user | 保留前缀 ✅ |