You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx反向代理多应用时资源加载失败的配置求助

Nginx反向代理多应用时资源加载失败的配置求助

嘿,我碰到过一模一样的问题!这事儿根源其实很清楚:你部署在5300端口的/app2应用,它返回的HTML里引用资源的路径是绝对路径(比如/assets/css/xxx),当用户访问http://127.0.0.1:8080/app2/时,浏览器会直接请求http://127.0.0.1:8080/assets/css/xxx——而Nginx里的location /规则优先级匹配到这个请求,就把它转发到5200端口的应用了,自然就加载失败。/api路径的问题也是同一个道理。

下面给你几个实用的解决办法,你可以根据自己的情况选:

方法一:修改应用的资源引用为相对路径(最推荐)

如果能改/app2和/api对应应用的代码,直接把所有绝对路径的资源引用(比如/assets/xxx)改成相对路径(比如./assets/xxx或者assets/xxx)。这样浏览器会基于当前页面的URL(/app2/)去请求/app2/assets/xxx,Nginx的location /app2/规则就能匹配到,自动转发到5300端口,资源就能正常加载了。

这种方法最干净,后续维护也省心,没有Nginx配置上的额外开销。

方法二:用Nginx的sub_filter修改响应中的资源路径(无需改应用代码)

如果没法修改应用代码,可以让Nginx在转发/app2的响应时,自动把HTML里的绝对路径资源替换成带/app2前缀的路径。具体配置如下:

events {}

http {
    server {
        listen 8080;
        server_name 127.0.0.1;
        rewrite_log on;
        error_log  /var/log/nginx/error.log notice;

        location / {
            proxy_pass http://127.0.0.1:5200;
            proxy_set_header  Host 127.0.0.1:5200;
        }

        location /api {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header  Host 127.0.0.1:8000;
            # 同样处理/api的资源路径
            sub_filter '/assets/' '/api/assets/';
            sub_filter_once off;
        }

        location = /app2 {
            return 302 /app2/;
        }

        location /app2/ {
            proxy_pass http://127.0.0.1:5300/;
            proxy_set_header  Host 127.0.0.1:5300;
            # 替换HTML中所有/assets/为/app2/assets/
            sub_filter '/assets/' '/app2/assets/';
            sub_filter_once off; # 确保替换所有匹配的资源路径
        }

        # 新增处理/app2/assets的路由,转发到5300的对应路径
        location /app2/assets/ {
            proxy_pass http://127.0.0.1:5300/assets/;
            proxy_set_header  Host 127.0.0.1:5300;
        }

        # 新增处理/api/assets的路由,转发到8000的对应路径
        location /api/assets/ {
            proxy_pass http://127.0.0.1:8000/assets/;
            proxy_set_header  Host 127.0.0.1:8000;
        }
    }
}

注意:这个方法需要你的Nginx编译时包含了ngx_http_sub_module模块,大部分主流发行版的预编译Nginx都带这个模块,如果没有的话需要重新编译Nginx加上这个模块。

方法三:根据Referer路由资源请求(适合不能改应用也不想用sub_filter的场景)

另一种思路是,通过浏览器发送的Referer请求头,判断资源请求来自哪个应用的页面,然后转发到对应的上游端口。配置示例:

events {}

http {
    # 定义一个map,根据Referer判断资源要转发到哪个上游
    map $http_referer $asset_upstream {
        ~*/app2/ http://127.0.0.1:5300;
        ~*/api/ http://127.0.0.1:8000;
        default http://127.0.0.1:5200;
    }

    server {
        listen 8080;
        server_name 127.0.0.1;
        rewrite_log on;
        error_log  /var/log/nginx/error.log notice;

        location / {
            proxy_pass http://127.0.0.1:5200;
            proxy_set_header  Host 127.0.0.1:5200;
        }

        location /api {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header  Host 127.0.0.1:8000;
        }

        location = /app2 {
            return 302 /app2/;
        }

        location /app2/ {
            proxy_pass http://127.0.0.1:5300/;
            proxy_set_header  Host 127.0.0.1:5300;
        }

        # 处理所有/assets开头的资源请求,根据map结果转发
        location /assets {
            proxy_pass $asset_upstream;
            proxy_set_header Host $host;
        }
    }
}

不过这个方法有个小缺点:如果浏览器没有发送Referer头(比如某些隐私模式下),资源会默认转发到5200端口,还是会出错,所以优先级不如前两种方法。

你可以先试试方法一,要是改应用代码不方便,就用方法二,亲测有效!

备注:内容来源于stack exchange,提问作者Asmaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 13:28:04