HTTP Redirects with Cloudfront & S3

Posted on Tue 18 August 2015 in aws

Redirects can account for a significant share of direct traffic so taking a few minutes to optimize them is worthwhile.

Using Cloudfront & S3 for redirects will improve responsiveness, reduce server load and improve management (since they are managed via aws-cli or the console).

Let's say you have a typical .htaccess redirect like this.

RewriteEngine On
### re-direct to www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Or worse, it could look like this in your index.php

$protocol = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";

if (substr($_SERVER['HTTP_HOST'], 0, 4) !== 'www.') {
    header('Location: '.$protocol.'www.'.$_SERVER['HTTP_HOST'].'/'.$_SERVER['REQUEST_URI']);
    exit;
}

Instead, let's use Cloudfront to host these redirects as close to the user as possible.

First you'll need an S3 bucket with the website configuration activated like this:

$ aws s3api get-bucket-website --bucket mysite.com
{
    "RedirectAllRequestsTo": {
        "HostName": "www.mysite.com",
        "Protocol": "http"
    }
}

Second, you'll need a cloudfront distribution using this site as the origin:

$ aws cloudfront get-distribution --id=E32XXXXXXXXX |jq .Distribution.DistributionConfig.Origins
{
 "Items": [
     {
         "OriginPath": "",
         "CustomOriginConfig": {
             "OriginProtocolPolicy": "http-only",
             "HTTPPort": 80,
             "HTTPSPort": 443
         },
         "Id": "S3-website-mysite.com",
         "DomainName": "mysite.com.s3-website-us-east-1.amazonaws.com"
     }
 ],
 "Quantity": 1
}

Finally, re-assign the DNS to point to the cloudfront Distribution .

$ aws route53 list-resource-record-sets --hosted-zone-id=XXXXXXXXX |jq '.ResourceRecordSets[0]'
{
  "AliasTarget": {
    "HostedZoneId": "XXXXXXXXX",
    "EvaluateTargetHealth": false,
    "DNSName": "dxxxxxxxxx.cloudfront.net."
  },
  "Type": "A",
  "Name": "mysite.com."
}

Now you can test the performance

curl -w @curl-timing.txt -Is http://mysite.com|egrep 'Location|time'
Location: https://www.mysite.com/
            time_namelookup:  0.005
               time_connect:  0.046
            time_appconnect:  0.000
           time_pretransfer:  0.046
              time_redirect:  0.000
         time_starttransfer:  0.092
                 time_total:  0.092