Nginx 反向代理时如何正确处理相对 URL?

相对 URL 错乱的处理:proxy_pass 路径对称、proxy_redirect 修正重定向头、sub_filter 改写页面内链接、Cookie 路径用 proxy_cookie_path。首选让后端感知 base path。本文给完整方案。

最佳实践
Nginx 反向代理时如何正确处理相对 URL?封面

**处理四件套:①proxy_pass 路径映射写对称(前缀替换规则想明白);②proxy_redirect 修正后端 302 的 Location 头;③sub_filter 改写 HTML 里的链接与资源路径;④proxy_cookie_path 修 Cookie 作用域。最省心的根治:让后端应用配置 base path(如 /app1),前后端路径天然一致,不用改写任何内容。

路径映射:两种写法的差别

location /app1/ {
    proxy_pass http://internal:8080/;      # /app1/x → /x(前缀被替换)
}

location /app1/ {
    proxy_pass http://internal:8080;       # /app1/x → /app1/x(原样转发)
}

末尾有无 / 决定前缀替换还是原样转发。后端不感知 /app1 前缀时用第一种,同时处理三类"出界":

① 重定向头:proxy_redirect

location /app1/ {
    proxy_pass http://internal:8080/;
    proxy_redirect http://internal:8080/ /app1/;
    # 或宽松写法
    proxy_redirect ~^https?://+/(.*)$ /app1/$1;
}

② 页面内容:sub_filter

location /app1/ {
    proxy_pass http://internal:8080/;
    sub_filter 'href="/' 'href="/app1/';
    sub_filter 'src="/'  'src="/app1/';
    sub_filter_once off;
    sub_filter_types text/html text/css application/javascript;
}

注意 sub_filter 默认只处理 text/html;CSS/JS 里的路径要扩 sub_filter_types。gzip 响应需先 proxy_set_header Accept-Encoding ""; 让后端不压缩,才能改文本。

③ Cookie 路径:proxy_cookie_path

proxy_cookie_path / /app1/;

后端种下的 Cookie 路径是 /,不改写会泄漏到整个域(或前端路由下 Cookie 不带)。

根治方案

主流框架都支持配置 base path(Django FORCE_SCRIPT_NAME、Spring server.servlet.context-path、前端构建的 base/publicPath)。让后端"知道自己挂在 /app1 下",生成的一切链接自动带前缀——以上改写全部不需要。

观测云对照

改写遗漏用 404 分布定位。 采集 Nginx 访问日志后,404 请求的路径分布图直接指出哪些资源路径没改写到;修复后 404 清零可验证。

常见问题(FAQ)

Q:sub_filter 没生效?
A:检查响应 Content-Type 是否在 sub_filter_types 里、响应是否 gzip 压缩(压缩的改不了,先禁后端压缩)。

Q:AJAX 请求的 URL 是 JS 变量拼的,sub_filter 改不到?
A:对——JS 动态拼的 URL 静态改写无能为力,这正是推荐后端感知 base path 的原因。

Q:proxy_redirect default 是什么行为?
A:默认(不配置时)按 proxy_pass 的映射自动处理 Location 头,多数简单场景已够;自定义域名/端口时才需显式写。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台