404 Pages in Coldfusion
First off, let me define what exactly a 404 page is. An HTTP 404 error message is a standard response code indicating that the client was able to communciate with the server but the server could not find the page requested. In Coldfusion, by default, the server (IIS) doesn't check that .cfm files exist but rather lets Coldfusion handle that. The result is one of those ugly blue and grey error screens that aren't picked up by the normal 404 methods or by our Application.cfm's error handler.
So, how do we handle this? There are currently two ways. First, you can change the IIS settings to force it to review if a .cfm file exists before handing it off to Coldfusion or you can change the settings in Coldfusion Administrator to include a certain page when a .cfm file is not found. I used the CF Administrator method, but you can find out more information about the IIS method here.
The first step if we are going to follow in either method is to create the Custom Error page that your user will see. There is a lot that can go into this depending on your site. In my case, we wanted to keep it very simple, so we just displayed a message saying simply there was an error and we record their referrer so we can figure out who is linking to the non-existant pages. For sites that are very consumer based though, you might want to include a search box or something to make them feel like they are not the ones at fault and attempt to keep them on your site. Sitepoint has a page with some good tips for a 404 page and it lists some interesting 404 page layouts.
For my 404 page, we mostly wanted to grab information about how the user got there (page name, query string, referer, etc) so we can fix any broken links or taken action if needed:
<head>
<style>
body { FONT-SIZE: 11px; LINE-HEIGHT: 135%; FONT-STYLE: normal; FONT-FAMILY: Tahoma,Verdana,Helvetica; }
</style>
</head>
<body>
There was an error loading your requested page. <br /><br />
HTTP 404 - Page Not Found.
</body>
</html>
<cfif Find( "404;", CGI.query_string )>
<!--- This accommodates how the URL is passed in when using the IIS method --->
<cfset target_url = REReplace( CGI.query_string, "404;|:#cgi.server_port#|#cgi.server_name#|http://|https://", "", "ALL" ) >
<cfset page_requested = ListFirst(target_url,'?') >
<cfset page_requested_qs = ListLast(target_url,'?') >
<cfelse>
<cfset page_requested = cgi.script_name >
<cfset page_requested_qs = cgi.query_string >
</cfif>
<cfset request_referrer = cgi.http_referer >
<cfset request_ip_address = cgi.remote_addr >
<cfset request_method = cgi.request_method >
<cfquery datasource="database_name">
INSERT INTO page_errors
( page_requested, page_requested_qs, request_server, request_referrer, request_ip_address, request_method, request_datetime, request_http_response_code )
VALUES (
<cfqueryparam value="#page_requested#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#page_requested_qs#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#cgi.server_name#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#request_referrer#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#request_ip_address#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#request_method#" cfsqltype="cf_sql_varchar">,
getDate(), '404'
)
</cfquery>
In order to change the Coldfusion Administrator settings, go to: CFAdministrator > Server Settings > Settings > "Missing Template Handler". In that field, enter the path name to the file, relative to the home directory, that you want to run whenever a .cfm file is not found. When I tested this on CF8, if a template is included (with cfinclude) and doesn't exist, it throws a normal error. If you navigate directly to a page that doesn't exist, then the Missing Template Handler is executed.
Note that if you were to use this Error page in the IIS method, it would record every single missing file hit, this includes images - so, if you used empty images as spacers or to track emails, they will trigger this every time.

