在现代 Web 架构中,Nginx 几乎是无处不在的“全能瑞士军刀”。它不仅能作为高性能的 Web 服务器,更常扮演着反向代理和API 网关的关键角色。而在配置反向代理时,有一个场景我们几乎都会遇到,那就是——URL 路径重写,或者说,去除请求路径中的特定前缀。
看似一个小小的配置,背后却隐藏着 Nginx 最核心的代理逻辑。配置对了,请求丝滑转发;配置错了,后端服务收到一堆 404,让你抓耳挠腮。
今天,我们就把这个知识点彻底讲透,让你彻底掌握 Nginx 路径重写的艺术。
一、为什么需要去除前缀?场景还原
想象一下,我们正在构建一个微服务系统。系统有一个统一的入口(API 网关),域名是 https://example.com
。后面则部署了多个独立的微服务,比如:
- 用户服务 (User Service):监听在
http://localhost:8001
- 订单服务 (Order Service):监听在
http://localhost:8002
这些微服务自身是不知道自己被代理的。例如,“用户服务”提供的接口是 /users/123
,而不是 /api/user/users/123
。
为了方便管理和区分,我们希望 API 网关的 URL 结构是这样的:
- 所有访问用户服务的请求,都以
/api/user/
开头。 - 所有访问订单服务的请求,都以
/api/order/
开头。
我们的核心目标是:
当用户访问 https://example.com/api/user/users/123
时,Nginx 需要将请求转发给 http://localhost:8001
,并且转发到后端的路径应该是 /users/123
,而不是原始的 /api/user/users/123
。
这个**“剪掉” /api/user/
** 的过程,就是我们所说的“去除前缀”。
图1: Nginx 去除前缀的反向代理流程
二、核心知识点:proxy_pass
指令的“斜杠魔法”
要实现这个功能,关键在于 proxy_pass
指令后面 URL 的写法,特别是末尾是否带有斜杠 (/
)。这是 Nginx 路径重写中最核心、最关键的区别!
我们直接看规则:
-
proxy_pass
目标 URL 不带斜杠 (/
)- 行为:Nginx 会将
location
匹配到的完整 URI 直接拼接到目标 URL 后面。 - 结果:不去除前缀。
- 行为:Nginx 会将
-
proxy_pass
目标 URL 带有斜杠 (/
)- 行为:Nginx 会将
location
匹配到的那部分前缀路径剥离,然后将剩余部分拼接到目标 URL 后面。 - 结果:成功去除前缀!
- 行为:Nginx 会将
听起来有点绕?我们用上面的“用户服务”场景来举例说明。
错误的配置(不去除前缀)
server {
location /api/user/ {
# 注意!目标URL末尾没有 "/"
proxy_pass http://localhost:8001;
}
}
- 请求:
GET /api/user/users/123
- 后端收到的请求:
GET /api/user/users/123
<-- 错误!
正确的配置(成功去除前缀)
server {
location /api/user/ {
# 注意!目标URL末尾有一个神奇的 "/"
proxy_pass http://localhost:8001/;
# 顺便加上推荐的代理头信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
- 请求:
GET /api/user/users/123
- 后端收到的请求:
GET /users/123
<-- 正确!
总结一下: proxy_pass
后面有没有斜杠,是两种完全不同的代理行为。想要去除 location
匹配的前缀,就一定要在 proxy_pass
的 URL 末尾加上 /
。
三、更强大的武器:rewrite
指令
虽然“斜杠魔法”能解决大部分问题,但有时我们需要更精细、更复杂的路径重写规则。这时候,rewrite
指令就该登场了。
server {
location /api/user/ {
# 1. 使用rewrite重写URI
rewrite ^/api/user/(.*)$ /$1 break;
# 2. 将重写后的URI代理到后端
proxy_pass http://localhost:8001;
}
}
rewrite
的优势在于灵活性和可读性,可以实现非常复杂的匹配和替换逻辑。
四、一个常见的陷阱:后端重定向问题
配置好代理后,还有一个常见的问题需要注意。如果后端服务返回一个相对路径的重定向 (Location: /login
),浏览器会错误地跳转到 https://example.com/login
,导致404。
图2: 错误的重定向流程 vs 正确的重定向流程
解决方案:proxy_redirect
指令
proxy_redirect
指令专门用于修改后端返回的 Location
响应头。
location /api/user/ {
proxy_pass http://localhost:8001/;
# 智能修复重定向路径
# 当后端返回 "Location: /" 时, Nginx自动修改为 "Location: /api/user/"
proxy_redirect / /api/user/;
# ... 其他 proxy_set_header ...
}
proxy_redirect default;
也能在很多情况下智能地处理,但显式声明是是更稳妥的做法。
总结与探讨
让我们快速回顾一下今天的核心知识点:
- 最简单的方法:在
proxy_pass
的目标 URL 末尾添加斜杠/
,即可自动去除location
匹配到的路径前缀。 - 更强大的方法:使用
rewrite ... break;
指令,通过正则表达式精确重写 URI。 - 别忘了陷阱:使用
proxy_redirect
指令来修正后端服务返回的相对路径重定向。
掌握了这三点,您就可以自信地应对 Nginx 中几乎所有的反向代理路径重写需求了。
👇 欢迎在评论区留下你的看法 👇
到你了!关于 Nginx 路径重写,我们想听听你的声音:
- 你是“斜杠派”还是“rewrite 派”? 在日常工作中,你更倾向于使用哪种方式来处理路径?
- 分享你的“坑”! 在配置 Nginx 代理时,你还遇到过哪些令人印象深刻的“坑”或者有趣的技巧?
- 还有什么想学的? 关于 Nginx,你最想了解哪个主题(比如:负载均衡、缓存、高可用)?
期待你的留言,让我们在交流中共同进步!如果你觉得文章有用,别忘了点赞、在看、分享三连支持一下!
Q.E.D.