Skip to main content

This is the ORIGINAL post. 

AWS CloudFront has been around for over 15 years and packs a lot of features for delivering content quickly and efficiently. It’s great for low-latency and high-speed transfers.

However, if you really want to get the most out of CloudFront, pairing it with AWS Lambda@Edge can take things to the next level and unlock even more cool capabilities.

Before we move on, we need to understand different types of requests from the end user to the origin server. See below diagram:

In the following part of the article, I will use Lambda@Edge to solve a real-world problem.

The Context

Our application frontend is hosted on AWS S3 and we build a serverless backend with API gateway and Lambda Functions.

Previously, we used the URL generated by API gateway to access the APIs which introduced us CORS (Cross-Origin Resource Sharing) issue even if we used custom domain for the API setup.

We know it can be sorted with the correct CORS settings. Still, to make the setup more standardized and easily managed, we decided to use the same CloudFront distribution to be integrated with the API gateway.

What we want to achieve is to send all requests with the path /api/* to the API Gateway origin, and send the rest of the requests to the S3 bucket origin.

The Problem

Now we had a problem.

All the requests going to API gateway start with /api/ in the URI path but for our API Gateway setting, we don’t need that because the format of the URI path received by API gateway should just be /{stageName}/{resourceName} .

With the existing native features of CloudFront, I could not really solve the problem, then I decided to use Lambda@Edge function to modify the request URI path for origin requests to API Gateway.

How To

– We need to have a lambda function

The function runtime I chose is Python 3.12 but you can choose others.

Here comes the code I use.

def lambda_handler(event, context):

request = event['Records'][0]['cf']['request']

uri = request.get('uri', '')

if uri.startswith('/api/'):
request['uri'] = uri.replace('/api/', '/', 1)

return request

This function is used to rewrite the URIs of incoming requests, effectively removing the /api/ prefix.

I believe you need to refer to this document before any development work.

– We need to update the trust policy for your lambda function

As the lambda function is deployed to the edge so the trust policy has to be updated.

You need to add edgelambda.amazonaws.com as one of the services in the statement shown as below:

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

– We need to publish the lambda function and deploy it to CloudFront with version ID

There are multiple ways to deploy. I suggest to use IaC to deploy everything related as it went pretty well while I used Terraform.

However, if you want to do manual work from AWS console, you will face a problem with the above method (Deploy via Lambda Function console).

See this screenshot above, I got the error: Cannot read properties of undefined (reading 'startsWith')

If you see the code I use, it does not matter with the function ‘startsWith’.

Obviously, someone met the same issue and it seemed like it had not been resolved by AWS yet. If you know what the problem is, please leave your comment.

However, there is always a way to do it.

First, we need to publish a new version for the Lambda function as we need the function arn with version ID.

Then go to the CloudFront distribution and update the /api/* path pattern under Behaviors tab. Scroll down to the bottom and associate the function arn with version ID to Origin request as below. Save the changes and the deployment will start.

Conclusion

To wrap it up, CloudFront paired with Lambda@Edge is a game-changer for handling tricky integration issues like modifying API paths. With a bit of custom code, you can tackle problems that CloudFront alone can’t handle.

So, don’t be afraid to get creative and make the most of these tools to streamline your setup!

I wrote this article and I hope this provides valuable guidance to others who may encounter similar issues in the future.

Finally

Please follow me on Medium if you are interested in Cloud, DevOps, automation, programming, and any tech topics. I would also appreciate it if you could give me a clap.

Your comments are always welcome.

Thanks.

Leave a Reply