You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Nginx反向代理下静态文件路由配置问题求助

Nginx反向代理下静态文件路由配置问题求助

大家好,我最近在折腾Nginx反向代理的配置,碰到个静态文件路由的问题,卡了好一会儿,想请各位大佬支支招~

现状描述

我现在把Nginx作为服务跑在80端口,接收客户端的所有请求,同时有几个Docker容器各自暴露不同端口跑着独立的应用。目前我的Nginx配置大致是这样的:

server {
        listen       80;
        listen       [::]:80;
        server_name  server_name;
        location /app1{
                proxy_pass http://ip:3006/;
        }
        location /app2{
                proxy_pass http://ip:3007/;
        }
        location /app3{
                proxy_pass http://ip:3009/;
        }
}

每个应用本身的静态文件(css、js、媒体文件这些),直接用容器端口访问时都是正常的,但通过Nginx的/app1/app2这类路径访问就出问题了。

需求

我想要实现的是:用户访问http://ip/app1/media/dummy.wav这类路径时,Nginx能自动把请求路由到对应容器的正确资源上。

遇到的问题

现在的问题是,当用户通过Nginx访问应用时,页面里的静态资源加载失败了。我查了浏览器的网络请求发现,应用里的静态资源引用都是根路径开头的(比如/css/style.css),但通过Nginx代理后,浏览器会直接请求http://ip/css/style.css,而不是http://ip/app1/css/style.css,导致Nginx找不到这些资源,返回404。

可行解决方案

后来查了一些资料,整理出几个可行的解决办法,分享给大家:

1. 修改Nginx配置,修正请求路径并传递上下文信息(推荐)

这个方法不需要改应用代码,通过Nginx的rewrite和请求头来处理。修改后的配置如下:

server {
        listen       80;
        listen       [::]:80;
        server_name  server_name;

        location /app1/ {
                # 把请求路径中的/app1前缀去掉,转发给后端容器
                rewrite ^/app1/(.*)$ /$1 break;
                proxy_pass http://ip:3006/;
                # 告诉后端应用当前的上下文路径,部分框架会用这个生成正确的资源链接
                proxy_set_header X-Forwarded-Prefix /app1;
                # 传递必要的代理头,确保后端能获取客户端真实信息
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /app2/ {
                rewrite ^/app2/(.*)$ /$1 break;
                proxy_pass http://ip:3007/;
                proxy_set_header X-Forwarded-Prefix /app2;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /app3/ {
                rewrite ^/app3/(.*)$ /$1 break;
                proxy_pass http://ip:3009/;
                proxy_set_header X-Forwarded-Prefix /app3;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

这里有几个关键点:

  • location /app1改成location /app1/(末尾加斜杠),避免误匹配类似/app12这类路径
  • 通过rewrite规则提取/app1后的路径部分,转发给后端容器
  • 添加X-Forwarded-Prefix头,让后端框架知道当前的上下文路径,生成带前缀的资源链接

2. 修改应用内的静态资源引用为相对路径

如果能修改应用代码的话,可以把所有静态资源的引用改成相对路径。比如把<link href="/css/style.css">改成<link href="./css/style.css">或者<link href="css/style.css">,这样浏览器在/app1路径下会自动请求/app1/css/style.css,Nginx就能正确转发了。不过这个方法需要修改应用代码,适合小项目或者自己能控制代码的场景。

3. 用Nginx的sub_filter替换响应中的资源路径

如果没法修改应用代码,还可以让Nginx在返回给客户端的HTML里,自动替换根路径的资源链接为带前缀的路径。配置示例:

location /app1/ {
        proxy_pass http://ip:3006/;
        proxy_set_header Host $host;
        # 替换HTML中的根路径资源链接为带/app1前缀的路径
        sub_filter '/css/' '/app1/css/';
        sub_filter '/js/' '/app1/js/';
        sub_filter '/media/' '/app1/media/';
        # 开启多次替换,确保所有匹配的路径都被处理
        sub_filter_once off;
}

这个方法的缺点是需要逐个配置要替换的资源路径前缀,如果应用里的资源路径比较多,配置会比较繁琐,而且动态生成的路径可能会漏替换。

验证方法

改完配置后,执行nginx -s reload重启Nginx,然后访问http://ip/app1,打开浏览器开发者工具(F12)查看网络请求,确认静态资源的请求路径是/app1/css/xxx.css这类带前缀的路径,并且返回200状态码,就说明配置生效啦~

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

火山引擎 最新活动