Posted June 29, 2006 at
8:50 AM
Tags:
ColdFusion
Handling 404 errors can be tricky no matter what. On your live, production server, you can set up custom 404 handling on a site-by-site basis via IIS custom error templates. However, for many of us, this is trickier on the development server where there are no site. Its just one web server with many sub directories, none of which are usually virtual sites.
To remedy this situation, I have developed a 404 error handler that is defined at the root of the developmental web server. This 404 error handler catches 404 errors and attempts to forward the errors to individual "site" error handlers in an attempt to mimic 404 error handling on a live site. This setup makes a few assumptions:
- Your 404 errors are handled by a ColdFusion template named "cferror.cfm"
- Your cferror.cfm template is located either in the root of the site (a sub directory on the development server) or at least that it is in the same directory or a parent directory of the requested non-existent page.
The system works by catching the 404 error at the root of the ColdFusion web server. It then takes the requested page and starts crawling up the directories url. For each directory, it check for the existence of the cferror.cfm template. If it is found, the root 404 error handler performs a CFLocation to that cferror.cfm template, sending, as the query string, the same "404;" query string that IIS has defined.
As the system crawls up the directory path, after checking for cferror.cfm, it checks for either an Application.cfm or Application.cfc file. If it hits one of these files, it stops crawling and displays its own Page Not Found message. The idea here is that we don't want to leave the context of the application when search for a 404 error handler.
I have prevented infinite loops (the root 404 error handler constantly CFLocating to itself) by stopping the search once there is no more directory to crawl (signaling that we are in the root directory). I have not tested this, but I assume this means that if the development server's cferror.cfm template is NOT IN THE ROOT of the web server, the infinite looping IS possible.
A word of caution: This template is done to help develop 404 error handling by simulating 404 error handling on the live, production server. It DOES NOT MIMIC live 404 error handling. On the live server, IIS will pass control directly to your site's 404 error handler without doing any URL location changes. Therefore, from your BROWSER's PERSPECTIVE, on the live server, your missing page URL may be in a different directory as your 404 error handler. On the development server, however, the missing page URL is ALWAYS in the same directory as the 404 error handler.
For example, let's say you request a non-existent page "ben-nadel/is/cool.htm" on the live server.
Browser sees:
ben-nadel/is/cool.htm
ColdFusion sees:
cferror.cfm
The web browser is TWO directories down in the site structure. The relative paths would start with "../../".
If you do the same thing on the development server:
Browser sees:
cferror.cfm?404;http://..../ben-nadel/is/cool.htm
ColdFusion sees:
cferror.cfm
Both the web browser and the 404 error handler are in the SAME directory (due to the root 404 error handler's CFLocation). The relative paths would be empty since there is no sub-folder URL.
The cferror.cfm template as it exists in the root of my development server:
Launch code in new window » Download code as text file »
- <!---
- Set a short timeout since this page should not
- hog any resources.
- --->
- <cfsetting requesttimeout="5" />
- <!--- Get the query string. --->
- <cfset strQueryString = CGI.query_string />
- <!--- Check to make sure that we have a 404 error. --->
- <cfif Find( "404;", strQueryString )>
- <!--- Strip out server name. --->
- <cfset strDirectoryPath = ReplaceNoCase( strQueryString, CGI.server_name, "", "ONE" ) />
- <!--- Strip out 404 and protocols. --->
- <cfset strDirectoryPath = REReplaceNoCase( strDirectoryPath, "(404;)|[a-z]{2,5}://", "", "ALL" ) />
- <!--- Remove any query strings. --->
- <cfset strDirectoryPath = REReplace( strDirectoryPath, "(\?.*)$", "", "ONE" ) />
- <!---
- If there is a file being used, get the directory
- from teh path.
- --->
- <cfif REFind( "\.[\w]*$", strDirectoryPath )>
- <!--- Remove the file name. --->
- <cfset strDirectoryPath = GetDirectoryFromPath( strDirectoryPath ) />
- </cfif>
- <!---
- Set the initial current directory value that will
- be check during the loop.
- --->
- <cfset strCurrentDirectory = strDirectoryPath />
- <!---
- Loop over the directory path while we still have
- directories and look for the cferror.cfm.
- --->
- <cfloop condition="true">
- <!--- Get the directory from the path. --->
- <cfset strCurrentDirectory = GetDirectoryFromPath( strCurrentDirectory ) />
- <!---
- Check to see if we need to break. We don't
- want to find THIS cferror.cfm page as that
- will just cause a crazy infinite loop. At this
- point, just let the page finish to show the
- page not found error.
- --->
- <cfif (Len( strCurrentDirectory ) LTE 1)>
- <cfbreak />
- </cfif>
- <!--- Check to see if the cferror.cfm file exists. --->
- <cfif FileExists( ExpandPath( strCurrentDirectory & "cferror.cfm" ) )>
- <!---
- We found an error template, so relocate to
- that template. To make sure our paths are not
- crazy, lets cflocation to it and use the same
- query string that we got.
- CAUTION: This is not how the LIVE server will
- handle this action. This is designed for local
- error handling on the developmental serer.
- --->
- <cflocation url="#strCurrentDirectory#cferror.cfm?#CGI.query_string#" addtoken="no" />
- <cfbreak />
- <!--- Check to see if we can find an application file. --->
- <cfelseif (
- FileExists( ExpandPath( strCurrentDirectory & "Application.cfm" ) ) OR
- FileExists( ExpandPath( strCurrentDirectory & "Application.cfc" ) )
- )>
- <!---
- We didn't find a cferror.cfm page, but we did
- hit the root of an application, so break out
- of this loop. We don't want to crawl up the
- directory any more than we have too. If this
- application doesn't catch errors then just stop.
- --->
- <cfbreak />
- <cfelse>
- <!---
- We didn't find the file or hit any application
- roots, so remove the right most slash for next
- loop. We do this otherwise the
- GetDirectoryFromPath() will not be able to keep
- moving up path.
- --->
- <cfset strCurrentDirectory = REReplace( strCurrentDirectory, "[\\/]{1}$", "", "ALL" ) />
- </cfif>
- </cfloop>
- </cfif>
- <!---
- If we are still here, then we didn't find a directory
- containing a cferror.cfm. Dump out some info to help
- the user debug.
- --->
- <h2>
- 404 Page Not Found
- </h2>
- <p>
- <cfset WriteOutput( CGI.query_string ) />
- </p>
- <cfdump var="#CGI#" />
Download Code Snippet ZIP File
Comments (0) |
Post Comment |
Ask Ben |
Permalink |
Other Searches |
Print Page
What Other People Are Searching For
[ local search ]
coldfusion 404 error page
[ local search ]
catching 404 errors with coldfusion
[ local search ]
coldfusion handling page not found
[ local search ]
coldfusion custom 404
[ local search ]
coldfusion file not found page 404
[ local search ]
coldfusion custom file not found
[ local search ]
404 in cgi query_string
[ local search ]
coldfusion setup 404
[ local search ]
set coldfusion 404 page
[ local search ]
coldfusion iis 404
[ local search ]
coldfusion handle 404
[ local search ]
cgi coldfusion 404
There are no comments posted for this web log entry.
Post Comment |
Ask Ben