你是不是也遇到过这样的情况:
这不是你一个人的问题。
在 Nginx 的世界里,location、rewrite、proxy_pass 是最常用也最容易混淆的三兄弟。它们掌控着“请求转发”的命脉,却常常因为顺序、作用域、路径拼接等细节让人头大。
本文将从原理到实战,彻底搞清楚这三者之间的区别与联系。看完这篇文章,你将能自信地写出任何一条请求转发规则,不再被神秘的路径匹配坑住。
理解三者的前提,是理解 Nginx 处理请求的顺序。
当浏览器访问一个网站时,请求会经过以下几个阶段:
简单来说,Nginx 在拿到请求后,会:
- 先确定哪个
server 块负责处理(根据域名和端口匹配); - 然后在该
server 里找到最符合路径的 location; - 若有
rewrite 指令,则根据规则重写 URI; - 最后执行
proxy_pass(转发给后端)或 root(返回静态资源)。
所以,这三者其实是同一条请求处理链上的不同阶段:
二、location—Nginx 路由分发的“入口判官”
location 是 Nginx 路由机制的核心,用于匹配请求 URI(即域名后的路径部分)。
1. 基本语法
location [=|~|~*|^~|@] /uri/ {
# 配置内容
}
常见匹配符解释:
举个例子:
server {
listen 80;
server_name example.com;
location = / {
return 200 "首页";
}
location ^~ /static/ {
root /usr/share/nginx/html;
}
location ~* \.(jpg|png|css|js)$ {
expires 30d;
}
}
这段配置表示:
2. 匹配优先级规则(非常关键)
Nginx 在匹配时遵循以下顺序:
这解释了很多“配置不生效”的原因。 例如:
location / {
return 200 "Default";
}
location /api/ {
return 200 "API";
}
location ^~ /api/private/ {
return 200 "Private";
}
访问 /api/private/test,结果返回 "Private",因为 ^~ 优先级高于 /api/。
rewrite 是修改 URI 的工具,它可以改变用户请求的路径,然后重新交给 Nginx 匹配。
1. 基本语法
rewrite regex replacement [flag];
参数解释:
- flag:控制行为,如
last、break、redirect、permanent。
2. 常见 flag 对比
3. 举例说明
server {
listen 80;
server_name example.com;
location /old/ {
rewrite ^/old/(.*)$ /new/$1 permanent;
}
}
访问 http://example.com/old/test.html浏览器会被重定向到 http://example.com/new/test.html。
如果改成:
rewrite ^/old/(.*)$ /new/$1 last;
则是内部跳转,浏览器地址栏不会变化,但实际响应来自 /new/ 路由。
四、proxy_pass—请求转发的“幕后搬运工”
proxy_pass 用于把请求转发到后端服务,是反向代理的核心。
1. 基本语法
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
当访问 /api/user 时,请求被转发到:
http://127.0.0.1:8080/user
2. 重点!路径拼接规则
很多人被坑在这一点上。proxy_pass 的行为取决于结尾是否带 /。
| |
|---|
proxy_pass http://127.0.0.1:8080; | http://127.0.0.1:8080/api/user |
proxy_pass http://127.0.0.1:8080/; | http://127.0.0.1:8080/user |
是不是很细?这差一个 / 就会完全改变结果。
原理是:
- 不带斜杠 → Nginx 会把匹配到的
location 前缀拼接在目标 URL 上; - 带斜杠 → Nginx 会用重写后的路径替换整个请求 URI。
3. 常见示例
反向代理后端 API:
location /api/ {
proxy_pass http://backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
转发静态文件服务:
location /static/ {
proxy_pass http://127.0.0.1:9000/;
}
代理 WebSocket:
location /ws/ {
proxy_pass http://127.0.0.1:7000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
让我们看一个实际项目配置:
server {
listen 80;
server_name www.demo.com;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
请求:http://www.demo.com/api/user/info
处理流程如下:
rewrite 将 /api/user/info → /user/info;break 终止 rewrite,继续执行当前 location;proxy_pass 将请求转发到 http://127.0.0.1:8080/user/info;
理解这条链路后,你再也不会被转发逻辑绕晕。
如果遇到转发异常、路径重复、404,可用以下手段定位:
- 打印 rewrite 日志在
nginx.conf 中打开:
rewrite_log on;
error_log /var/log/nginx/error.log notice;
curl -v http://localhost/api/test
- 用 uri / $proxy_host 变量打印日志
log_format debug '$remote_addr "$request_uri" -> "$uri" proxy:$proxy_host';
access_log /var/log/nginx/debug.log debug;
这些方法能帮助你看到每一步到底发生了什么重写和转发。
- 确认 proxy_pass 末尾
/ 是否符合预期;
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
proxy_pass http://backend;
这样可以实现高可用与负载均衡。
总结
location、rewrite、proxy_pass 并不是孤立的配置项,而是 Nginx 控制请求流的三重奏:
它们共同构建出一套声明式的请求分发 DSL(领域特定语言),是 Nginx 的灵魂所在。 当你能流畅地在脑中推演一条请求的流向时,你就真正理解了 Nginx 的精髓。
配置文件不只是写给机器的命令,它是系统架构思维的具象化。 理解转发机制,就像理解一座城市的交通图——掌握了流向,才能掌控性能与稳定。