HTTP Redirects with Lambda

fkaz
TrainingDock
Published in
3 min readMar 23, 2021
301 HTTP redirect

In this article, I cover:

  • Lambda functions
  • Application Load Balancers
  • Terraform for Infrastructure-As-Code vis the AWS provider

The Problem

Sometimes you just need a redirect..

Some time ago, we had an app that users accessed using a URL that looked like https://oldapp.company.com. While that app was still actively used, we rebuilt the app and deployed the new version at https://newapp.company.com. We asked a pilot group of users to use the new app at the new URL. The pilot group beta was a great success and soon we were ready for all users to use the new app.

For marketing reasons, we eventually wanted all users to stop using the old url. But, in the initial weeks of the new app roll out, we wanted oldapp.company.com to seamlessly redirect to newapp.company.com.

The Options

So, we wanted to still expose an http(s) endpoint at https://oldapp.company.com that simply returned a 301 for a permanent http redirect to https://newapp.company.com. We also wanted some flexibility in how how the redirects were done. For example, if a user had a bookmark on http://oldapp.company.com/x/y, we wanted that to redirect to http://newapp.company.com/x/y.

As with most things, AWS gives us multiple ways to implement this:

  1. S3 static site hosting with bucket redirect configured
  2. S3 static site hosting with object level redirects configured
  3. Deploy a trivial nodejs app (containerized using ECS/Fargate) with simple redirect response for all requests. Use ALB and Route 53 to expose the endpoint.
  4. Implement a trivial lambda function. Use ALB and Route 53 to expose the endpoint.

We went with #4 because it offered the best combination of simplicity and support for the flexibility we needed. Option #1 was simple but inflexible. Option #2 was painful (i.e. create many dummy S3 object just for redirects). Option #3 was overkill, we figured.

Infrastructure-As-Code with Terraform

The Lambda

The lambda function was trivially implemented as shown here:

<root>/src/lambda/redirect.js

The terraform definition for the lambda is shown below. We use the archive_file data source from terraform to generate us a zip file that we can use for the nodejs lambda package. Next we defined the aws_lambda_function resource for the lambda specifying the attributes like function name, runtime, source package.

<root>/terraform/lambda.tf

The lambda resource above depends on an IAM role (and related policy) that we define as shown below. Basically, we are defining a new role that can be assumed by a lambda function, and we grant permissions that allow for logging to cloudwatch logs.

<root>/terraform/iam.tf

So, this defines our lambda and its IAM role. We still need to setup a trigger and invocation permissions, but we will do that as part of the Application Load Balancer definition.

Application Load Balancer

Our goal here is to define a application load balancer configured with a target group that triggers the lambda for each request. We use the aws_lb, aws_lb_target_group, and related resources to specify this. We also configure the load balancer to listen on 443 for https connections referencing an existing certificate.

Finally, we ensure that the target group has lambda:InvokeFunction permissions on the lambda we defined earlier using the aws_lambda_permission resource.

<root>/terraform/alb.tf

The final part is fairly simple. We need to configure a Route53 A record for the oldapp.company.com as an alias pointing to the public DNS name of the load balancer.

I hope you found this article helpful. Please clap on the page if you liked it. Feel free to leave a question or comment or below.

--

--

fkaz
TrainingDock

Over 20 years of experience delivering software and infrastructure systems. Usually working on something related to AWS, Scala, and DevOps.