Use AWS CloudFront Functions for URI Rewrites
Tags: aws, cloudfront, functions, javascript
Published: 2021-05-06 19:27:21

---
title: Use AWS CloudFront Functions for URI Rewrites
published: true
description: Deploy JavaScript at AWS CloudFront edge to implement URI Rewrites and Redirects.
tags: aws, cloudfront, functions, javascript
cover_image: https://cdn.hashnode.com/res/hashnode/image/upload/v1620328024177/CBq1YF4jE.jpeg
canonical_url: https://rosswickman.com/archive/use-aws-cloudfront-functions-for-uri-rewrites
---

With just over one week to move a customer application from one data center into our managed service environment, I was provided with a new (to me) requirement. The requirement was to configure URI redirects for their web application. This didn't seem like a huge concern at the immediate request. I figured I'd just put a couple of listener rules on the Application Load Balancer (ALB) and call it good doing what all DevOps engineers do...

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1620326441535/m6WTB2j1T.png)

That was before I received the spreadsheet with almost 60 (known) redirects. More potentially to come.

## What to do?

I didn't want to make an already complicated solution more complicated.

I knew I had limits to the number of rules allowed in Load Balancer Listeners.

I wasn't interested in adding or modifying any Lambda@Edge functions managing my Content Security Policies.

Fortunately for me, right at the time of receiving this new requirement, AWS Announced CloudFront Functions.

## What is/are CloudFront Functions?

...a new serverless edge compute capability. You can use this new CloudFront feature to run JavaScript functions across 225+ CloudFront edge locations in 90 cities across 47 countries.... ( [read the full announcement here](https://aws.amazon.com/about-aws/whats-new/2021/05/cloudfront-functions/) ).

## How could CloudFront Functions help me?

Aside from the rule limits imposed on me by ALB Listeners such as:

- 100 total rules per ALB
- 5 conditions per rule
- 5 wildcards per rule
- 5 weighted target groups per rule

I would have had to use wildcards to make some of the rewrites work. You can use your imagination and the following example to see how this may not produce a favorable outcome.

### Use case example

Imagine a website like  [AllRecipies](https://www.allrecipes.com/)  wanting to redirect certain recipes to new or improved names.

Consider *Homemade Mac and Cheese* served here:
https://www.allrecipes.com/recipe/11679/homemade-mac-and-cheese/

Let's say for example sake the `11679` in that URI is a catalog of recipes. AllRecipies may want to redirect anything that isn't a successful hit to a different catalog of recipes. So they use a wildcard like:
https://www.allrecipes.com/recipe/11679/* to push all requests to https://www.allrecipies.com/summer21/

What happens is now https://www.allrecipes.com/recipe/11679/homemade-MOUSE-and-cheese/ successfully redirects with a `200` response instead of going to a `404` Page Not Found. 

*NOTE:* oddly enough, AllRecipes is actually doing some magic to forward that URL to the correct recipe.

## Using CloudFront Functions for URI Rewrites

Being under the gun to come up with a solution, I immediately took a stab at CloudFront Functions. I'm honestly not sure how I got  [this](https://gist.github.com/rosswickman/f60d3dc9eb2459fe74a0d6c7c376882c) to work after the first attempt, so I'm interested in getting anyone's feedback on this implementation.

To accommodate an unknown amount of future requests for rewrites, I tweaked and implemented the example provided in the [CloudFront Functions Introduction Blog](https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/).

### My implementation

```
function handler(event) {
  var request = event.request;
  var rewrites = [
    ['/summer21','/recipies?year=2021&season=summer'],
    ['/recipies/homemade-mouse-and-cheese/', '/recipies/homemade-mac-and-cheese/'],
    ['/recipies/camping/grilling', '/recipies?activities=camping&with=grill']
  ]

  for (var arrayIndex in rewrites){
    if (request.uri == rewrites[arrayIndex][0]) {
      var newUri = rewrites[arrayIndex][1];

      var response = {
        statusCode: 301,
        statusDescription: 'Permanently moved',
        headers: {
          "location": { "value": newUri }
        }
      }
      return response;
    }
  }
  return request;
}
``` 

## Making the solution more robust

This CloudFront Function appears to be working as expected. This example allows you to redirect any URI pattern and forward it to a new path or include a search query for client or server-side functionality. All while using JavaScript at the Edge. Without a doubt, this could be modified to further accommodate query strings in the request.

I typically like to deploy my solutions via CloudFormation specifically because this is for a customer; however, at the time of this post and the function implementation, the CloudFormation Team has not released an update to the User Guide for creating this as a managed resource in CloudFormation. I am told it should be released soon. Once I have the information, I will try to get back here and provide a CloudFormation Template in an update.

Until then, if you are looking to try this out or implement CloudFront Functions in your own environment, I encourage you to checkout  [this blog](https://dev.to/aws-builders/aws-cloud-front-functions-471c) post by a fellow AWS Community Builder. 

Please do not hesitate to comment below how you decide to implement CloudFront Functions, this specific function, or better yet how I can make this specific function even better.