AWS Cloudfront 作为具有自定义域的 Heroku 站点的 CDN

AWS Cloudfront as CDN for Heroku Site with Custom Domain

最近,我从 AWS Route 53 (brianpatrickhummel.com) 购买了一个域来托管个人作品集。投资组合站点已启动 运行ning,使用 S3 存储桶和 Cloudfront 作为 CDN。在投资组合网站上,访问者可以预览我构建的一些应用程序,这些应用程序使用 iframe 元素在现场启动,我注意到我的 Heroku 部署的应用程序需要 10-20 秒才能加载,因为这些网站上的访问者很少一般,没有 CDN 服务。

因此,我开始研究使用 AWS Cloudfront 作为 CDN。我从一个 Heroku 应用程序开始,添加一个自定义域,现在配置如下:

Domain Name: burger.brianpatrickhummel.com
DNS Target: burger.brianpatrickhummel.com.herokudns.com

最后一步是 "configure your app’s DNS provider to point to the Heroku-supplied DNS Target." 在这一步和正确配置 Cloudfront 分发之间,我 运行 自己陷入了混乱的漩涡。我不确定我在哪里进行某些 DNS/CNAME 更改,在 Cloudfront、Route 53 或两者中。

与这三种技术(Heroku、Cloudfront、Route 53)具体相关的在线文档不多,我花了很多时间在这三篇文章之间来回切换,但无济于事:

Heroku - Using Amazon CloudFront CDN

Configuring Amazon Route 53 DNS for Your Heroku App

我相信必要的更改本质上很简单,并且非常感谢那些可能对此特定配置有经验的人的任何见解。

---更新---

我有最后一个问题,现在我的所有 Heroku 应用程序都已成功通过 Cloudfront 进行路由,我意识到所有具有生成 POST HTTP 请求的组件的应用程序都会收到 403 - 禁止错误。这与相应 AJAX 调用中的相对 URL 有什么关系吗:

$(document).on("click", ".saveButton", function () {
  var thisId = $(this).attr("id");
  $.ajax({
    method: "POST",
    url: "/save/" + thisId
  }).done(function () {} 

我在 Cloudfront 文档中看到以下内容:

CloudFront always caches responses to GET and HEAD requests. You can also configure CloudFront to cache responses to OPTIONS requests. CloudFront does not cache responses to requests that use the other methods.

与成功发送请求相比,处理来自 Heroku 应用服务器的响应的问题更多吗?

-- 更新 2 --
根据 Cloudfront 文档中的以下声明,我认为这与 HTTP/HTTPS 有关:

CloudFront doesn't redirect DELETE, OPTIONS, PATCH, POST, or PUT requests from HTTP to HTTPS. If you configure a cache behavior to redirect to HTTPS, CloudFront responds to HTTP DELETE, OPTIONS, PATCH, POST, or PUT requests for that cache behavior with HTTP status code 403 (Forbidden).

Heroku 声明:

If you are wanting to serve Cloudfront assets using SSL you can simply use HTTPS on the distribution domain given to you by Amazon. Note, whilst you can create CNAME’s for this purpose, serving Cloudfront assets over your CNAME and SSL has an attached cost.

在 AWS Cloudfront Distribution Cache Behavior 设置中,您可以选择 Viewer Protocol Policy 三个选项:

If you want CloudFront to allow viewers to access your web content using either HTTP or HTTPS, specify HTTP and HTTPS. If you want CloudFront to redirect all HTTP requests to HTTPS, specify Redirect HTTP to HTTPS. If you want CloudFront to require HTTPS, specify HTTPS Only.

Cloudfront 文档继续指出:

Redirect HTTP to HTTPS Viewers can use both protocols, but HTTP requests are automatically redirected to HTTPS requests. CloudFront returns HTTP status code 301 (Moved Permanently) along with the new HTTPS URL. The viewer then resubmits the request to CloudFront using the HTTPS URL.

When a viewer makes an HTTP request that is redirected to an HTTPS request, CloudFront charges for both requests. For the HTTP request, the charge is only for the request and for the headers that CloudFront returns to the viewer. For the HTTPS request, the charge is for the request, and for the headers and the object returned by your origin.

HTTPS Only Viewers can access your content only if they're using HTTPS. If a viewer sends an HTTP request instead of an HTTPS request, CloudFront returns HTTP status code 403 (Forbidden) and does not return the object.

天哪,我不知道托管个人网站会有多复杂!

I'm uncertain as to of where I make certain DNS/CNAME changes, in Cloudfront, Route 53 or both

既然 Route53 是 DNS 服务(不是 CloudFront),那么您将在 Route53 中创建 CNAME 记录。您想要在 Route53 中创建 CNAME 记录,将您的子域指向 CloudFront。然后,您需要配置 CloudFront 以了解它需要通过配置备用域名字段来为该域提供服务。

Domain Name: burger.brianpatrickhummel.com

您会将其指向 Route 53 中的 CloudFront...但在您可以这样做之前,您需要创建一个新的 CloudFront 分配并将该主机名配置为该分配的备用域名。

DNS Target: burger.brianpatrickhummel.com.herokudns.com

在创建分配 CloudFront 时将其配置为源域名。

在缓存行为设置中,将 Host header 列入白名单,以便 Heroku 了解请求是针对哪个站点的。

这是我要执行的步骤,

由于您已经在 53 号公路上,

Get a free SSL from ACM

确认您对域电子邮件地址的 SSL 验证。 确保它看起来像下面的绿色,

Assign it to CloudFront Endpoint with the SSL and CNAME as well

您还将看到将在 Route53 中为此 SSL 端点自动创建一个 cname。

如果你 ping burger.brianpatrickhummel.com,它应该从云端响应。

现在在 Cloudfront 中设置 Origins 以将其指向您的端点以及所需的所有缓存设置。如果不需要缓存设置,可以全部设置为0,这样cloudfront就不会缓存任何数据了。

在您的 Cloudront 模式中,确保您在末尾有 * 以便它匹配所有 url 模式以将其转发到您的端点。

如果您的端点需要保护,您可以从 Cloudfront 传入额外的 headers 并确保请求是从 Cloudfront 发出的,而不是任何 public 端点。

好像Hostno longer trusted and accepted by heroku。它将不再 link 正确到达站点

改用Origin Custom Header

自定义的名称header会经过一些解析和大小写更改,因此要对其进行调试,请添加此命令以打印请求中提供的相关header。

puts request.headers.env.reject { |key| key.to_s.include?('.') }

您应该会在其中看到您的 header,但格式可能不同。

作为参考,我的 header 是 X-Request-ID(这是 recommended by Heroku 的额外用途),它被转换为 HTTP_X_REQUEST_ID