Nginx反向代理配置详解
2024 年 11 月 02 日 • 笔记
关于Nginx反向代理的相关配置理解
引用:
一、基础 URL 格式规范
1. 无路径情况
合法格式:
http://host
https://host
http://host:port
https://host:port
非法格式:
http://host/
http://host:port/
(结尾不能有/
)
2. 包含路径情况
合法格式:
http://host/
https://host:port/
http://host/api
http://host/api/
非法格式:
http://host
(必须带/
)http://host:port
(必须带/
)
二、代理路径匹配规则
1. 基础匹配原则
nginx
复制代码
location / {
proxy_pass http://backend:8080;
}
- 访问
/
→ 后端路径/
- 访问
/api/xx
→ 后端路径/api/xx
2. 路径透传规则
location 规则 | 原始访问路径 | 透传后的路径 |
---|---|---|
/ |
/ |
(空) |
/ |
/a |
a |
/a/ |
/a/b/c?d |
b/c?d |
三、URL 包含路径时的处理
1. 配置示例对比
场景1:URL 以 /
结尾
nginx
复制代码
location / {
proxy_pass http://backend:8080/;
}
- 访问
/api/xx
→ 后端路径/api/xx
场景2:URL 包含自定义路径
nginx
复制代码
location /api/ {
proxy_pass http://backend:8080/v1;
}
- 访问
/api/xx
→ 后端路径/v1xx
(注意路径直接拼接)
场景3:路径规范配置
nginx
复制代码
location /api/ {
proxy_pass http://backend:8080/v1/;
}
- 访问
/api/xx
→ 后端路径/v1/xx
(推荐写法)
2. 重要注意事项
当
proxy_pass
包含路径时,结尾的/
应与location
规则保持一致,否则会出现路径拼接异常。
四、正则匹配特殊处理
1. 禁止行为
nginx
复制代码
# 错误示例(正则location中proxy_pass包含路径)
location ~* ^/api/ {
proxy_pass http://backend/; # 会报错
}
2. 正确解决方案
nginx
复制代码
location ~* ^/api/ {
proxy_pass http://backend; # 仅保留host:port
}
五、URL 重写技巧
1. 基础重写示例
nginx
复制代码
location ~* ^/api/ {
rewrite ^/api/(.*) /?path=$1 break;
proxy_pass http://backend:8080;
}
- 访问
/api/a/b/c
→ 后端路径/?path=a/b/c
2. 重写覆盖效果
nginx
复制代码
location / {
rewrite ^/api/(.*) /?path=$1 break;
proxy_pass http://backend:8080/node/;
}
- 重写规则会覆盖
proxy_pass
中的路径,最终访问/?path=a/b/c
配置建议总结
- 普通 location 优先使用
location /path/
+proxy_pass http://host/
格式 - 正则 location 必须使用无路径的
proxy_pass
- 路径拼接时注意结尾
/
的一致性 - 复杂路径转换优先考虑
rewrite
方案
测试脚本
以下是一个交互式 Bash 脚本,可以帮您分析输入的 Nginx location
和 proxy_pass
配置,预测实际代理的路径:
bash
复制代码
#!/bin/bash
# Nginx proxy_pass 路径分析工具
# 使用方法:./proxy_analyzer.sh
echo -e "\033[1;36mNginx proxy_pass 路径分析器\033[0m"
echo "输入您的配置信息(按Ctrl+C退出)"
while true; do
# 获取用户输入
echo -e "\n\033[1;33m=== 新分析 ===\033[0m"
read -p "请输入 location 匹配规则(例如:/api/):" location_rule
read -p "请输入 proxy_pass 地址(例如:http://backend/):" proxy_pass_url
read -p "请输入测试访问路径(例如:/api/users):" test_path
# 解析 proxy_pass 组件
if [[ $proxy_pass_url =~ (http[s]?://[^/]+)(/.*)? ]]; then
backend_host=${BASH_REMATCH[1]}
backend_path=${BASH_REMATCH[2]:-/}
else
echo -e "\033[1;31m错误:proxy_pass 格式无效\033[0m"
continue
fi
# 处理 location 规则
if [[ "$location_rule" == "/" ]]; then
relative_path="$test_path"
else
relative_path=${test_path#$location_rule}
fi
# 判断路径处理类型
if [[ "$proxy_pass_url" == */ ]]; then
# 情况1:proxy_pass 以 / 结尾
if [[ "$location_rule" == */ ]]; then
final_path="${backend_path}${relative_path}"
else
final_path="${backend_path}${test_path#${location_rule%/}}"
fi
else
# 情况2:proxy_pass 不以 / 结尾
final_path="${backend_path%/}/${relative_path#/}"
fi
# 显示分析结果
echo -e "\n\033[1;32m分析结果:\033[0m"
echo -e "访问路径: \033[1;35m$test_path\033[0m"
echo -e "实际代理到: \033[1;35m${backend_host}${final_path}\033[0m"
# 显示处理逻辑
echo -e "\n\033[1;34m处理逻辑:\033[0m"
echo "1. location 规则: '$location_rule' 匹配后剩余路径: '$relative_path'"
echo "2. proxy_pass 分解: 主机部分='$backend_host' 路径部分='$backend_path'"
echo "3. 最终路径拼接: '${backend_path}' + '${relative_path}'"
# 特殊案例提醒
if [[ "$proxy_pass_url" != */ && "$location_rule" == */ ]]; then
echo -e "\n\033[1;31m注意:proxy_pass 不以/结尾但 location 以/结尾,可能导致路径拼接异常!\033[0m"
fi
done
使用示例
bash
复制代码
$ ./proxy_analyzer.sh
Nginx proxy_path 路径分析器
输入您的配置信息(按Ctrl+C退出)
=== 新分析 ===
请输入 location 匹配规则(例如:/api/):/api/
请输入 proxy_pass 地址(例如:http://backend/):http://backend/v1/
请输入测试访问路径(例如:/api/users):/api/users/123
分析结果:
访问路径: /api/users/123
实际代理到: http://backend/v1/users/123
处理逻辑:
1. location 规则: '/api/' 匹配后剩余路径: 'users/123'
2. proxy_pass 分解: 主机部分='http://backend' 路径部分='/v1/'
3. 最终路径拼接: '/v1/' + 'users/123'
支持的配置类型
- 常规代理:
location /path/
+proxy_pass http://host/
location /
+proxy_pass http://host:port
- 路径重写:
location /old/
+proxy_pass http://host/new/
- 特殊案例检测:
- 自动识别路径拼接警告
- 处理带查询参数的URL
实现原理
- 路径解析:
- 使用
BASH_REMATCH
正则分组提取proxy_pass
的主机和路径部分 - 通过字符串操作处理
location
规则匹配
- 使用
- 路径拼接逻辑:
- 边界情况处理:
- 自动处理
location /
特殊情况 - 保留原始查询参数(?后的内容)
- 自动处理
可以将此脚本保存为 proxy_analyzer.sh
,然后运行 chmod +x proxy_analyzer.sh
赋予执行权限。
留言 (0)