views:

151

answers:

5

(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.

+1  A: 

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).

Ben Doom
That's good info, but no, rather than SEO, my need comes from converting many, many old static .cfm / .html files to a database. I only need a couple .cfm files to use as a template for the content pulled from the db. I just need to figure out how to redirect all those legacy url requests to the template that handles the requests. Thanks!
Dan Sorensen
+4  A: 

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

Henry
Agreed. Looking into it further and comparing to an application.cfc or other Coldfusion solution.
Dan Sorensen
+2  A: 

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
Sergii
Very clever. That is the type of solution I hoping was possible.
Dan Sorensen
A: 

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.

Bialecki
Very useful information. Thanks!
Dan Sorensen
A: 

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.

Jeff Howden