Improve Your Content Delivery Using AWS Lambda@Edge | by Piotr Mol | Jun, 2022

Learn how to attach Lambda functionality to your CloudFront distribution

Photo by Safar Safarov on Unsplash

AWS Lambdas are one of the most known services in the Amazon cloud. With Lambda functions, you can create serverless API or you can react to specific events in your system as messages are pushed to queues or items are updated in the DynamoDB table.

But there is one application of the Lambda functions that is less known. Moreover, this solution has its own name and is called the Lambda@Edge. The Lambda@Edge is a feature of Amazon CloudFront that lets you run code closer to users of your application, which improves performance and reduces latency.

In this article, I’m describing a few use cases where the Lambda@Edge is useful. I will also show you how to create one Lambda@Edge function. So, as usual, grab your cup of coffee, sit comfortably, and follow me along :).

To fully understand what the Lambda@Edge can offer us, we have to step back and describe what it is the CloudFront.

“Amazon CloudFront is a web service that speeds up distribution of your static and dynamic web content, such as .html, .css, .js, and image files, to your users. CloudFront delivers your content through a worldwide network of data centers called edge locations. When a user requests content that you’re serving with CloudFront, the request is routed to the edge location that provides the lowest latency. “

The CloudFront is an ordinary CDN (content delivery network). It helps us to serve content with a better user experience. In a basic use case, we could have the static page in the s3 bucket and the CloudFront distribution set to serve this page.

CloudFront + S3 setup

Great, now we know what the CloudFront is. So, where in this content delivery network is the place for the Lambda function, and what can I do with them?

The Lambda@Edge is a function attached to the request or response in CloudFront and may be triggered in four cases:

  • on viewer request (After the CF receives a request from the end user)
  • on origin request (Before the CF propagates the request to the origin, e.g. s3 bucket)
  • on origin response (After the response from origin to CF)
  • on viewer response (Before CF sends a response to the end user)

That all sounds interesting, but I still don’t see any benefits of these functions, you may say. There are plenty of benefits and applications. I will share them right now.

The first application of the Lambda@Edge may be the A/B testing. The idea is simple. There will be two s3 buckets hosting a static page. Lambda’s code will randomly redirect users to a specific frontend version. Then, we will assign a cookie to each request, just to make sure that the same user will see the same version of the page each time.

Secondly, we could use the Lambda@Edge for dynamic content generation. We could resize images based on the request attributes, or we could render pages based on some logic-less templates, e.g. Mustache.

Another Lambda@Edge use case is URL manipulation. We can prettify them, or we can map the URL to match the origin directory structure. The CloudFront and s3 are designed to support one static page per one s3 bucket. If needed, we can get around it. We can deploy multiple pages to s3 and connect them with one CloudFront distribution, but then, we need the Lambda@Edge.

Finally, we could use the Lambda@Edge to increase our app security. We can assign a request to custom origins that enforces access control. We can filter up the bots from users, or we can create a viewer authenticator directly in the Lambda@Edge code.

Great. Now, when we get to know some use cases, we are ready to see examples of how to create the Lambda@Edge. I have prepared the CloudFront distribution and s3 bucket already. There is a static page inside the s3 bucket.

1*4rTzp0TEtf1jxt4 tuZO8Q
Test website deployed to s3 and CloudFront

Let’s imagine that the “The Dog’s World” should be secret. The world mustn’t know about our secret memes. We’d like to protect our treasures. To do so, we will add the Lambda@Edge, and we will protect the access by adding the basic auth. Yes, I know that the basic auth it’s not the best protection, but we are learning how to add Lambda@Edge not how to set up advanced authorization.

Before we start, one disclaimer. You can create CloudFront functions only in the us-east-1 region, and you have to use the node or python as Lambda runtime. There is no support for other languages now.

To create Lambda@Edge, go to the AWS console, search for Lambda functions and click create function. Inside the create function form, pick Use a blueprint option and then search for a CloudFront. There, you should find three templates. In fact, it doesn’t matter which one you pick. We will change the code. We are using templates to make sure we will have an appropriate IAM role created for the Lambda@Edge.

Create Lambda@Edge using a blueprint

When you click configure, then you have to set the name of the function as well as the name of the IAM role that will be created.

1*DmnM AS
Basic Lambda information

At the bottom of the page, you will see the Lambda function code. It’s a code from the template we are using. Don’t bother. We will delete it in a minute and set our own. Please, click create function.

Confirm Lambda creation

After clicking the create function button, you will be redirected to the Lambda console. You will also see the popup asking you to set the CloudFront trigger. Please, click cancel. We don’t have the right code yet. Then scroll down a little, to code source. Now, delete the Lambda code and replace it with the following one:

The code is pretty straightforward. Here I search for the authorization header and I compare that header with the expected one. The user and password are hardcoded in code. I know. I know. That’s bad. But it’s only an example of how to create Lambda, not how to authenticate with secrets :).

Finally, if the auth header doesn’t match the required one, I’m using the Lambda@Edge callback to reject the request and ask the user about a password.

Cool, having that code set, please click deploy button. Now, the code will be deployed, but it’s not connected to CloudFront yet. To do so, let’s click the add trigger button.

Changing the lambda code and adding the trigger

Then, we have to pick the CloudFront service:

1*Q U0Ih9AMUI6BEs 5drBFw
Picking CloudFront from list of services

Finally, we can pick the CloudFront Distribution we want to extend. In the form, leave the Cache behavior setting as it is, but please change the CloudFront event to Viewer request. We would like to trigger the function when the final user hits the endpoint. We also have to confirm we want to deploy the function to the Lambda@Edge.

Lambda@Edge trigger settings

This will take a while to set the trigger. You will be redirected to the lambda console, and you will see information like this one:

Successfully deployed Lambda@Edge info

As you can see, the AWS created a new version of the function. That’s another of limitation of Lambda@Edge — we cannot use the $latest tag. It has to be versioned.

After waiting a few minutes, we can check if lambda works. When entering the CloudFront URL, depending on the browser and the language you use. You should see a similar result to mine. If the page is blocked, you have to log in first. That’s what we wanted to do. Good job!

1*BF I2TUz6JX6B ZBb4bYOw
Blocked public access to CloudFront page

In today’s tutorial, we went through basic use cases of the Lambda@Edge. I also showed you how to create one. Now, you can easily integrate the Lambda@Edge into your application. No matter if you have the same use case or another. Adding Lambda@Edge to CloudFront distribution is always the same.

Happy coding, and see you next time!

News Credit

%d bloggers like this: