A problem every web developer has when starting with a new project is whether to use the root domain like this my-new-domain.io, or add www as a prefix and end up with www.my-new-domain.io The question looks innocent but it is critical if you plan to scale your operation, because a CNAME cannot be placed on the root domain.
If a CNAME cannot be placed on the root domain, then it is hard to use a CDN or even a cloud load balancer with the root domain.
One solution to this problem is to create an automatic redirection for HTTP traffic, so anyone coming to any url in "my-new-domain.io" will get a 301/302 response to "www.my-new-domain.io" and keep the original url path.
If you use Dyn DNS, then you probably know that enterprise Dyn customers have a redirection service. The big downside is that it does not support SSL.
If you are a Fastly CDN customer, then look here for the cookbook on edge redirections. We help our Fastly customers set up root domain serving and apex redirection.
Others had to be content with maintaining web servers and load balancers just for the sake of redirecting the apex domain. Until now.
To avoid setting up web servers just for the redirection, we leverage the power of the Cloudfront edge computing, via the newly announced Lambda@Edge functionality.
The idea is to set up a Cloudfront distribution, associate it with a Lambda function, and use a DNS that supports an ALIAS record to map the domain apex to Cloudfront. If necessary, a certificate can be provisioned on Cloudfront.
On Cloudfront, you need a new distribution. Set the origin to be a bogus IP address like 10.10.10.10, and write the apex domain in the distribution's CNAME list.
On Lambda, create a new function:
Type: Edge Node JS
Handler: index.handler
Role: Select a role with minimal permissions for Lambda execution only.
Use this code:
'use strict';
exports.handler = (event, context, callback) => {
/* set proper case for the Host header */
var raw_json=JSON.stringify(event);
var searchMask = '"host"';
var regEx = new RegExp(searchMask, "ig"); /* Case insensitive search */
var replaceMask = '"Host"';
raw_json = raw_json.replace(regEx, replaceMask);
event=JSON.parse(raw_json);
/* Extract request object. */
const request = event.Records[0].cf.request;
/* add a www prefix. */
var location = "https://www." + request.headers.Host[0] + request.uri;
/* Generate HTTP redirect response using 302 status code. */
const response = {
status: '302',
statusDescription: '302 Found',
httpVersion: request.httpVersion,
headers: {
Location: location,
},
};
callback(null, response);
};
Define the Lambda function as triggered by a viewer-request coming from the distribution you created above.
Once the distribution is fully deployed, you can test it with curl: >curl http://xyzxyzxyzxyz.cloudfront.net/something -I -H "Host: my-new-domain.io"
Thats's nearly all. The last thing is to copy the Cloudfront distribution name, and change the DNS A record to an ALIAS to the distribution. This can be done on Route53, NS1, or Dyn.
Comments
1 comment
How to do this for Route53?
Please sign in to leave a comment.