Redirect 301 with AWS Lambda

Redirect 301 with AWS Lambda

Requirement

Using one of many online SEO checkers, I’ve found that one of the most prominent issue is a missing HTTP 301 redirect from www domain to the main one (https://www.marcoaguzzi.it to https://marcoaguzzi.it). Since the website is a static s3 bucket served by cloudfront, this can be achieved by using a Lambda@Edge function.

What’s a Lambda@Edge function?

In the AWS ecosystem, Lambda functions are small programs that can be invoked by a number of different callers. The Amazon motto is: “write the code and forget about the server”.

The regular lambdas can be written in some of the most common languages on the market (e.g. Java and Python) and called in any way you like, from the CLI to an event fired in some cloud obscure point.

Why @Edge?

Lambda@Edge are all of the above, but can run in Edge locations, that is, the different points where cloudfront is serving the content that has been configured as source. Those points are near the client, and therefore faster. Four different association can be made between the cloudfront distribution and the lambda function:

  • viewer request: before the cache distribution is contacted
  • viewer response: after the cache has served its output, but before reaching the client again
  • origin request: between the cache and the source (the s3 endpoint in this case)
  • origin response: between the source and the cache

The relevant case for this scenario is the first one, so viewer request. Being @Edge, there are limitations.
Quoting two among all

  • Java is not an option (10 second wait for a coldstart on a webpage is not an option, is it?)
  • Only versioned lambdas can be used, so that a snapshot of the code has been made, numbered, and cannot be modified in any way.

The code

Reference between cloudformation and the lambda

In this snipped below there’s the link between the cloudfront distribution
and the lambda@edge. (since it’s too trimmed down, I didn’t promote it to a gist)

It can be seen:

  • the viewer-request specification (so 1st case as the list above)
  • the arn of the lambda, which terminates with the “:6”, that indicates the specific version numbered #6 by AWS. That snapshot of the function won’t be modified ever. It’s also convienient if an error happens and it’s necessary to rollback to a previous version.
Cloudfront link to Lambda@Edge
1
2
3
4
5
6
7
8
9
10
CloudFrontDistribution:
Properties:
DistributionConfig:
DefaultCacheBehavior:
LambdaFunctionAssociations:
- EventType: viewer-request
LambdaFunctionARN: arn:aws:lambda:us-east-1:***:function:***-LambdaEdge-***:6
DefaultRootObject: index.html
Enabled: true
Type: AWS::CloudFront::Distribution

The actual redirect

Please see the code in the Gist below.

The nodejs code

Some hints:

  • Line 2 and 3 are used to navigate the cloudfront request that has the information needed for the redirect
  • Line 4 checks for the presence of “www.”
  • Line 9 is tricky, because the actual right form of the response that cloudfront accepts back from the lambda changed over time: location has to be an array (as for the other headers)
  • Line 11 adds also the uri part so that a www url of an internal page does not get redirected to the home page.
  • This code works with an .mjs file, in order to instruct lambda runtime to use ECMAScript

Checking the solution

Once the Cloudformation template has been deployed (it could take a while, since the update of the Lambda@Edge function will trigger the deploy of the distribution) the redirect can be seen with a simple network check with a browser.

And now SEO is happier! :-)

Author

Marco Aguzzi

Posted on

2023-12-10

Updated on

2024-11-03

Licensed under