Closing The 404 Gap For Dynamic Page Generation With onMissingTemplate()

The Problem That This Introduces

This is all well and good, but sadly, doesn't work if the user or link doesn't specify index.cfm or another .cfm template inside our faux directory, and instead just stops with the folder name like so: myclient.com/foo/. In this case, ColdFusion is never given the opportunity to handle the request, and instead the web server software -- in my case, IIS -- does. What we need to do is find a way to have IIS hand the request off to CF for handling

My Solution For The New Problem

This is easily accomplished with custom error pages. (The same can be done for Apache and any other server software worth its salt.)

Since the folder the user is requesting (/foo) doesn't actually exist, IIS throws a 404 error. However, if it did exist, it would be the default document that was displayed: index.cfm. So the first thing we need to do is create a script that will take the requested URL and append "index.cfm" to it, so that CF can process the request.

<cfset requestedURI = listGetAt(cgi.query_string, 2, ";") />
<!--- strip port --->
<cfset requestedURI = Replace(variables.requestedURI, ":80", "", "ALL") />
<!--- if just asking for folder's default doc, append index.cfm --->
<cfif right(variables.requestedURI, 1) is "/">
<cfset requestedURI = variables.requestedURI & "index.cfm" />
<cflocation url="#variables.requestedURI#" addtoken="false" />
<cfabort>
</cfif>
<cfoutput>
<p><strong>#variables.requestedURI#</strong></p>
<p>This document can not be found.</p>
</cfoutput>

IIS updates the variable CGI.Query_String to indicate some details about the 404 request, but since we're going to redirect the request, we need to strip out this meta-information. The first thing I do is strip everything left of the first semicolon by treating it as a semicolon delimited list and asking for the second item. (Note that this only works if your URL will never contain a semicolon. You'll have to use other methods if you need semicolons in your URL.) I also strip out the port, which IIS adds, by replacing ":80" with nothing. Once we have a cleaned up URL, we just cflocate to it, and let our onMissingTemplate function take care of the rest. This is all the functionality that we need in our custom 404 handler, so all thats left to do is configure IIS to use it.

To tell IIS to use this template, you need to put it somewhere web-accessible on the site that you want to use it for. I just made mine /404.cfm. Then, in IIS, go to the website properties, custom errors tab, and find the 404 error. Edit it, change the Message Type drop-down from FILE to URL (FILE will only process static files, not dynamic scripts), and specify the absolute path to your new script (/404.cfm).

Custom Error Setup in IIS

Now, when a request comes in for myclient.com/foo/, IIS recognizes that the folder doesn't exist and throws a 404 error. The error is handled by our new script, 404.cfm. As we saw above, this script will append index.cfm to the request and clean the URL up a bit, then do a 301 redirect (via cflocation) to what is essentially the same URL, just with the default document added on. This request is passed off to the ColdFusion application server, where it determines that the template doesn't exist, and invokes my onMissingMethod() function. This function recognizes the shop request, determines that it does exist, and passes any business rules, and passes it off to the shop-site request handler, which in turn displays the page.

It's an interesting workflow, and I haven't seen yet how efficient it is under load, but I love the fact that I was able to pull it off.

0
Average: 4.8 (4 votes)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)