John D Wells

A Freelance Web Architect

Adept at all modern web standard technologies. Deadly with an open source sword, especially Wordpress.

Proud to work with some of the finest designers in London. And some incredible clients, too.

Lead developer for Fresh & Mean. Fancy a pint?

This tumblelog is further embellished by my Flickr, Twitter, and Digg accounts.

02 Feb 08

503 Status - Website Temporarily Down

In the past week or so, I’ve had to implement a “503 Status” a number of times on different websites, for different reasons. Every web request includes a “status”: 200 means “OK”; 404 means “Not Found”; 500 means “Internal Server Error”; and 503 means “Temporarily Unavailable”. The advantage of a 503, as opposed to a 404 or worse 500, is that search engine robots take notice and can be instructed to “come back later”, as opposed to, at worst, never coming back again. It’s also handy because you can customize the look and feel of this message, calming any visitors that were hoping to find your site alive and well.

To learn how to properly implement a 503 status during a site upgrade, I found this tutorial to be all I needed to know. However my resulting .htaccess file differed ever so slightly, so I thought I’d share.

Folder Structure

First, let’s list the files involved. I’m running my sites on Apache, so I’m using an .htaccess file to help out. Because this is a 503 redirect, it helps to name the ‘holding page’ 503.php. And since it’s a “pretty” holding page, we need a place to hold CSS and images. Let’s put those into a /503 folder. This is how it looks:

/  
    /503.htaccess  
    /503.php  
    /503  
        /css  
        /images  

503.htaccess Setup

OK, now let’s talk about how we want the 503 to work. Because I’m working on an upgrade, I need to let myself bypass the 503. That means excluding my IP address from the rewrite rules. For everyone else, I redirect to 503.php, BUT, I also need to make sure that page, as well as the contents of the 503 folder, are allowed to be viewed. If we didn’t do this, the server would enter an endless loop and cough up a 500 Internal Server Error. Bad.

Right, so 503.htaccess looks like:

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1
        RewriteCond %{REQUEST_URI} !^/503/ [NC]
        RewriteCond %{REQUEST_URI} !^/503.php [NC]
        RewriteRule .* /503.php [L]
    </IfModule>

Our first RewriteCond tests for our IP. I’ve placed a local IP in there, but of course you’ll want to add your real IP. If you aren’t sure what this is, simply visit whatismyipaddress.com. You can also repeat this line as many times as you want, to allow others through as well.

Our second conditional tests to see if any of the 503/ folder’s contents are being requested. Similarly, the third conditional tests to see if our 503.php file is being requested.

To be clear, because of the way the conditionals are written, we’re sort of filtering by negatives. What we’re really saying is this:

  1. If the requesting IP is NOT the value specified, continue to the next line; if it IS, skip all other conditionals, and the RewriteRule.
  2. If the requesting url does NOT include the /503 folder, continue to the next line; if it DOES, skip all remaining conditionals, as well as the RewriteRule.
  3. If the requesting url is NOT 503.php, continue to the next line and fire off the RewriteRule; if it IS, skip the RewriteRule.

503.php Setup

We’re nearly done! Now all we need to do is use a few lines of PHP to send the proper 503 headers (up to now we’ve only done a redirect). That means our first 5 lines of 503.php should look like this:

<?php
        header("HTTP/1.1 503 Service Temporarily Unavailable");
        header("Status: 503 Service Temporarily Unavailable");
        header("Retry-After: 3600");
    ?>

It’s important that these lines are at the beginning, because you cannot send content before headers. The 4th line, “Retry-After: 3600” is a measurement in seconds as to how long you expect the site to be down. This will tell any spiders to “come back in an hour”. How polite!

Turning It On

Now we have everything set up, but currently the 503 switch hasn’t been flipped. But doing so is a breeze: simply rename 503.htaccess to .htaccess. OR, better yet, assuming you normally use an .htaccess file (if, for example, you run Wordpress with pretty URLs), follow these steps:

  1. Duplicate .htaccess, and rename it to 200.htaccess
  2. Open 503.htaccess, and copy its contents to your clipboard
  3. Close 503.htaccess, and open .htaccess
  4. Paste the contents from 503.htaccess into .htaccess; Save

Now, you’re in business. And best of all, turning 503 off is just as simple: copy the contents of 200.htaccess, and paste it into .htaccess.

Final Note

If you do use .htaccess for Wordpress or similar, and need to run a 503 but also let yourself through as above, you’ll need your 200.htaccess redirect rules below your 503 rules in 503.htaccess. Sorry if that’s confusing. Let’s just see that as an example:

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1
        RewriteCond %{REQUEST_URI} !^/503/ [NC]
        RewriteCond %{REQUEST_URI} !^/503.php [NC]
        RewriteRule .* /503.php [L]

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.php [L]
    </IfModule>

So the begining of our mod_rewrite rules is for all things 503; if we get through those, it is then on to the basic Wordpress rewrite rules. Done and done.

Comments (View)