Static Hosting #3 Fix Cloudfront 404 errors when visiting direct URLs

Now, because we’re using a REST API to communicate with the S3 bucket when visiting a direct URL it could actually show the error page instead. That’s because in this example we’re using gatsby which creates routes with folders and index files e.g /path/to/index.html but in the URL the route is actually /path/to. We can use lambda@edge to fix this.

Create a lambda function

Go to the AWS Lambda dashboard, create a new function in Node.js and paste the following code.

'use strict';
exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  // replace dangling / in the url with /index.html
  request.uri = request.uri.replace(//$/, '/index.html');
  // return to Cloudfront
  return callback(null, request);

This is quite straightforward, first we extract the request object from the event then replace the dangling / with /index.html and last but not least we send it back to Cloudfront.

Assign lambda to Cloudfront Distribution

At the time of writing, if we try to Add Trigger from the lambda dashboard, we won’t be able to find Cloudfront on the list. That’s because we’re not using regular Lambda, this is Lambda@edge, meaning lambda at edge location. So assigning triggers is done from the Cloudfront dashboard.

There are four possible points at which we can run lambda@edge:

  1. Viewer Request - when user sends a request to Cloudfront
  2. Origin Request - when Cloudfront makes a request to the origin server
  3. Origin Response - when origin server sends a response to Cloudfront
  4. Viewer Response - when Cloudfront sends a response to the user

Cloudfront request diagram

Copy your lambda’s ARN and go to Cloudfront. Select your distribution and go to Distribution Settings then Behavior and finally Create Behavior. For simplicity’s sake let’s say we want to run this on every url so enter * in Path Pattern. Scroll to the bottom and find Lambda Function Associations. Select Viewer Request event and paste in your lambda’s ARN.

Add lambda trigger to cloudfront distribution


To sum up, we have bought a domain name via a Route 53 Registrar, created a bucket and changed to static hosting with public access. Then we had to configure a Cloudfront distribution in order to achieve higher accessibility rate thanks to Amazon’s edge locations and we were also able to add an SSL Certificate to our distribution in order to provide a secure connection. Last but not least, we have Aliased the Cloudfront distribution URL to take full advantage of it under our own domain name. Then to fix the 404 error when visiting a direct url we have added a lambda@edge function to append /index.html to the url so the cdn can serve the correct file.

Doing all this through the AWS Console is repetitive and error-prone. Go ahead and checkout how to write Infrastructure as Code, setup a CI/CD Pipeline using AWS CDK and deploy your static site hosting infrastructure with a single command.