关键是proxy_pass末尾斜杠决定路径是否剥离location前缀:带/则转发/login,不带/则转发/api/login;需结合后端路由预期匹配,并通过access_log、error_log及直连后端验证404来源。

排查 Nginx 路径映射或重写规则导致的 404,关键不是“有没有转发”,而是“转发过去的内容对不对”。很多 404 实际是后端明确拒收——因为收到的路径、Host 或协议信息和它预期的不一致。下面按真实排查顺序讲清楚几个核心环节。
看透 proxy_pass 斜杠逻辑:/ 和 不带 / 的区别
这是最常踩的坑,直接影响后端收到的 URI:
-
proxy_pass http://127.0.0.1:3000/;(末尾有 /)→ Nginx 会删掉 location 匹配前缀,再拼接。比如
location /api { ... }下访问/api/login,实际发给后端的是/login -
proxy_pass http://127.0.0.1:3000;(末尾无 /)→ Nginx 原样转发完整路径,即
/api/login全部传过去 - 若后端路由不带
/api前缀(如只认/login),却用了不带斜杠的写法,就会 404;反之,若后端必须带前缀,却用了带斜杠写法,也会 404
检查 rewrite 是否引入双斜杠或路径错位
手动加 rewrite 时容易出问题,尤其和 proxy_pass 混用:
- 常见错误:
rewrite ^/api/(.*)$ /$1 break;+proxy_pass http://backend;→ 可能生成//login(开头两个 /),Node.js 等服务会直接报错Cannot POST //login - 验证方法:在后端加日志或用
curl -v直连后端,对比 Nginx 转发过来的原始请求路径是否含多余 /、大小写错误、或缺失前缀 - 建议优先用
proxy_pass本身的斜杠机制处理路径替换,少用rewrite,除非真需要正则重写
确认 Host 和协议头是否被正确传递
后端常依赖 Host 头做多租户识别、CORS 判断或 HTTPS 重定向,传错就直接拒收:
- 默认 Nginx 把客户端的
Host(如a.example.com)原样传给后端,但后端可能只信任自己的域名(如api.prod.com) - 应显式设置:
proxy_set_header Host $proxy_host;(不是$host) - 如果外层是 HTTPS,内层是 HTTP,记得加:
proxy_set_header X-Forwarded-Proto $scheme;,否则后端可能误判协议并发起 301 重定向,引发循环或 404
用日志和直连交叉验证,定位 404 来源
别猜,用证据说话:
- 查 Nginx access log:
grep "404" /var/log/nginx/access.log | tail -5,看状态码是 Nginx 自己返回的,还是透传后端的 - 查 error log:
tail -f /var/log/nginx/error.log,留意是否有upstream timed out或no live upstreams,说明根本没转出去 - 绕过 Nginx 直连后端:
curl -v http://127.0.0.1:3000/login(模拟 Nginx 发过去的路径),如果也 404,问题就在后端路由或权限;如果 OK,说明 Nginx 转发内容有偏差











