从AWS Cloudfront

时间:2016-05-15 02:45:27

标签: caching nginx fonts amazon-cloudfront cross-domain-policy

所以,这就是我的难题!在过去的三天里,我一直试图让Cloudfront与我的nginx服务器很好地玩耍...阅读了无数的StackOverflow帖子和博客文章......搜索了互联网,我仍然遇到有关跨域访问策略的问题它涉及Cloudfront服务字体。我将发布我的完整设置,希望有更多专业知识的人可以帮我弄清楚发生了什么。将来,我希望这篇文章能够为面临类似问题的许多其他人提供服务。 这里......

Nginx配置:

我有一个带有以下服务器块配置的nginx webserver。 (...为简洁而截断)

    server {
        server_name  example.com www.example.com;
        root /var/www/example.com/html;
        index index.html index.htm;

        location / {
            try_files $uri $uri/ =404;
        }
        location /assets {
            autoindex on;
        }

        # Media
        location ~* \.(jpe?g|gif|png|ico|cur|gz|svgz?|mp4|ogg|ogv|webm|htc|webp)$ {
            expires 1M;
            access_log off;
            add_header Cache-Control public;
        }

        # Fonts
        location ~* \.(eot|ttf|woff|woff2|svg)$ {
            expires 365d;
            access_log off;
            add_header Cache-Control public;
            add_header Access-Control-Allow-Origin example.com;
            // Have also tried setting the "Access-Control-Allow-Origin" header to "*", but I'd prefer not to do this for security reasons.
        }

    }

仅供参考:我想要服务并卸载到CloudFront的所有网站文件都在我的虚拟主机的/assets目录中。 (即http://example.com/assets/.。)

CloudFront的:

我使用以下设置创建了一个新的CloudFront分配:

注意:我没有使用S3来托管我的网站文件和资产。

一般:

  • 替代域名(CNAME): static.example.com
  • 默认根对象: index.html

起源:

  • Origin域名: example.com
  • 原点路径:(留空)
  • 原始SSL协议: TLSv1.2,TLSv1.1,TLSv1
  • 原始协议策略:仅限HTTP
  • HTTP端口: 80
  • HTTPS端口: 443
  • Origin自定义标题:(无)

行为:

  • 路径模式:默认()*
  • 查看器协议策略: HTTP和HTTPS
  • 允许的HTTP方法: GET,HEAD
  • 缓存HTTP方法: GET,HEAD(默认缓存)
  • 转发标题:白名单
    • 访问控制允许来源
  • 对象缓存:使用原始缓存标头
  • 转发查询字符串:否(改进缓存)
  • 自动压缩对象:

DNS设置:

我的区域文件的一部分......

example.com. 1800 IN A 12.34.567.890  //faked IP here for privacy reasons
www.example.com. 1800 IN CNAME example.com.
static.example.com. 1800 IN CNAME kg72kgf83nhfy3.cloudfront.net.  //faked CloudFront dist. domain name here for privacy reasons

发生了什么?为什么它不合适?

因此,CloudFront会处理和部署我的发行版,并且我假设从我的 ' / assets /..' 中提取资产网络目录。所有srchref和CSS url()引用都指向我当前的HTML和CSS文档中的 http://static.example.com ,包括所有font-face引用。部署分发后,我在浏览器中点击了我的网站 http://example.com

似乎所有静态网站资产都是从CloudFront正确提供的,具有我的nginx配置中定义的适当缓存标头... EXCEPT ... webfonts。我在浏览器控制台中丢失了页面上的字体和跨域访问策略错误消息。

标题 -

  • 图片,供参考(在ping我的服务器时)

    curl -I "http://example.com/assets/images/image1.png"
    HTTP/1.1 200 OK
    Server: nginx/1.6.3
    Date: Sun, 15 May 2016 02:09:25 GMT
    Content-Type: image/png
    Content-Length: 194665
    Last-Modified: Sun, 15 May 2016 01:52:35 GMT
    Connection: keep-alive
    ETag: "5737d663-2f869"
    Expires: Tue, 14 Jun 2016 02:09:25 GMT
    Cache-Control: max-age=2592000
    Cache-Control: public
    Accept-Ranges: bytes
    
  • 字体(在ping我的服务器时)

    curl -I "http://example.com/assets/fonts/webfont.woff"
    HTTP/1.1 200 OK
    Server: nginx/1.6.3
    Date: Sun, 15 May 2016 02:10:29 GMT
    Content-Type: application/font-woff
    Content-Length: 8752
    Last-Modified: Sun, 15 May 2016 01:51:55 GMT
    Connection: keep-alive
    Vary: Accept-Encoding
    ETag: "5737d63b-2230"
    Expires: Mon, 15 May 2017 02:10:29 GMT
    Cache-Control: max-age=31536000
    Cache-Control: public
    Access-Control-Allow-Origin: example.com
    Accept-Ranges: bytes
    
  • 相同的图片(从CloudFront请求时)

    curl -I "http://static.example.com/assets/images/image1.png"
    HTTP/1.1 200 OK
    Content-Type: image/png
    Content-Length: 194665
    Connection: keep-alive
    Server: nginx/1.6.3
    Date: Sun, 15 May 2016 02:39:16 GMT
    Last-Modified: Sun, 15 May 2016 01:52:35 GMT
    ETag: "5737d663-2f869"
    Expires: Tue, 14 Jun 2016 02:39:16 GMT
    Cache-Control: max-age=2592000
    Cache-Control: public
    Accept-Ranges: bytes
    X-Cache: Miss from cloudfront
    Via: 1.1 lots_of_random_characters_i_dont_know_if_should_share_here.cloudfront.net (CloudFront)
    X-Amz-Cf-Id: lSM1plINYENbYycBn424LJ2wdtDhS3CpqAFiDSoxQDEctP_WM09bUQ==
    
  • 相同字体(从CloudFront请求时)

    curl -I "http://static.example.com/assets/fonts/webfont.woff"
    HTTP/1.1 200 OK
    Content-Type: application/font-woff
    Content-Length: 8752
    Connection: keep-alive
    Server: nginx/1.6.3
    Date: Sun, 15 May 2016 02:41:00 GMT
    Last-Modified: Sun, 15 May 2016 01:51:55 GMT
    ETag: "5737d63b-2230"
    Expires: Mon, 15 May 2017 02:41:00 GMT
    Cache-Control: max-age=31536000
    Cache-Control: public
    Access-Control-Allow-Origin: example.com
    Accept-Ranges: bytes
    Vary: Accept-Encoding
    X-Cache: Miss from cloudfront
    Via: 1.1 lots_of_random_characters_i_dont_know_if_should_share_here.cloudfront.net (CloudFront)
    X-Amz-Cf-Id: vNfiyurS8pjosofnpLNSrnZuaGFg0V4xIs4ySCm05NKDMZ_PozhuOg==
    

将我的网站加载到 http://example.com ,一切似乎都有效(即图片)除了网络字体。检查浏览器控制台会为每种字体输出以下消息:

  

源自' http://static.example.com'的字体已被跨源资源共享策略阻止加载:“访问控制 - 允许 - 来源”'标头包含无效值' example.com'。起源' http://example.com'因此不允许访问。

那么,任何人都有任何想法?我会非常欣赏帮助/输入。我是一个年轻的网络开发者,只是想学习。

谢谢! :)
-Kyle


脚注:

  • One of many blog posts我已经跟着但还没有能够让事情发生。
  • 我的计划是将散列查询字符串附加到每个文件的末尾(即。//static.example.com/assets/images/image.png?622c6911),以使CloudFront缓存无效。这样我就不必总是通过更改名称重新上传新资产......我可以简单地控制HTML中的失效,并在我希望CloudFront从我的网络服务器请求该文件的最新版本时,将新的查询字符串附加到资产原点。
  • 我最终将为我的网站购买SSL证书,因此我希望流量支持HTTP和HTTPS请求。

1 个答案:

答案 0 :(得分:3)

解释如下:

  

' Access-Control-Allow-Origin'标头包含无效值' example.com'。起源' http://example.com'因此不允许访问。

原点是http://example.com ...不是example.com。您的响应标头的值不正确。根据定义,原点是scheme + hostname + port(在标准端口上为http和https省略了隐式端口80和443)。

当请求不受跨域规则约束时(例如图像的情况),浏览器会忽略Web服务器上的错误配置。对于字体,您要点击此墙,因为该值格式不正确。

  

add_header Access-Control-Allow-Origin example.com;

这是你问题的根源。您需要使用Origin:标头中的浏览器发送的相同来源进行响应,假设该来源确实有效且应该被允许。我不是nginx专家,根据this answer,您可以使用正则表达式验证传入的来源,并相应地设置响应:

if ($http_origin ~* "^https?://.*example\.com$" ) {
    add_header Access-Control-Allow-Origin $http_origin;
}

不熟悉nginx正则表达式的怪癖,我有点宽容,但你明白了。

在此之前,我们需要修复CloudFront缓存行为。

  

转发标题:白名单

     

访问控制允许来源

这不是一个请求标题......它是一个响应标题,因此将其列入白名单实际上并没有做任何事情。

您需要将Origin标头列入白名单,以便CloudFront将其转发到Web服务器,以便服务器可以使用Access-Control-Allow-Origin:中的相同值进行响应,如图所示上方。

Access-Control-Request-HeadersAccess-Control-Request-Method也应该列入白名单,但对于GET请求,我不知道它们会很重要。

除了OPTIONSGET之外,您还应修改允许的方法以包含HEAD

奖金材料:

  

我的计划是将散列查询字符串附加到每个文件的末尾(即//static.example.com/assets/images/image.png?622c6911),以使CloudFront缓存无效。

在这种情况下,您需要将Forward Query Strings设置为Yes

CloudFront根据对象实际发送到服务器的内容来缓存对象。如果查询字符串未转发到源,则附加查询字符串将仅使浏览器缓存而非CloudFront缓存无效。是的,即使您的服务器不想要或不需要查询字符串,如果查询字符串旨在用于缓存破坏CloudFront,您也需要启用此功能。这就是为什么不转发它们"改善缓存。"它将得到改善"在确定是否已有对象的缓存版本时,CloudFront完全忽略它们。

另请注意,Via标头不包含敏感信息,X-Amz-Cf-Id也不包含。