Using a Bespoke CDN with WordPress

I have been helping a friend with his website lately and again it started to slow down, due to the massive traffic the site gets.  The last time I checked the stats Elephant Journal get’s 250,000 visitors a month with approximately 450,000 page views!  That’s quite a busy wee site.

A while back we moved some of the static files off site, and that helped massive get the site another 70,000 visitors a month – people didn’t drop out or bounce while they were waiting for the site to load.  This was real easy to do, and just meant we pointed the URL of the file to the new server.  But now the site is slowing again, and I believe it is due to the massive number of images that get downloaded.  So how do you move all these images off site and update all the URLs?  WordPress comes to the rescue…but you need to do some coding.When you log into WordPress go to Settings > Media (or Miscellaneous if you use an older version of WordPress).  Here you will see a couple of boxes indicating where the images get uploaded to and a box for the URL where the images come from.  This second box is where the magic begins.

Content Delivery Networks

There are many content delivery networks out there, all with a massive range of prices and options and configurations and what nots.  If your blog is big and you have a lot of images, you could be talking about £50-£150 a month, more if you ask for the best servers with the widest spread of load.  There are plenty of companies that do a fantastic job e.g. Amazon, VPS.net, or even the power house of CDNs, Akamai.

Note – nothing I write here will ever be better than using a professional CDN.  These guys are set up for real power and load.  You will never be told it is a mistake to spend a bit of money on say an Amazon set up as you will see massive benefits.  What am writing here is an option for those that don’t have the real money to spend.

But what if you can’t afford these guys, or just want to test out if having your images and static files off site will help?  We if you have another webserver at your disposal, or can afford say a small virtual machine from say Elastic Hosts, then you can do get all the images off WordPress real easy without moving a single file…kind of.

My Content Delivery Network

Firstly, my setup is that I have a webserver that is on very light load at the moment, so I added a subdomain to my friend’s website, and pointed it to my new server.  Using IIS7.0 I set up the website, and the following URL redirect in the website.config:

<rules>
    <rule name="All Files">
        <match url="^(.*)$" />
        <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="files.ashx?file=/{R:1}" />
    </rule>
</rules>

You will see a that all requests for images or directories that don’t exist are routed to files.ashx.  This is a small script that will then build up the location of the requested image, and save the file to the server.  It will then redirect the user back to the requested file which should now reside on the server.

The code for that looks something (or exactly) like this:

<%@ WebHandler Language="C#" %>

using System;
using System.Web;
using System.IO;
using System.Net;

public class files : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "text/plain"; 

    // file name
    string fileName = context.Request.QueryString["file"];
    if (!string.IsNullOrEmpty(fileName))
    {
       // some sort of file has been requested
       string mapped = context.Server.MapPath(fileName);
       if (!System.IO.File.Exists(mapped))
       {
              // try and download it
              try
              {
                     WebClient fileReader = new WebClient();

                     // build the directories
                     string[] dirs = fileName.Split('/');
                     string tempPath = string.Empty;
                     for (int ii = 0; ii < dirs.Length - 1; ii++)
                     {
                            string dir = dirs[ii];
                            var mappedAgain = context.Server.MapPath(tempPath + dir);
                            if (!Directory.Exists(mappedAgain)) // could someone have created the path while we creating other bits?
                            {
                                   Directory.CreateDirectory(mappedAgain);
                            }

                            tempPath += dir + "/";
                     }

                     if (!System.IO.File.Exists(mapped)) // now double check that the file was not downloaded while we were creating the path above
                            fileReader.DownloadFile("http://your.otherlocation.com/" + fileName, context.Server.MapPath(fileName));
                     else
                            context.Response.Redirect(fileName);
              }
              catch
              {
                     // most likely this is a 404 error, that we couldn't find the file on the other site.  Don't do anything, maybe
                     // even through a 404 error back to the website?  That'd be nice
                     context.Response.StatusCode = 404;
                     context.Response.Status = "404 File not found.";
              }
       }
       else
              context.Response.Redirect(fileName);
       }

       context.Response.Write("File not found."); // if you got here then the file did not exist.
       }

        public bool IsReusable {
              get {
                     return false;
              }
       }

}

Now once you have that in place, and your new subdomain has propagated throughout the internet, then you can change your settings in WordPress.

If you remember the second box where the magic begins, labelled “Full URL path to files” then in here you place the URL to the new subdomain e.g. http://files.yourdomain.com/.  Also if you have a file path within the “Store uploads in this folder” box, you must add it to http://files.yourdomain.com/, or if you have left it blank you should still add the default value to this second magic box.  So in complete the URL in the second magic box, in a default world, should be http://files.yourdomain.com/wp-content/uploads.  Now when WordPress renders your site, all images will have a path of http://files.yourdomain.com/wp-content/uploads/yourfile.name and (hopefully) the script given above, will download the file and redirect the user to the new location correctly.

But even if this doesn’t fully work for yourself, in that you don’t get the full speed increase you were hoping for, you will get an idea of how CDNs work and how much traffic your images give you.  You can then take this information and choose a professional CDN that will fit your needs.  So its a win win…?

Leave a Reply

Your email address will not be published.