AWS CloudFront Functions offer a lightweight and scalable way of handling URL redirects and rewrites through Javascript functions.
This post covers how to implement a simple canonical domain redirect through CloudFront functions.
What is a canonical URL?
Sometimes a webpage can be accessed via multiple URLs. There can a number of valid reasons for this, like a desktop page under https://www.example.com/page and a mobile page under https://mobile.example.com/page.
Often this is undesirable like when the WWW subdomain serves the same content as the apex domain, for example, https://example.com/page.
This can cause search engines to index pages twice, which has a few undesirable effects:
- Search engines consider it duplicate content
- No way of knowing which of the variants will be indexed
- Unnecessary crawl hits on the site
What are CloudFront Functions?
AWS CloudFront functions are code that executes on AWS CloudFront Edge locations in response to events. As they execute at the Edge, they are very fast to execute although very restricted on what they can do.
Good use cases for CloudFront Functions
- URL redirects and rewrites
- Cache and header manipulation
- Access control and authorization
Main CloudFront Functions limitations
- No network or file system access
- Very limited memory and execution time
- Very small package size
Implementing Canonical Redirects through CloudFront Functions
Here is a simple example that shows how to create a CloudFront Function that listens to viewer-request events and will redirect users from any hostname to the www.example.com variant of the page (the canonical version).
// Define which domain do we want to be the canonical one
var canonicalHost = ‘www.example.com’;
// Get the request object from the event
var request = event.request;
// Extract the host (domain) from the request object
var host = event.request.headers.host.value;
// Test if the request matches the canonical domain
if (host !== canonicalHost ) {
// Make new url
var target = 'https://' + canonicalHost + uri;
// Adds the query string if there is one
if (Object.keys(request.querystring).length > 0) {
target = target + '?';
for (var key in request.querystring) {
if (!target.endsWith('?')) { target = target + '&'; }
target = target + key + '=' + request.querystring[key].value;
}
}
// Returns a response to CloudFront
return {
// Status code of 301 for permanent redirect
statusCode: 301,
statusDescription: 'Moved Permanently',
// Location header to redirect the request to the canonical URL
headers: {
'location': { value: target }
}
};
}
Reference