问题 如何将S3用作静态网页,将EC2用作REST API? (AWS)


通过AWS服务,我们可以从S3存储桶运行Web应用程序,并通过Load Balancer(在EC2实例上运行的Node.js应用程序集)中的REST API访问数据。

目前我们已经指定了URL如下:

  • API负载均衡器: API。somedomain.com
  • S3上的静态Web应用程序: somedomain.com

但是这个设置给我们带来了一系列问题,因为这个设置请求是CORS。我们可以使用特殊标头解决CORS问题,但这并不适用于所有浏览器。

我们想要实现的是在同一个域上运行API,但路径不同:

  • API负载均衡器: somedomain.com/ API
  • S3上的静态Web应用程序: somedomain.com

其中一个想法是将API Load Balancer附加到CDN,并在查询到达“/ api / *”路径时将所有请求转发到Load Balancer。但这不起作用,因为我们的API不仅使用HEAD和GET请求,还使用POST,PUT,DELETE。

另一个想法是使用第二个EC2实例而不是S3存储桶来托管网站(使用一些网络服务器,如nginx或apache)。但是当一切就绪时(S3静态内容托管),这会产生太多的开销。此外,如果使用此方案,我们将无法获得Amazon CloudFront性能的所有好处。

那么,您是否可以推荐如何组合Load Balancer和S3,以便它们可以在相同的域上运行,但具有不同的路径? (API on somedomain.com/ API 和Web应用程序 somedomain.com

谢谢!


8051
2018-06-25 12:09


起源



答案:


您不能拥有具有相同主机名的EC2实例和S3存储桶。考虑当Web浏览器向该主机名发出请求时会发生什么。 DNS将其解析为IP地址(或多个地址),并将请求的数据包传递到该地址。地址要么终止于EC2实例,要么终止于S3存储桶,而不是两者。

据我所知,您在S3上托管的静态网页包含JavaScript代码,可以向EC2实例发出各种HTTP请求。如果S3网页与EC2实例位于不同的主机上,则相同的源策略将阻止浏览器尝试某些请求。

我能看到的唯一解决方案是:

  • 向EC2实例发出所有请求,同时获取S3内容并在需要网页时将其提供给浏览器。
  • 让您的JavaScript使用iframe并更改 document.domain 在网页中的共同父源。例如,如果您的网页位于 www.example.com 你的EC2实例是在 api.example.com,JavaScript会改变 document.domain 到了 example.com 并且浏览器将允许来自的iframe www.example.com 与...沟通 api.example.com
  • 咬紧牙关并使用CORS。这真的不难,而且 它得到了支持 在所有远程浏览器中(IE 8和9都可以,但不是以标准方式)。

第一种方法并不好,因为在这种情况下你几乎不会使用S3。

第二种情况应该对你没问题。它应该适用于任何浏览器,因为它不是真正的CORS。因此不需要CORS头。但这很棘手。

第三种,CORS,方法应该没问题。您的EC2实例只需返回正确的标题,告诉S3存储桶中的网页,它们可以安全地与EC2实例通信。


11
2018-06-27 02:53



谢谢你这么好的解释!可能我们将采用CORS方法并为IE创建解决方法。 - user1671010
乐意。如果这样可以解决您的问题,请将其标记为已接听。 - Charles Engelke


答案:


您不能拥有具有相同主机名的EC2实例和S3存储桶。考虑当Web浏览器向该主机名发出请求时会发生什么。 DNS将其解析为IP地址(或多个地址),并将请求的数据包传递到该地址。地址要么终止于EC2实例,要么终止于S3存储桶,而不是两者。

据我所知,您在S3上托管的静态网页包含JavaScript代码,可以向EC2实例发出各种HTTP请求。如果S3网页与EC2实例位于不同的主机上,则相同的源策略将阻止浏览器尝试某些请求。

我能看到的唯一解决方案是:

  • 向EC2实例发出所有请求,同时获取S3内容并在需要网页时将其提供给浏览器。
  • 让您的JavaScript使用iframe并更改 document.domain 在网页中的共同父源。例如,如果您的网页位于 www.example.com 你的EC2实例是在 api.example.com,JavaScript会改变 document.domain 到了 example.com 并且浏览器将允许来自的iframe www.example.com 与...沟通 api.example.com
  • 咬紧牙关并使用CORS。这真的不难,而且 它得到了支持 在所有远程浏览器中(IE 8和9都可以,但不是以标准方式)。

第一种方法并不好,因为在这种情况下你几乎不会使用S3。

第二种情况应该对你没问题。它应该适用于任何浏览器,因为它不是真正的CORS。因此不需要CORS头。但这很棘手。

第三种,CORS,方法应该没问题。您的EC2实例只需返回正确的标题,告诉S3存储桶中的网页,它们可以安全地与EC2实例通信。


11
2018-06-27 02:53



谢谢你这么好的解释!可能我们将采用CORS方法并为IE创建解决方法。 - user1671010
乐意。如果这样可以解决您的问题,请将其标记为已接听。 - Charles Engelke


只是想补充一点,如果我们采用CORS方法和预检请求增加了服务器和网络带宽的开销,我们甚至可以考虑在CORS响应中添加标题“Access-Control-Max-Age”

访问控制 - 最大 - 年龄


0
2017-08-12 04:03