Use AWS CloudFront Functions for URI Rewrites

rosswickman

Ross Wickman

Posted on May 6, 2021

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

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 ).

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 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 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.

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;
}
Enter fullscreen mode Exit fullscreen mode

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 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.

💖 💪 🙅 🚩
rosswickman
Ross Wickman

Posted on May 6, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related