john chesley

fresh stuff

destinations

favorites

smart 404

default server error pages do a decent job of letting whoever receives it know that what they expected to see doesn't exist. they're usually completely useless. but, using some fairly simple logic you can give your visitor a more helpful message

what causes 404 errors?

a 404 error means that the page requested doesn't exist. there are 3 things that can cause this to happen:

  1. the visitor typed the address in and misspelled it, or used an outdated bookmark
  2. there's a bad link on your own site that points to a page that doesn't exist
  3. there's a bad link out there on the web, another misspelling by someone trying to link to you, or perhaps you moved things and broke old links (don't do that, eh)

how we can handle these

using a couple of server variables it's possible to detect which of these three caused the error. we'll use the HTTP_REFERER header, sent to the site from the visitor's browser, to find out where they came from, combined with the SERVER_NAME variable to figure it all out:

where do these variables come from?

depending on what server setup you're on, you access these variables in different ways. in PHP you'll access the $_SERVER automatic variable like so:


$server_name = $_SERVER['SERVER_NAME'];

$referer = $_SERVER['HTTP_REFERER'];

then you can carry out some simple comparisons to figure out exactly what happened:


if (preg_match("/http:\/\/".$server_name."/", $referer) ...

display a different message, depending on which conditions match, and there you have it, a more helpful error page!

not using php?

me neither. django apparently supports custom 404 error pages, but translating the basic idea from my original php implementation seemed easier. plus that way i could use the exact same, simple template i use for every other page on my site to display it.

getting the variables into a Context object was easy enough. they're stored in the request.META dictionary, so passing that to a 404 mini-template and using django's template syntax (plus a custom tag for the regex processing) gave me back the content I wanted to put into my normal default template, complete with the correct "error message". beauty! :)