Cloudfront为压缩和未压缩文件使用不同的Content-Type

时间:2017-03-02 07:24:44

标签: svg amazon-s3 content-type amazon-cloudfront

我正在通过S3和Cloudfront为静态网站生成器生成的网站提供服务。使用正确的内容类型将文件上载到S3。 DNS指向使用S3存储桶作为其来源的Cloudfront。 Cloudfront负责加密和压缩。我告诉Cloudfront自动压缩对象。这很好,直到我决定将一些使用过的图像从PNG更改为SVG。

每当一个文件被请求为未压缩时,它就会按照设置的Content-Type(image / svg + xml)按原样传送,并且网站会正确呈现。但是,如果请求压缩文件,则使用默认的Content-Type(application / octet-stream)传递文件,并且渲染中缺少图像。如果我然后右键单击图像并选择在新选项卡中打开图像,它将正确显示(没有页面的其余部分)。

结果与使用的浏览器无关。在Firefox中,我知道如何将其设置为强制请求压缩或未压缩的页面。我也试过curl检查标题。结果如下:

λ curl --compressed -v -o /dev/null http://dev.example.com/img/logo-6998bdf68c.svg
* STATE: INIT => CONNECT handle 0x20049798; line 1090 (connection #-5000)
* Added connection 0. The cache now contains 1 members
*   Trying 52.222.157.200...
* STATE: CONNECT => WAITCONNECT handle 0x20049798; line 1143 (connection #0)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to dev.example.com (52.222.157.200) port 80 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x20049798; line 1240 (connection #0)
* STATE: SENDPROTOCONNECT => DO handle 0x20049798; line 1258 (connection #0)
> GET /img/logo-6998bdf68c.svg HTTP/1.1
> Host: dev.example.com
> User-Agent: curl/7.44.0
> Accept: */*
> Accept-Encoding: deflate, gzip
>
* STATE: DO => DO_DONE handle 0x20049798; line 1337 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x20049798; line 1464 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x20049798; line 1474 (connection #0)
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< Content-Length: 7468
< Connection: keep-alive
< Date: Wed, 01 Mar 2017 13:31:33 GMT
< x-amz-meta-cb-modifiedtime: Wed, 01 Mar 2017 13:28:26 GMT
< Last-Modified: Wed, 01 Mar 2017 13:30:24 GMT
< ETag: "6998bdf68c8812d193dd799c644abfb6"
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
< X-Cache: RefreshHit from cloudfront
< Via: 1.1 36c13eeffcddf77ad33d7874b28e6168.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: jT86EeNn2vFYAU2Jagj_aDx6qQUBXFqiDhlcdfxLKrj5bCdAKBIbXQ==
<
{ [7468 bytes data]
* STATE: PERFORM => DONE handle 0x20049798; line 1632 (connection #0)
* Curl_done
100  7468  100  7468    0     0  44526      0 --:--:-- --:--:-- --:--:-- 48493
* Connection #0 to host dev.example.com left intact
* Expire cleared

对于未压缩的它看起来更好:

λ curl -v -o /dev/null http://dev.example.com/img/logo-6998bdf68c.svg
* STATE: INIT => CONNECT handle 0x20049798; line 1090 (connection #-5000)
* Added connection 0. The cache now contains 1 members
*   Trying 52.222.157.203...
* STATE: CONNECT => WAITCONNECT handle 0x20049798; line 1143 (connection #0)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to dev.example.com (52.222.157.203) port 80 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x20049798; line 1240 (connection #0)
* STATE: SENDPROTOCONNECT => DO handle 0x20049798; line 1258 (connection #0)
> GET /img/logo-6998bdf68c.svg HTTP/1.1
> Host: dev.example.com
> User-Agent: curl/7.44.0
> Accept: */*
>
* STATE: DO => DO_DONE handle 0x20049798; line 1337 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x20049798; line 1464 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x20049798; line 1474 (connection #0)
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Content-Type: image/svg+xml
< Content-Length: 7468
< Connection: keep-alive
< Date: Wed, 01 Mar 2017 20:56:11 GMT
< x-amz-meta-cb-modifiedtime: Wed, 01 Mar 2017 20:39:17 GMT
< Last-Modified: Wed, 01 Mar 2017 20:41:13 GMT
< ETag: "6998bdf68c8812d193dd799c644abfb6"
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
< Vary: Accept-Encoding
< X-Cache: RefreshHit from cloudfront
< Via: 1.1 ac27d939fa02703c4b28926f53f95083.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: AlodMvGOKIoNb8zm5OuS7x_8TquQXzAAXg05efSMdIKgrPhwEPv4kA==
<
{ [2422 bytes data]
* STATE: PERFORM => DONE handle 0x20049798; line 1632 (connection #0)
* Curl_done
100  7468  100  7468    0     0  27667      0 --:--:-- --:--:-- --:--:-- 33639
* Connection #0 to host dev.example.com left intact

出于性能原因,我不想关闭压缩。它看起来只会发生在SVG文件类型中。所有其他类型都有正确的,即。相同的Content-Type。我已经尝试使缓存无效,甚至通过将缓存时间设置为0秒来完全关闭缓存。上传到S3时,我无法上传压缩版本,因为上传过程是自动的,无法轻松更改单个文件。

我希望我做错了,因为这是最容易修复的。但我不知道设置有什么问题。我已经使用谷歌找到有类似问题的人,但看起来它只是我。谁有想法?

2 个答案:

答案 0 :(得分:0)

你误解了这个问题。 CloudFront不会更改Content-Type

但是,CloudFront会根据请求中的变体缓存同一对象的不同版本。

如果您注意到,这些对象的Last-Modified次不同。您最初在S3中设置了内容类型错误。您随后解决了这个问题,但CloudFront并未意识到元数据已发生变化,因为ETag没有发生变化,因此您会收到错误的RefreshHit响应。它在广告gzip编码支持的请求上提供旧版本。如果对象的实际有效负载已更改,CloudFront可能已经更新了其缓存。

执行invalidation清除缓存,几分钟后,此问题就会消失。

答案 1 :(得分:0)

我能够通过将MIME类型强制为“ image / svg + xml”而不是将其与python boto3同步后选择的“ binary / octet-stream”来解决此问题。

在S3存储桶中的svg上单击鼠标右键时,您可以通过查看元数据来检查模仿类型:

enter image description here

我不确定这是由python同步还是S3 / Cloudfront中的某些怪异引起的。我必须补充一点,那就是缓存失效在此之后不起作用。我必须使用正确的mimetype重新上传文件,以使Cloudfront可以正常访问svg。