无法通过 Cloudfront 从 EC2 解码 CORS 压缩内容

Posted

技术标签:

【中文标题】无法通过 Cloudfront 从 EC2 解码 CORS 压缩内容【英文标题】:Unable to decode CORS gzipped content from EC2 via Cloudfront 【发布时间】:2015-07-16 23:47:11 【问题描述】:

这可能与Serving gzipped CSS and javascript from Amazon CloudFront via S3 有关,但是尽管我遵循了文档,但我仍然可以解决这种情况:

一个 S3 存储桶包含我已 gzip 压缩的文件(使用 grunt-contrib-compress,如果有任何相关性。)

我的存储桶有一个 CORS 配置:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*.myorigin.net</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

存储桶通过 Cloudfront 提供服务。

我的 Cloudfront 已将 CORS 配置为:

允许 GET、HEAD、OPTIONS、PUT 等... 在 HTTPS 上 缓存 OPTIONS 请求 将 Access-Control-Request-Headers、Access-Control-Request-Method 和 Origin 列入白名单

使用 curl,我可以获得我的资源,带有正确的标头来请求 gzip,我得到一个 gzip 压缩版本

curl --insecure https:/whatever.cloudfront.net/.../foo.js --silent -H "Accept-Encoding:gzip,deflate,sdch" -I

HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Length: 33990
Connection: keep-alive
Date: Wed, 06 May 2015 17:12:53 GMT
Content-Encoding: gzip
Last-Modified: Wed, 06 May 2015 16:36:40 GMT
ETag: "7a92919df6117827de9474851afe06c0"
Accept-Ranges: bytes
Server: AmazonS3
Age: 70
X-Cache: Hit from cloudfront
Via: 1.1 (redacted).cloudfront.net (CloudFront)
X-Amz-Cf-Id: iaghGGDg3f3l4njz7mpXeOzqIS5OCR5kaehk4Td4-Bxiv2KtljHVlQ==

我可以通过添加--compressed 标志来解码内容,因此文件似乎是正确的。

如果我现在再次使用 curl 执行 CORS 请求,我会得到正确的编码:

curl --insecure https://.../foo.js --silent -H "Accept-Encoding: gzip,deflate,sdch" -I -H "Origin: myorigin.net"
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Length: 33990
Connection: keep-alive
Date: Wed, 06 May 2015 17:16:06 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD
Access-Control-Max-Age: 3000
Content-Encoding: gzip
Last-Modified: Wed, 06 May 2015 16:36:40 GMT
ETag: "7a92919df6117827de9474851afe06c0"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
X-Cache: Miss from cloudfront
Via: 1.1 redacted.cloudfront.net (CloudFront)
X-Amz-Cf-Id: kaUV4S9wiCGzXp8N_Gg2LhGK8uYw1-qRtSw6w_Ry4V8oHZiLRvWULA==

由于某种原因,当我的 浏览器 发出请求时...没有“内容编码”,因此内容没有解压缩,因为我正在加载它requirejs,我得到一个严重的错误。

Request :
GET /resources-gz/foo.js HTTP/1.1
Host: d28p9e2ugw1o8w.cloudfront.net
Connection: keep-alive
Cache-Control: no-cache
Accept: */*
Pragma: no-cache
User-Agent: Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Referer: http://localhost:3000/start
Accept-Encoding: gzip,deflate,sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2

Response:
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Length: 33990
Connection: keep-alive
Date: Wed, 06 May 2015 16:31:27 GMT
Last-Modified: Wed, 06 May 2015 14:36:32 GMT
ETag: "7a92919df6117827de9474851afe06c0"
Accept-Ranges: bytes
Server: AmazonS3
Age: 1261
X-Cache: Hit from cloudfront
Via: 1.1 eazeaze.cloudfront.net (CloudFront)
X-Amz-Cf-Id: IjpNd37e-c38Moz3HQJ940KNTXfp1NN7O4enQJUYPd6Aet5Egw8XPg==

我显然错过了什么......

【问题讨论】:

【参考方案1】:

是的,你错过了一些东西。

读取最后一个响应的响应头。

Last-Modified: Wed, 06 May 2015 14:36:32 GMT
ETag: "7a92919df6117827de9474851afe06c0"
Age: 1261
X-Cache: Hit from cloudfront

这是 CloudFront 缓存命中,CloudFront 在您请求之前 20 多分钟从 S3 获取此对象...并且此版本的对象最后一次在 S3 中修改是两个多小时前...所以,您正在获得一份可能可以追溯到您“修复”您最近修复的任何内容之前的副本。

当一个对象的 etag 没有改变时,这意味着 body 没有改变......但这并不意味着响应头的任何内容。

对此进行测试的最简单方法是在 S3 中放入一个您以前从未使用过的名称的新文件...当然是 gzip,然后再次尝试下载。

【讨论】:

那么为什么curl 完成的请求会缓存未命中,并接收到正确的标头,而浏览器完成的请求却是“旧”版本?另外,我启动了缓存的云端失效,它似乎没有帮助......谢谢! 当您从浏览器加载Age: 值时它会增加吗?如果不是,浏览器会假装从 CloudFront 获取它,但实际上是从它自己的本地浏览器缓存中加载它。 好吧,实际上,我想我已经解决了我的缓存失效问题(并且没有等待足够长的时间。)从一个干净的状态返回后,事情似乎还不错。所以这就是我所缺少的:耐心;)!!

以上是关于无法通过 Cloudfront 从 EC2 解码 CORS 压缩内容的主要内容,如果未能解决你的问题,请参考以下文章

CloudFront + EC2 + Apache + PHP

Cloudfront 和 EC2

EC2 上用于 Wordpress 的 Cloudfront

AWS 将 EC2 替换为 CloudFront

CloudFront 到 EC2 源返回 502 错误。我该如何调查?

我需要亚马逊的 EC2、Cloudfront、RDS 吗?