Search code examples
amazon-web-servicesamazon-s3amazon-cloudfrontcache-controlaws-powershell

How can I cache to 1 minute with S3 and CloudFront and Write-S3Object


I have a staging CloudFront site that is sourced from S3

What I would like to do is to set this up so Cloudfront caches only for one minute and then any request after that will go back to the S3 to get new data. If possible I would also like to know how to turn off the caching completely.

I tried this:

Write-S3Object -BucketName "xx-staging" 
               -Key "index.html" 
               -Metadata @{"Cache-Control" = "60000"}
               -File "index.html" 

The result is this:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 24686
Connection: keep-alive
Date: Mon, 18 May 2015 14:14:21 GMT
x-amz-meta-cache-control: 60000
Last-Modified: Mon, 18 May 2015 13:45:46 GMT
ETag: "b2d38663e20237e056f8e507a2caa77a"
Accept-Ranges: bytes
Server: AmazonS3
Age: 1648
X-Cache: Hit from cloudfront
Via: 1.1 6d4df30b39d1e7ecggb0ecd7b8940b88.cloudfront.net (CloudFront)
X-Amz-Cf-Id: oNHGs5CK8hed2OJ_BPaeaf1zFzQE4w7tmnkOym5_1QAMvU6YjNwcfw==

When I try another request five minutes later I get a similar reply with

X-Cache: Hit from cloudfront

Can anyone point to what I am doing wrong.

Please note I am looking for an answer that uses Write-S3Object.

Note that I tried adding in the portal:

CacheControl max-age: 60000

This gave me the following which still says "Hit from cloudfront"

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 24686
Connection: keep-alive
Date: Mon, 18 May 2015 15:34:11 GMT
x-amz-meta-cache-control: 60000
Cache-Control: 60000
Last-Modified: Mon, 18 May 2015 15:26:29 GMT
ETag: "b2d38663e20237e056f8e507a2caa77a"
Accept-Ranges: bytes
Server: AmazonS3
Age: 82
X-Cache: Hit from cloudfront
Via: 1.1 cf25d52fc78aeceb914fb4445fd00a15.cloudfront.net (CloudFront)
X-Amz-Cf-Id: JHXjHLaUUzN4L0M7rqkrr97c2glFlNT_avHASTxDuQw6ePeK4mQppg==

Solution

  • Here's a nice primer for the Cache-Control header. You need the header to look like this*:

    Cache-Control: public,max-age=60
    

    The cache-control header uses seconds, not milliseconds. 'public' just means "it's okay to store this on a CDN", basically. I believe this will work in your initial Powershell command:

     -HeaderCollection @{"Cache-Control" = "public,max-age=60"}
    

    If you want to completely disable caching, set it like this*:

    Cache-Control: no-cache
    

    Or this:

    Cache-Control: max-age=60,must-revalidate
    

    I'd suggest using curl -D - http://s3-website-url to test that you have it right. That way you can forget about Cloudfront to verify the headers.

    * there are plenty of variations. This is very common way and will work.