Set AWS Cloudfront Distribution Cache-Control Policy
Budget: $10 – $30 AUD
My website is hosted on an AWS EC2 instance using Open Litespeed. All static files (images/CSS/JS/fonts) are served via AWS Cloudfront distribution.
The issue:
I would like my static assets (fonts/css/js/images) served by Cloudfront to be cached for 6 months, but presently they’re being served at 7 day expiry due to AWS default behaviour.
AWS’s default behaviour is as follows: it passes through any cache-control header from referrer, but if none is present it will automatically default to 7 days.
The referrer is a CSS file hosted on Cloudfront itself (Line 7k) which has no cache-control header (Line 7h).
AWS’s default behaviour when no header is received is to respond with cache-control max-age of 7 days (Line 6d).
The server also sends back two more expires headers (Line 6i and 6j)
Unfortunately, you cannot set a cache-control header in Cloudfront itself (from AWS documentation).
An example request and response header for a font file:
1. Request URL: https://redacted.cloudfront.net/wp-content/uploads/elementor/custom-icons/redacted-24/font/redacted.woff2?13513404
2. Request Method: GET
3. Status Code: 200
4. Remote Address: 65.8.29.125:443
5. Referrer Policy: strict-origin-when-cross-origin
6. Response Headers
a. accept-ranges: bytes
b. access-control-allow-origin: *
c. age: 729
d. cache-control: public, max-age=604800
e. content-length: 10924
f. content-type: font/woff2
g. date: Sun, 05 Sep 2021 04:58:53 GMT
h. etag: "2aac-611f1761-1436806;;;"
i. expires: Sun, 12 Sep 2021 04:58:53 GMT
j. expires: max-age=A10368000, public
k. last-modified: Fri, 20 Aug 2021 02:45:53 GMT
l. permissions-policy: fullscreen=(self),geolocation=*,camera=()
m. referrer-policy: strict-origin-when-cross-origin
n. server: LiteSpeed
o. strict-transport-security: max-age=15552000; includeSubDomains;preload
p. via: 1.1 redacted1.cloudfront.net (CloudFront)
q. x-amz-cf-id: 4TEYrZbsXXCAqGN_s_M6wIpIVshYeKmk0n7VlnktIc1BEEIXlfbP2A==
r. x-amz-cf-pop: MEL50-C2
s. x-cache: Hit from cloudfront
t. x-content-type-options: nosniff
u. x-frame-options: SAMEORIGIN
v. x-xss-protection: 1; mode=block
7. Request Headers
a. :authority: redacted.cloudfront.net
b. :method: GET
c. :path: /wp-content/uploads/elementor/custom-icons/redacted-24/font/redacted.woff2?13513404
d. :scheme: https
e. accept: */*
f. accept-encoding: gzip, deflate, br
g. accept-language: en-AU,en;q=0.9
h. cache-control: no-cache
i. origin: https://www.redacted.com.au
j. pragma: no-cache
k. referer: https://redacted.cloudfront.net/wp-content/litespeed/css/abfec40b0c0c5eb030b24cdcc94ecf0f.css
l. sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92".
m. sec-ch-ua-mobile: ?1
n. sec-fetch-dest: font
o. sec-fetch-mode: cors
p. sec-fetch-site: cross-site
q. user-agent: Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36
So you can see the request header has no-cache (line 7h) and therefore AWS is applying its default behaviour to of 7 days to the response cache-control header (line 6d).
In htaccess there is the usual mod_headers.c stuff is in there (but is ignored because I’ve come to understand Open Litespeed ignores this).
In Litespeed Cache plugin in Wordpress, Default Public Cache is set for 15552000 seconds with no effect.
Files are not in an S3 distribution, so Lambda@Edge solution is not possible.
The issue:
I would like my static assets (fonts/css/js/images) served by Cloudfront to be cached for 6 months, but presently they’re being served at 7 day expiry due to AWS default behaviour.
AWS’s default behaviour is as follows: it passes through any cache-control header from referrer, but if none is present it will automatically default to 7 days.
The referrer is a CSS file hosted on Cloudfront itself (Line 7k) which has no cache-control header (Line 7h).
AWS’s default behaviour when no header is received is to respond with cache-control max-age of 7 days (Line 6d).
The server also sends back two more expires headers (Line 6i and 6j)
Unfortunately, you cannot set a cache-control header in Cloudfront itself (from AWS documentation).
An example request and response header for a font file:
1. Request URL: https://redacted.cloudfront.net/wp-content/uploads/elementor/custom-icons/redacted-24/font/redacted.woff2?13513404
2. Request Method: GET
3. Status Code: 200
4. Remote Address: 65.8.29.125:443
5. Referrer Policy: strict-origin-when-cross-origin
6. Response Headers
a. accept-ranges: bytes
b. access-control-allow-origin: *
c. age: 729
d. cache-control: public, max-age=604800
e. content-length: 10924
f. content-type: font/woff2
g. date: Sun, 05 Sep 2021 04:58:53 GMT
h. etag: "2aac-611f1761-1436806;;;"
i. expires: Sun, 12 Sep 2021 04:58:53 GMT
j. expires: max-age=A10368000, public
k. last-modified: Fri, 20 Aug 2021 02:45:53 GMT
l. permissions-policy: fullscreen=(self),geolocation=*,camera=()
m. referrer-policy: strict-origin-when-cross-origin
n. server: LiteSpeed
o. strict-transport-security: max-age=15552000; includeSubDomains;preload
p. via: 1.1 redacted1.cloudfront.net (CloudFront)
q. x-amz-cf-id: 4TEYrZbsXXCAqGN_s_M6wIpIVshYeKmk0n7VlnktIc1BEEIXlfbP2A==
r. x-amz-cf-pop: MEL50-C2
s. x-cache: Hit from cloudfront
t. x-content-type-options: nosniff
u. x-frame-options: SAMEORIGIN
v. x-xss-protection: 1; mode=block
7. Request Headers
a. :authority: redacted.cloudfront.net
b. :method: GET
c. :path: /wp-content/uploads/elementor/custom-icons/redacted-24/font/redacted.woff2?13513404
d. :scheme: https
e. accept: */*
f. accept-encoding: gzip, deflate, br
g. accept-language: en-AU,en;q=0.9
h. cache-control: no-cache
i. origin: https://www.redacted.com.au
j. pragma: no-cache
k. referer: https://redacted.cloudfront.net/wp-content/litespeed/css/abfec40b0c0c5eb030b24cdcc94ecf0f.css
l. sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92".
m. sec-ch-ua-mobile: ?1
n. sec-fetch-dest: font
o. sec-fetch-mode: cors
p. sec-fetch-site: cross-site
q. user-agent: Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36
So you can see the request header has no-cache (line 7h) and therefore AWS is applying its default behaviour to of 7 days to the response cache-control header (line 6d).
In htaccess there is the usual mod_headers.c stuff is in there (but is ignored because I’ve come to understand Open Litespeed ignores this).
In Litespeed Cache plugin in Wordpress, Default Public Cache is set for 15552000 seconds with no effect.
Files are not in an S3 distribution, so Lambda@Edge solution is not possible.