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

时间:2019-05-18 15:50:34

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

我有一个运行在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上时,我遇到了类似的问题。 Netlify客户服务告诉我他们不支持反向代理,但我可以使用他们自己的redirects

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

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

4 个答案:

答案 0 :(得分:1)

这是对我有用的方法,但是我只是在下面回答的其他人的帮助下才弄清楚了。事后看来,这似乎很简单,而且我自己没有弄清楚这一点我感到很愚蠢!

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

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

"homepage": ".",

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

答案 1 :(得分:0)

您的路径可能与静态变量不匹配,因为它在加载时会在/上下文中而不是/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 :(得分:0)

你应该这样做吗?

出于一个简单的原因,我不建议您这样做:由于您不控制上游,并且他们明确告诉您他们不支持您的方案,因此他们可以随时决定阻止您的代理服务器,然后由于设置不受支持,您的整个网站将被关闭。这就是很多人在白天尝试用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!
}

答案 3 :(得分:0)

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

我的整个配置如下所示:

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前缀下响应。并且您将立即避免所有头痛。