Question

(Update: I converted this question to a community wiki as the answer appears more subjective than I thought it would. There are multiple answers depending on one's needs.)

If I have a folder that only includes application.cfc and index.cfm, what is a fast, reliable method to handle dynamically generated URLs? i.e. URLs that do not have a corresponding physical .cfm file.

This example url generates a 404, but it should lookup a page in a db and return it via index.cfm:

http://www.myserver.com/cfdemo/mynewpage.cfm

Should I use onMissingTemplate() in the application.cfc to handle the missing file? Since this method doesn't process onRequestStart(), onRequest() and onRequestEnd(), I wonder if it should be avoided.

Alternately, I could setup an ISAPIRewrite rule since I'm using IIS (or mod_rewrite on Apache)

# IF the request is not /index.cfm, doesn't exist and ends in cfm or html,
# rewrite it. Pass the requested filename $1.$2 as the 1st param: cgi.page
# append the remaining url params $4 ($3 is the ?)
RewriteCond %{SCRIPT_NAME} ^(?!/index.cfm)(.*)$
RewriteCond %{REQUEST_FILENAME}     !-f
RewriteCond %{REQUEST_FILENAME}     !-d 
RewriteRule ^\/(.*)\.(cfm|html)(\??)(.*)$   /index.cfm?page=$1.$2&$4 [I,L]

Are these methods appropriate, or am I missing a better way of accomplishing this goal? It seems that Coldfusion should have this type of feature built into the application.cfc. Maybe I'm just missing it.

Was it helpful?

Solution

nothing wrong with url rewrite on web server level. I'd vote for that.

OTHER TIPS

Because CF by default handles only cfm/cfc requests, you can do in the beginning of Application.cfc something like this:

<cfif Right(cgi.SCRIPT_NAME, 9) NEQ "index.cfm">
    <!--- analyze the SCRIPT_NAME and start processing --->
</cfif>

For other filetypes using web-server configuration is the only way I can see. But instead of creating rewriting rules you can try to use custom 404 handlers. At least when using IIS you'll be able to get the context in cgi.QUERY_STRING, if set up the dummy page, say 404.cfm (it does not need to exist) and putting following check before previous example:

<!--- trap 404 requests triggered by IIS --->
<cfif right(cgi.SCRIPT_NAME, 7) EQ "404.cfm">
    <cflog file="mylogfile" text="404 error triggered by IIS. Context: #cgi.QUERY_STRING#">
</cfif>

For Apache it is possible to use following handler, but I'm not sure if you can extract the context in this case:

ErrorDocument 404 /404.cfm

If you are doing this for SES URLs, I'd offer two pieces of advice.

The first is that they matter less and less as time goes on. Google, for example, recognizes that URLs need to include query data.

Second: CF can natively handle SES URLs in the form hostname/file.cfm/param1/param2. Ray Camden's BlogCFC, for example, works that way. It is on by default in CF8, but needs to be enabled in CF7. I don't have a lot of information handy on this, but it should be easy to Google (or Bing, or whatever).

If you can allow it, I'd try to convert URLs like:

http://www.myserver.com/cfdemo/mynewpage.cfm

to:

http://www.myserver.com/cfdemo/mynewpage OR
http://www.myserver.com/index.cfm/cfdemo/mynewpage

so that you don't lose the onRequest methods. The first one can be done only at the webserver level, so in Apache or IIS. The second one can be done in just ColdFusion. See this: http://www.cfcdeveloper.com/index.cfm/2007/4/7/Coldfusion-SES-URL.

Otherwise, if you must have the .cfm at the end, you can use a URL rewrite package in Apache or IIS to strip it out and then forward the request to a cfm page or do what you're doing with onMissingTemplate. I'd try to opt for a solution that doesn't involve losing the onRequest methods, but up to you.

I'd definitely go for URL rewriting. Not only will it be a more predictable, yet generalized approach, but it reduces a significant amount of string parsing load from the CF server. Further, it results in CF handling a request to a real file thereby getting you the benefit of onapplicationstart, onrequeststart, and other events.

As an aside, I've personally always found URLs like /index.cfm/foo/bar/ to look unpro and hackish. Additionally, URLs (like /foo/bar) that don't end in either a file extension or trailing slash are technically incorrect (per old-school static site conventions at the very least) and ought to probably be avoided as well. I'd also be curious where Ben Doom gets his assertion that "The first is that they matter less and less as time goes on. Google, for example, recognizes that URLs need to include query data." In my experience I've actually found the exact opposite to be true.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top