【问题标题】:Reverse proxying to static website not working反向代理到静态网站不起作用
【发布时间】:2019-10-05 14:55:05
【问题描述】:

我有一个 nginx 服务器在 www.example.com 运行。

在其中,我设置了一个反向代理到我的一个静态网站,该网站托管在Zeit now

location /apps/app1/ {
    proxy_pass https://app1.username.now.sh;
}

但是,当我访问 www.example.com/apps/app1 时,我得到了正确的浏览器选项卡名称(在我的情况下为“React App”,因为我的静态网站是使用 React 制作的,默认名称是“React App”)。

在浏览器控制台中,我看到以下错误:

GET https://www.example.com/static/css/1.621e483e.chunk.css net::ERR_ABORTED 404 (Not Found)
GET https://www.example.com/manifest.json 404 (Not Found)
Manifest: Line: 1, column: 1, Unexpected token.

当我的静态网站托管在 Netlify 时,我遇到了类似的问题。 Netlify 客服告诉我他们不支持反向代理,但我可以使用他们自己的redirects

为什么我无法通过外部 URL 反向代理到静态网站?有没有办法解决这个问题?

更新 1: 我目前正在尝试将bluprince13.com/apps/renting-vs-buying/ 反向代理为renting-vs-buying.bluprince13.now.sh

【问题讨论】:

    标签: reactjs nginx nginx-location nginx-reverse-proxy netlify


    【解决方案1】:

    可能您的路径与静态数据不匹配,因为当它加载时,它会在/ 上下文中而不是/apps/app1/ 中寻找静态数据。因此,它不会与您的位置匹配,也不会代理到您的网站。

    我建议您在代理和主机中使用相同的路径,否则您将需要重写 URL,但您需要找到应用程序所服务的静态的每个路径模式。

    如果可能,请尝试在 / 上下文中使用子域并放置相同的基本标头以帮助您的应用程序更好地解析。

    server {
        listen 80;
        server_name app1.example.com;
    
        location / {
            proxy_set_header HOST $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            proxy_pass https://app1.username.now.sh/;
        }
    }
    

    希望对你有帮助。

    请注意:我认为您应该避免使用反向代理。您确定没有其他更好的解决方案,例如设置 CNAME 记录 DNS?

    【讨论】:

      【解决方案2】:

      你应该这样做吗?

      我不建议这样做,原因很简单:由于您不控制上游,并且他们明确告诉您他们不支持您的方案,他们可以随时决定阻止您的代理服务器,然后您的整个网站将由于不受支持的设置而关闭。这就是很多人在过去尝试用 Cloudflare 修复损坏的 Tumblr 时发生的事情(过去,从 Tumblr 获取空白页面是很常见的,因此,将 Cloudflare 放在它前面,实际上确实提高了速度并修复了空白页问题)。


      怎么做。

      但是,如果你还想用 nginx 来做,那真的很简单,而且这是一个围绕 nginx 很流行的问题:

      您基本上只需要将前端的/apps/app1/ 映射到后端的/,就可以这样做——注意尾斜线在这里非常重要——根据http://nginx.org/r/proxy_pass (将其称为“URI”的存在):

      location /apps/app1/ {
          proxy_pass https://app1.username.now.sh/; # DO NOT REMOVE trailing slash!
      }
      

      【讨论】:

      • 我添加了斜杠。不过还是不行。
      • @bluprince13 问题是您的应用使用绝对 URL 而不是相对 URL;它不能正常工作;一种选择可能是使用 $http_referer 来确定哪个应用程序请求哪个资源。
      【解决方案3】:

      这对我有用,但我只是在下面回答的其他人的帮助下才弄明白的。事后看来,这似乎很简单,我自己没有弄清楚,我觉得很傻!

      响应的 HTML 包含 CSS 和 JS 文件的绝对 URL。浏览器最初从 /apps/app1 前缀加载 HTML 页面,但随后它尝试从 /static、/favicon、/css 等加载资源。但是,那里什么都没有!

      问题在于应用程序使用绝对引用。我需要做的就是更改我的应用程序以使用相对引用。使用 React,您可以通过将其放入您的 package.json 轻松做到这一点(请参阅文档 here):

      "homepage": ".",
      

      现在,浏览器将从 /apps/app1/static、/apps/app1/favicon、/apps/app1/css 等正确加载资源。

      【讨论】:

        【解决方案4】:

        这是可能的,但有其技术上的缺点(除了一个明显的考虑,即您可能违反上游的服务条款)。

        我的整个配置如下所示:

        server {
          server_name localhost;
          listen *:8000;
        
          location /apps/ {
            sub_filter 'href="/c' 'href="/apps/c';
            sub_filter 'href="/f' 'href="/apps/f';
            sub_filter 'href="/m' 'href="/apps/m';
            sub_filter 'href="/s' 'href="/apps/s';
            sub_filter 'src="/s'  'src="/apps/s';
            sub_filter_once off;
            proxy_set_header Accept-Encoding "";
            proxy_pass https://renting-vs-buying.bluprince13.now.sh/;
          }
        }
        

        这里 Nginx 被配置为使用其sub_filter 模块替换响应的某些部分。我们指定要查找和替换的字符串。由于您的 HTML 很可能由 Webpack 之类的东西生成并且没有换行符,因此我们需要在每一行中重复替换,这就是 sub_filter_once off 的原因。

        关于Accept-Encoding。 Nginx 能够在text/html 响应中执行替换。仅有的。这意味着没有压缩。由于后端喜欢使用压缩内容进行响应,因此我们要求它不要这样做。

        几点说明:

        • 过滤器的静态列表很脆弱:在后端添加一些新前缀时,您的应用程序可能会中断;
        • 您正在浪费代理和后端之间的带宽,因为无法使用压缩。

        我建议最好的选择是更改您的应用程序,使其以/apps 前缀响应。你会立即避免所有的头痛。

        【讨论】:

        • 感谢您的回答。我不明白 c f m s 子过滤器的用途。
        • 这里的每个答案都告诉您相同的信息:响应的 HTML 包含 CSS 和 JS 文件的绝对 URL。当浏览器看到该绝对 URL 时,它会从该绝对路径中获取它,尽管您的页面位于 /apps。因此,您的浏览器最初从 /apps 前缀加载页面,然后尝试从 /static/favicon/css 加载资产(您注意到过滤器字符串的第一个字母吗?)
        • 你在使用 Chrome DevTools 控制台吗?在 Chrome 中打开一个新选项卡,打开开发工具,转到网络选项卡,然后打开应用程序的 URL。并且您应该能够看到浏览器发出了哪些请求、它们的完整 URL 以及哪些请求失败了。
        猜你喜欢
        • 1970-01-01
        • 2017-10-15
        • 2014-04-30
        • 1970-01-01
        • 2021-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多