NGINX 除了 HTML 页面外,其他页面均出现 404 错误

NGINX 除了 HTML 页面外,其他页面均出现 404 错误

我在 docker 容器中将 nginx 设置为反向代理,以链接到容器外部的站点。我的 vhost 配置设置如下(我尝试在 home-assistant 的位置前添加 ^~):

server { # simple reverse-proxy
    listen       80;

    location / {
        proxy_pass http://192.168.1.99:6789;
    }

    location ^~ /home-assistant {
        proxy_pass http://192.168.1.99:8123/;
    }

    location /calibre-web/ {
        proxy_pass http://192.168.1.99:8181/;
    }

  }

对于 home-assistant 和 calibre-web 网站,页面都可以加载,但其他所有项目(图像、CSS 等...)都出现 404 错误。 如果我尝试单击应用程序中的链接,它会将我链接到 192.168.1.99/file,而不是 192.168.1.99/site-folder/file。下面是日志中的几条记录(请注意一个 200 响应和其他 404 响应)。我在这里做错了什么?提前感谢帮助。

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/logbook-66108d82763359a218c9695f0553de40.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:54 +0000] "GET /home-assistant/ HTTP/1.1" 200 1654 "-" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/icons/favicon-192x192.png HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/core-457d5acd123e7dc38947c07984b3a5e8.js HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

这是我的根 nginx.conf 的副本。我猜错误就在这里某处,我只是不知道在哪里。

答案1

您正在尝试从原始应用程序未知的位置代理传递请求。在 docker 容器中,应用程序仍然认为它是从网站根目录 ( http://192.168.1.99:8123/) 访问的,因此它会生成所有相对于 的 URL /,而不是相对于您的/home-assistant/或 的 URL /calibre-web/

解决这个问题的方法有很多种,你应该选择最适合你的方法:

1. 替换代理 HTML 中的链接

首先,在将结果提交给客户端之前,它可以替换从代理应用程序收到的每个链接ngx_http_sub_module。默认情况下不启用,因此您可能需要从源代码编译 nginx如果您的发行版没有它(要检查此模块运行的可用性nginx -V,它应该显示--with-http_sub_module在配置参数的某个地方)。

如果您选择此方法,请将以下指令添加到您的配置中:

location ^~ /home-assistant {
    rewrite ^/home-assistant(/.*)$ $1 break;
    proxy_pass http://192.168.1.99:8123/;
    sub_filter "<head>" "<head><base href=\"${scheme}://${host}/home-assistant\">";
}

2. 更改容器内的应用程序路径

将 docker 容器内的应用程序移动到 root/home-assistant而不是 root ,因此它将生成与该路径相关的服务内容中的所有 URL ,而不是 root /。这是一个显而易见的(也可能是最简单的)解决方案,它根本不需要接触 nginx 配置(而是在 docker 内编辑配置)

3. 根据 Referer 头选择上游

根据Referer标头确定应使用哪个上游。摘自此处。看起来相当聪明,尽管我自己不会在生产中使用它(注意它只适用于 css/js 文件)。

location ~* ^/(css|js)/.+\.(css|js)$ {
    #checking if referer is from home-assistant
    if ($http_referer ~ "^.*/home-assistant"){
        return 417;
    }

    #checking if referer is from calibre-web
    if ($http_referer ~ "^.*/calibre-web"){
        return 418;
    }
}

error_page   417  /home-assistant$request_uri;
error_page   418  /calibre-web$request_uri;

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123/;
}

location /calibre-web {
    proxy_pass http://192.168.1.99:8181/;
}

如果我是你,我会选择#2 - 在容器内移动应用程序,这是最简单且最不容易出错的方式来获取你需要的东西。

PS 我完全忘记了你可以直接从硬盘驱动器提供静态文件,因为你的后端与 nginx 位于同一台服务器上。这将需要一些依赖于应用程序的配置,但最终你会得到最有效的解决方案。

答案2

一种解决方案可能是不在指令中传递 URI proxy_pass

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123;
}

location ^~ /calibre-web/ {
    proxy_pass http://192.168.1.99:8181;
}

注意语句/中端口号后面缺少一个字符proxy_pass。这意味着 nginx 会将发送到服务器的 URI 传递给应用服务器。

如果是/字符 (URI),它将用该字符替换请求 URI。

此行为记录在http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

相关内容