https://mp.weixin.qq.com/s/UdPByQduYYzOl8bRCAMNbQ

Nginx 反向代理必知必会:优雅地去除 URL 前缀
在现代 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 路径重写中最核心、最关键的区别!

我们直接看规则:

  1. proxy_pass 目标 URL 不带斜杠 (/)
    • 行为:Nginx 会将 location 匹配到的完整 URI 直接拼接到目标 URL 后面。
    • 结果:不去除前缀。
  2. proxy_pass 目标 URL 带有斜杠 (/)
    • 行为:Nginx 会将 location 匹配到的那部分前缀路径剥离,然后将剩余部分拼接到目标 URL 后面。
    • 结果:成功去除前缀!
    听起来有点绕?我们用上面的“用户服务”场景来举例说明。

错误的配置(不去除前缀)


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 正确的重定向流程

200 OK
解决方案: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; 也能在很多情况下智能地处理,但显式声明是是更稳妥的做法。

总结与探讨
让我们快速回顾一下今天的核心知识点:


1. 最简单的方法:在 proxy_pass 的目标 URL 末尾添加斜杠 /,即可自动去除 location 匹配到的路径前缀。
2. 更强大的方法:使用 rewrite ... break; 指令,通过正则表达式精确重写 URI。
3. 别忘了陷阱:使用 proxy_redirect 指令来修正后端服务返回的相对路径重定向。
掌握了这三点,您就可以自信地应对 Nginx 中几乎所有的反向代理路径重写需求了。
文档更新时间: 2025-12-12 09:14   作者:admin