反向代理到静态网站不起作用

Reverse proxying to static website not working

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

在其中,我设置了一个反向代理到我的托管在 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. The Netlify customer service told me that they don't support reverse proxying, but that I could use their own redirects 时,我遇到了类似的问题。

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

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

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

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

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

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 吗?

你应该这样做吗?

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


怎么做。

不过,如果你还想用nginx来做,那真的很简单,而且这是一个围绕nginx很受欢迎的问题:

你基本上只需要将 front-end 上的 /apps/app1/ 映射到后端的 / ,它可以像这样完成 - 注意尾部斜杠非常重要此处 — 根据 http://nginx.org/r/proxy_pass(将其称为 "URI" 的存在):

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

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

我的整个配置如下所示:

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 前缀下响应。你会立即避免所有头痛。

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

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

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

"homepage": ".",

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