How we redirected requests in AWS Cloudfront using Lambda Edge

Amazon S3 and Amazon CloudFront are often referred to as Match Made in the Cloud. We at supportlobby use Cloudfront, S3 and EC2 combinations to deploy Static Website in AWS. Cloudfront caches your content in Edge locations to deliver your website faster.

The Problem:

We faced an issue with our pages stored in S3 private buckets and serving them through CloudFront with S3 as the origin. S3 does have the functionality to serve index.html files within folders automatically, specifically when you don’t provide. For example, if you try to access “public/site”, it can serve /public/site/index.html automatically. Natively, CloudFront does not have this functionality except for the main folder.

In our case, we would also need to do additional redirection on the pages. One solution is to handle the redirection internally inside the pages, which we do not prefer and hence, we have the following solution.

Solution: Lambda@Edge

We implemented Lambda@Edge at the Origin Request to rewrite URIs. This helped us to host static sites files in S3 and serve through CF and perform desired redirection.

What is Lamda@Edge?

Lambda@Edge is a feature of AWS Cloudfront that allows you to attach functions to your Cloudfront distributions. These functions run on the AWS edge location and as the code runs closer to your users of your application, it reduces latency and improves performance. Lambda@Edge is now limited to Node.js and has limitations compared to original Lambda.

With Lambda@Edge, you can intercept a CloudFront request at different stages. You can see those different stages in the following diagram.

Diagram showing intercepting CloudFront request at different stages with Lambda
Image Source: Amazon Lambda@Edge Documentation

We decided to intercept the Origin Request which is one of the stages of Cloudfront. Origin Request executes only when CloudFront forwards a request to our origin (S3 in our case). When the requested object is in the CloudFront cache, the function doesn’t execute. This helps us in having the function execute only once and avoids any overhead to the actual visitors, Viewer Requests.

So we will be using Lambda@Edge to achieve the following:

  • CloudFront adds index.html files where it expects to find them, when paths without index.html are requested.
  • Request gets redirected to URI with trailing slash where possible if no trailing slash is supplied.

Our Lambda@Edge is displayed below. Please configure this Lambda function in your Cloudfront cache behaviour settings:

‘use strict’;

const pointsToFile = uri => /\/[^/]+\.[^/]+$/.test(uri);

const hasTrailingSlash = uri => uri.endsWith(‘/’);

const needsTrailingSlash = uri => !pointsToFile(uri) && !hasTrailingSlash(uri);

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 and query string from the request

    const olduri = request.uri;

    const qs = request.querystring;

    // If needed, redirect to the same URI with trailing slash, keeping query string

    if (needsTrailingSlash(olduri)) {

        return callback(null, {

            body: ”,

            status: ‘302’,

            statusDescription: ‘Moved Temporarily’,

            headers: {

            location: [{

                key: ‘Location’,

                value: qs ? `${olduri}/?${qs}` : `${olduri}/`,

            }],

            }

        });

    }

    // Match any ‘/’ that occurs at the end of a URI, replace it with a default index

    const newuri = olduri.replace(/\/$/, ‘\/index.html’);

     // Replace the received URI with the URI that includes the index page

    request.uri = newuri;

    // Return to CloudFront

    return callback(null, request);

};

The above code when executed, check to see if the requested URI has an extension or not. All the requests with specific extensions will remain the same and no modifications are performed on the request. 

For all the other requests, the above code generates a new URI by adding index.html to the end of URI. CloudFront then cache further such requests until it gets invalid and continues to serve from the CF cache.

GET STARTED WITH OUR CLOUD SERVICES

What is AWS CloudFront?

Amazon CloudFront is a content delivery network operated by Amazon Web Services. They provide a globally distributed network of proxy servers that cache content, such as web videos or other bulky media, more locally to consumers, thus improving access speed for downloading the content.

What is Lambda@Edge?

What is AWS CloudFront?
Amazon CloudFront is a content delivery network operated by Amazon Web Services. They provide a globally distributed network of proxy servers that cache content, such as web videos or other bulky media, more locally to consumers, thus improving access speed for downloading the content.

How does Lambda differ from Lambda edge?

Lambda is a regional service whereas Lambda@Edge is a global service. Lambda@Edge allows one to execute the logic across multiple locations.

What is Lambda edge CloudFront?

Lambda@Edge is an extension of AWS Lambda, a compute service that lets one execute functions that customize the content that CloudFront delivers.

Vipin Venu

Technical Director at Activelobby, Cloud, DevOps & Micro-services Consultant

You may also like...

Leave a Reply