Perfect global user experience requires use of content delivery network to minimize latency. CloudFront is a CDN built by the AWS cloud. CloudFront features a programmable edge compute provided by Lambda@Edge.
As I mentioned in previous AWS Tips 06/2020 - Lambda@Edge functions are interesting. Let me show you a basic use-case for edge compute functions.
S3 and Origin Access Identity
Content can be served from S3 to CloudFront CDN via traditional S3 HTTP endpoint or using Origin Access Identity. Origin Access Identity provides better access control and CloudFront can directly access S3 objects.
There is one edge case that must be handled when using Origin Access Identity. Requests going to
/example (or a folder) won't automatically serve
/example/index.html S3 object because such redirect or alias doesn't exist. Result of such request will be a 404 error returned from S3 to CloudFront and to the client.
This problem can be solved with simple Lambda@Edge function triggered by Origin Request. CloudFront allows you to attach Lambda@Edge functions to four stages of request and response processing:
viewer-request- triggered when client HTTP request accesses the CloudFront distribution.
origin-request- triggered on cache miss when CloudFront forwards the client request to distribution Origin.
origin-response- triggered when Origin returns the HTTP response to CloudFront.
viewer-response- triggered when CloudFront returns the HTTP response to the client.
Back to the
/example/ folder 404 problem. It's ideal to use
origin-request because we can detect access with
/ at the end of URI path. We can rewrite the request path from non-existent
/example/index.html before the HTTP request hits S3.
Basic Lambda@Edge rewrite
Consider the following Lambda@Edge Python 3 code that rewrites the URI as described. The handler function looks at CloudFront request object and the last character of the URI path and conditionally appends
index.html to it.
Regex Lambda@Edge rewrite
Another version of this function that may not be as fast is using a regular expression to rewrite the URI path in similar fashion. I've included this version because it is useful also for other types of URI rewrites.
Easiest deployment of this function can be done through the SAM tools.
Here's a useful serverless stack snippet for Lambda@Edge functions. Lambda@Edge function resource is deployed with Publishing Alias. Publishing Alias handles required function Version for Lambda@Edge. Place the above rewrite function code in
code_directory/app.py. SAM will find it, package it and deploy it.
And finally the CloudFront distribution resource default Cache behavior configuration for
origin-request. Triggerring the function before request gets sent to the Origin. This behavior can be customized to non-default if you have multiple CloudFront Distribution Origins.
CloudWatch Logs Expiration
CloudWatch Logs have a 5GB free tier. Many customers want to stay within this limit to keep their AWS bill low. Speaking from experience, it is easy to max out the free tier with a few Lambda functions logging their messages. In default configuration AWS Lambda functions write to CloudWatch Log Groups with no expiration and these logs are never deleted. The trick to stay in the free tier is setting the log expiration directly from within your CloudFormation or SAM stack with the following snippet. The snippet just creates
AWS::Logs::LogGroup resource and configures the log message expiration.