V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
kyonn
V2EX  ›  NGINX

nginx 二级目录反向代理是不是有先天缺陷?

  •  
  •   kyonn · 28 天前 · 3569 次点击

    如下一个最简化的反代配置,将本地 80/443 端口的 /git/ 反代到本地容器的 8085 端口。

    访问 127.0.0.1/git/ 成功跳转到 8085 端口容器的 web 页面,但是发现有诸多问题:

    1. css 和 png 加载失败。抓了下调试信息,发现是容器返回的样式等文件地址都是绝对路径 /,进而导致浏览器请求样式文件时,没有正确走 location /git/ 的反代。通过 sub_filter 指令批量替换后解决了。
    2. 问题 1 解决后,点击其它页面元素,还是会出现 404 错误。原因同 1

    类似这种二级目录的反向代理,是不是天然有缺陷,没办法像 二级域名 或 三级域名 反代那样完美实现?

    注:

    1. 域名管理不在手上,添加多个二级或三级域名比较麻烦,所以考虑的是同一个域名下的子目录。
    2. 可以修改反代 upstream docker 的配置,因为是自己部署的。
    location /git/ {
        proxy_http_version 1.1;
        proxy_pass http://192.168.1.13:8085/;
    }
    
    第 1 条附言  ·  28 天前
    问题信息缺失引起歧义了。本意是想问 针对 这类二级目录 反代的情况,在不修改被反代服务的情况下,能否利用 nginx 一些特殊的配置做到类似 二级域名 反代那样的效果。

    因为被反代的服务通常不是自己写的(开源的第三方服务),如果再修改它的静态资源打包方式比较麻烦,要额外修改被反代的项目。除了静态资源,我也也比较好奇,是否有其它的限制比较难处理,比如#11 提到的问题。

    另一方面,因为域名解析控制权不在我这,所以加二级域名、三级域名也比较麻烦。所以倾向于使用同一个域名下二级目录反代的方式。

    问题已经解决了,按照大家提供的信息,我去修改了 被反代服务的静态资源 context-path ,加了 /git/ 子目录,目前看暂时工作正常了。
    40 条回复    2025-08-05 11:34:20 +08:00
    perfectlife
        1
    perfectlife  
       28 天前
    个人感觉这不是 nginx 的缺陷,是 http://192.168.1.13:8085 服务的问题 ,服务里比如 index.html 里面使用的 css png js 资源地址用的是绝对路径,用相对路径就没问题了
    RobinHuuu
        2
    RobinHuuu  
       28 天前 via iPhone
    目录反带得结合 rewrite 规则,把你的需求喂给 ai ,ai 给你写
    momocraft
        3
    momocraft  
       28 天前
    先看看你要反代的服务有没有路径设置
    SanjinGG
        4
    SanjinGG  
       28 天前 via Android
    看样子是你打包没用相对路径吧
    kyonn
        5
    kyonn  
    OP
       28 天前
    @momocraft 是指 contextpath 吗?让被代理的容器 web 服务在 contextpath 而不是 / ?
    kyonn
        6
    kyonn  
    OP
       28 天前
    @RobinHuuu 可能我问法不太正确,AI 给出的答案也都是有问题的。
    kyonn
        7
    kyonn  
    OP
       28 天前
    @perfectlife
    @SanjinGG
    被代理的容器是现成的开源项目。直接通过容器端口访问是正常的。

    根据[这篇文档]( https://blog.csdn.net/jiabeis/article/details/100974516)的意思,是必须使用 contextpath 功能才能支持二级目录反代?
    perfectlife
        8
    perfectlife  
       28 天前
    @kyonn 直接访问端口时 根目录是 / ,访问正常是预期的现象, 你反代时根目录是/git/了, 绝对路径就会出错了, 三楼说的对,要先看这个开源项目支持不支持路径设置, 比如你用 nginx 使用/kibana 反向代理 kibana ,你就需要在 kibana 里设置 server.basePath: "/kibana"
    maocat
        9
    maocat  
       28 天前   ❤️ 1
    浏览器路径加/git/是人为操作,同理,如果需要浏览器自动加载/git/静态资源,是不是需要在代码里提前配置/git/ ?,解决方法,1 ,前端编译时项目加上/git/,2. 所有静态资源文件由后端推送,3,直接 nginx 转发静态文件
    看你的描述,我猜测你部署的是 coze
    momocraft
        10
    momocraft  
       28 天前
    @kyonn 问我没用,我都不知道你要代理什么服务
    duanxianze
        11
    duanxianze  
       28 天前
    确实有先天缺陷,比如 cookie,localStorage 不能隔离等等问题,但你这个问题纯粹是你没写对
    totoro625
        12
    totoro625  
       28 天前
    proxy_pass 的服务器不支持自定义为 example.com/git/为主页的话
    直接自己手搓规则
    由简到繁观察请求路径,例如 A 只请求很少的几个文件夹路径,就单独为 A 写
    例如 A 请求/_nuxt 和 /css/main.css (如果与主站点重复,需要人为修改主站点 css 请求路径,或子站点请求路径)
    location /_nuxt {
    proxy_pass http://192.168.1.13:8085/_nuxt;
    }
    location /css/main.css {
    proxy_pass http://192.168.1.13:8085/css/main.css;
    }
    skiy
        13
    skiy  
       28 天前
    你在主机上面 curl http://192.168.1.13:8085 看看页面上的 URL 正常吗。
    Alfchao
        14
    Alfchao  
       28 天前
    前端资源要用相对路径,和 nginx 没关系
    tsja
        15
    tsja  
       28 天前
    全栈前端表示,每次部署新项目都会被 nginx 折磨半天,有的问题 AI 也解决不了
    jspatrick
        16
    jspatrick  
       28 天前
    @kyonn #7 我觉得 4L 正解,问题应该是出在前端打包上
    如果是 webpack ,参考 https://www.webpackjs.com/configuration/output/#outputpublicpath
    如果是 vite ,参考 https://cn.vitejs.dev/config/shared-options.html#base
    Charles0929
        17
    Charles0929  
       28 天前
    nginx 二级代理需要上游服务支持,比如 web 打包需要增加通用前缀,这种 vite 等插件是支持配置的,如果是其他语言,比如 java 一类,springboot 也有 servlet-context-path 这些配置
    Suaxi
        18
    Suaxi  
       28 天前
    反代二级目录,vue + webpack 的话 可以通过 config 的 publicPath 来配置

    ps:能用二级域名尽量用二级域名
    hugozach
        19
    hugozach  
       28 天前
    代码写的问题就代码的问题 还怪上 nginx 了
    oneisall8955
        20
    oneisall8955  
    PRO
       28 天前
    南无阿弥陀佛 还是二级域名减轻心智负担
    kyonn
        21
    kyonn  
    OP
       28 天前
    @Alfchao
    @jspatrick
    @Charles0929
    @Suaxi

    OK ,我按照这个关键字找下解决方案。因为是部署的是别人打包的容器,不是自己写的代码,不确定能否设置 context-path
    irisdev
        22
    irisdev  
       28 天前
    额楼主不是说代理的是开源容器吗,怎么楼上还有让楼主改代码的,写脚本批量替换路径是不是能解决?
    635925926
        23
    635925926  
       28 天前
    你写了/给你访问/。请问哪里有问题了?
    zhhbstudio
        24
    zhhbstudio  
       28 天前
    看上去是 sub_filter 没写全,根据不能用的页面针对性加一下
    clarkethan
        25
    clarkethan  
       28 天前
    这是你博客引用静态资源的路径应该做对应的修改,nginx 不背这个锅
    coderzhangsan
        26
    coderzhangsan  
       28 天前
    #1 已经说明问题了,这不是 nginx 的问题,这是 web 页面静态资源路径的问题,静态资源相对路径后面要加上/git/,否则不会触发 nginx /git/ 重写规则,会按当前 nginx 配置去搜寻静态资源路径。
    ssiitotoo
        27
    ssiitotoo  
       28 天前
    你要知道你的入口是 nginx 了然后你配置了/git/代理到你后端 请求 nginxip/js/1.js 等静态资源在 nginx 那儿是找不到 需要在资源路劲前添加/git/才能请求到你后 8085 的资源
    SenLief
        28
    SenLief  
       28 天前 via iPhone
    前端程序员问题,项目不支持二级路径反代就不行。
    kyonn
        29
    kyonn  
    OP
       28 天前
    问题已经解决了,按照大家提供的信息,我去修改了 被反代服务的静态资源 context-path ,加了 /git/ 子目录,目前看暂时工作正常了。

    -----------

    问题信息缺失引起歧义了。本意是想问 针对 这类二级目录 反代的情况,在不修改被反代服务的情况下,能否利用 nginx 一些特殊的配置做到类似 二级域名 反代那样的效果。提问的缺陷也是指 二级目录反代缺陷,而不是说 nginx 有缺陷。

    因为被反代的服务通常不是自己写的(开源的第三方服务),如果再修改它的静态资源打包方式比较麻烦,要额外修改被反代的项目。除了静态资源,我也也比较好奇,是否有其它的限制比较难处理,比如#11 提到的问题。

    另一方面,因为域名解析控制权不在我这,所以加二级域名、三级域名也比较麻烦。所以倾向于使用同一个域名下二级目录反代的方式。


    @perfectlife
    @RobinHuuu
    @momocraft
    @SanjinGG
    @maocat
    @duanxianze
    @totoro625
    @skiy
    @Alfchao
    @jspatrick
    @Charles0929
    @Suaxi
    @irisdev
    @zhhbstudio
    @coderzhangsan
    @ssiitotoo
    @SenLief
    w292614191
        30
    w292614191  
       28 天前
    我也倾向 /git ,然后 nginx 自动处理,但不行,只能修改项目的 basePath 之类的。自己的项目还好,第三方项目就很麻烦
    idealhs
        31
    idealhs  
       28 天前
    目前遇到的大部分都支持设置 basePath ,也是有很多小项目前端整的不好确实没法这么用的。
    wwhontheway
        32
    wwhontheway  
       28 天前
    对,非常难受,之前想用 nginx 二级目录的方式代理多个 kibana ,结果一堆静态文件找不到。最后看到的解法也是去被代理的机器上修改一些东西。虽然可行,但是还需要去被代理服务修改配置就很难受
    muyuanqiang7
        33
    muyuanqiang7  
       28 天前
    我记得可以用 rewrite path 来处理静态文件的加载,但是在有些 api 请求上还是有点问题。代理第三方的是可以解决的,问下 AI 吧
    kyonn
        34
    kyonn  
    OP
       28 天前
    @muyuanqiang7 按我的理解,rewrite path 应该只能重写 原始请求的 uri ,如果 被代理机器返回的就是 /xxx.css ,浏览器就按 /xxx.css 去请求静态资源,这时候 rewrite 就不起作用了。除非把本机所有 /xxx.css 类的请求都 rewrite 给 被代理机器,但是这个改动会影响第 2 个被代理机器。

    假如只有一台被代理机器,应该是可行的。不知道我的理解是否正确。
    liuhai233
        35
    liuhai233  
       28 天前
    @kyonn
    1. 二级域名转发,每个服务一个域名
    2. 不同端口,每个端口一个服务
    konakona
        36
    konakona  
       28 天前
    首先,在 Nginx 配置中,需要明确理解其作用范围。/git/ 的配置仅对该子目录生效,这并非 Nginx 的缺陷,而是对其作用机制的误解。

    如果不是特意将主域名分发至多个不同的 endpoint 服务上,应注意 endpoint 的 contextpath 。如果使用的是开源镜像等固定 contextpath 的服务,且无法修改,则可以通过 sub-filter 实现所需功能。
    muyuanqiang7
        37
    muyuanqiang7  
       28 天前
    @kyonn 你说的和我之前问 AI 回答的意思差不多,但是我的实际使用的时候是我不加 rewrite 的情况下,我的 css 、js 、png 请求地址就是/,但是当我加了 rewrite 后被代理的第三方服务的请求静态资源就正常了。
    echo21bash
        38
    echo21bash  
       28 天前
    老运维一看题目就知道是,后端源代码写的绝对路径,甩锅给研发 ok
    adoal
        39
    adoal  
       28 天前
    V2EX 里的月经问题了。如果反代后方应用没有“我的前方可能会有一个反代服务器,把不同 Host 不同 port 不同 prefix 的请求转给我,所以我需要在生成页内链接时做调整”的意识,这个问题就是没有完美解的。

    一个不得已的托底方法是用 mod_substitute 对后方应用生成的页面做内容替换。当然,这种替换不能保证 100%无假阴无假阳。
    ttkit
        40
    ttkit  
       27 天前
    你的 css ,js 资源引用打包时应该用完整的域名路径: http://m.ccc.om/a.css 而不是 /a.css ,这样可以解决你这个问题吧?
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2574 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 15:19 · PVG 23:19 · LAX 08:19 · JFK 11:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.