Open duswie opened 1 year ago
I think it would be great if we could even extend it using ResponseHeaderPolicy and also pass options to define the strict transport security etc.
Thanks for your Feedback! My current solution for custom response headers is as follows and work fine for me. When I find time, I will try to implement it natively.
resources:
Resources:
ResponseHeadersPolicyBuildAssets:
Type: AWS::CloudFront::ResponseHeadersPolicy
Properties:
ResponseHeadersPolicyConfig:
Name: AddCacheControlHeader
CustomHeadersConfig:
Items:
- Header: Cache-Control
Override: false
Value: max-age=31536000
constructs:
website:
#...
assets:
'/build/*': public/build
extensions:
distribution:
Properties:
DistributionConfig:
CacheBehaviors:
0:
ResponseHeadersPolicyId: !Ref ResponseHeadersPolicyBuildAssets
@duswie thanks for that. Is this the actual content of a working .yml
file?
I am asking because the 0:
should probably be -
, and once that's changed, there are a few properties that are required that don't work for me (throw errors). Examples: TargetOriginId
, ViewerProtocolPolicy
etc.
Disclaimer: I am using static-website
and not server-side-website
Here is my related discussion about caching of static assets: https://github.com/getlift/lift/discussions/370
An alternative could be to extend the cloudfront function but unfortunately, I could not figure out how to do that programmatically.
Cheers
yes, im using it like that, but I only posted the relevant parts. 0:
is used cause it has to be an object in order to get merged with the exiting CacheBehavior
with index 0 generated by lift. Otherwise they all get overwritten.
It's not tested with the static-website
construct.
You might check the ejected CloudFormation template for the right indices.
Hey @duswie I am not sure what I am doing wrong on static-website
. Anyway an alternative I found was to modify/overriding the previous response Cloudfront function:
function handler(event) {
var response = event.response;
response.headers = Object.assign({}, {
"x-frame-options": {
"value": "SAMEORIGIN"
},
"x-content-type-options": {
"value": "nosniff"
},
"x-xss-protection": {
"value": "1; mode=block"
},
"strict-transport-security": {
"value": "max-age=63072000"
}
}, response.headers);
var request = event.request ? event.request : null;
var uri = request.uri ? request.uri : '';
// if it is not / and does not end with .html add long term caching!
if (uri != '' && !uri.endsWith('/') && !uri.endsWith('.html')) {
Object.assign(response.headers, {
"cache-control": { "value": "public, max-age=63072000" },
"enrico-was-here": { "value": "yay" }
});
}
return response;
}
This had the wanted behaviour. For sure not the most elegant way, but it did the job for now :)
Start from the Use-case
It's best practise to serve static assets with a efficient cache policy: https://web.dev/uses-long-cache-ttl/
This is especially relevant when using an asset build system with cache busting (dynamic asset names). In this case I just want to set one Cache-Control header for all assets.
Example Config
Implementation Idea
A) CloudFront function: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-cache-control-header.html
or
B) CloudFront Response Header Policy (AWS::CloudFront::ResponseHeadersPolicy) https://docs.aws.amazon.com/de_de/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-responseheaderspolicy.html
Not sure which one performs better, but I think the response header policy is the 'cleaner' way.
I look forward to your feedback and would implement the feature if desired.