Lambda routing fix for Cloudfront

Lambda routing fix for Cloudfront

Fix Cloudfront's lack of index subfolder routing with Lambda. ...

This post will be about a Lambda routing fix for Cloudfront, which is caused by the way that Cloudfront deals with routes for sub folders.

Unlike S3, Cloudfront does not allow the index file within a subfolder to be automatically displayed, this is behaviour that needs to be programmed with a Lambda function.

Step 1

Lambda routing fix for Cloudfront
Create a cloudfront CDN that is linked to a publically accessible S3 bucket (set to website hosting) that you’d like to fix routing on and create a lambda function in N. Virginia with the below code.

Step 2

Lambda routing fix for Cloudfront
Attach the lambda@edge access policy (see code below) to that lambda function, then click the ‘Deploy to Lambda@Edge’ using the actions button and ensure it is attached to the right CDN with the options ‘Origin Request’ selected.

Step 3

Lambda routing fix for Cloudfront
Once the Lambda function has propagated, routing to index objects within a folder should return the content of the index.html file.

I’ve posted the Lambda function below (with comments) so you can use this Lambda routing fix for Cloudfront! I’ve also written a similar post to this on how to trigger a code pipeline to deploy to an S3 bucket via a lambda function, that you may find helpful! Enjoy 🙂

Lambda function

'use strict';
exports.handler = (event, context, callback) => {

    // Extract the request from the CloudFront event that is sent to Lambda@Edge 
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Replace the received URI with the URI that includes the index page
    request.uri = updateUri(olduri);

    // Return to CloudFront
    return callback(null, request);

};

function updateUri(olduri) {
    // if url ends with file name all it to pass through to site
    if (olduri.match(/\.[0-9a-z]+$/i)) {
        return olduri;
    }
    // else (if it ends with "/" folder path) then add "/index.html"
    else if (olduri.endsWith('/')) {
        return `${olduri}index.html`;
    }
    // else return the previous url with "/index.html ad"
    return `${olduri}/index.html`;
}

Lambda permission role’s trust relationship

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "edgelambda.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Share this post