Performing ColdFusion Processing After A CFLocation Tag

Posted April 1, 2009 at 9:14 AM

Tags: ColdFusion

The other day, I had a situation where a user had to hit a page where some processing would be triggered. The user was then immediately forwarded onto another page after the processing took place. The processing that took place did not take long, but it was not mission critical so I wanted to have the user forwarded before it was done completing (as they had no need to wait around). Normally, this is the kind of thing that I would perform using CFThread; but, since I was on a ColdFusion 7 box, I had to go another route.

I knew that CFLocation immediately aborts the current page request and forwards the user; but, I figured I would set up a base test just to make sure. I coded up a quick example, logging break points on the first page and the target page. Here is my first landing page:

 Launch code in new window » Download code as text file »

  • <!--- Log pre-CFLocation value. --->
  • <cfset LogMessage( "Pre-CFLocation" ) />
  •  
  • <!--- Redirect user to next page. --->
  • <cflocation
  • url="page2.cfm"
  • addtoken="false"
  • />
  •  
  • <!--- Log post-CFLocation value. --->
  • <cfset LogMessage( "Post-CFLocation" ) />

As you can see, it logs a value, CFLocation's the user to the next page, then tries to log a second value. The next page is small and simply logs a test value:

 Launch code in new window » Download code as text file »

  • <!--- Log landing page value. --->
  • <cfset LogMessage( "Target Page" ) />
  •  
  • <p>
  • Target Page
  • </p>

When I run the above landing page and get forwarded to my target page, the log file has the following:

Pre-CFLocation
Target Page

As you can see, the "Post-CFLocation" value never got logged. This is expected as the CFLocation aborted the current page request.

Now, to get around this, I have replaced the CFLocation tag with two CFHeader tags. The CFLocation tag is ultimately just setting the same header values; however, by doing this manually, we can get the same effect without having ColdFusion abort the current page request:

 Launch code in new window » Download code as text file »

  • <!--- Log pre-CFLocation value. --->
  • <cfset LogMessage( "Pre-CFLocation" ) />
  •  
  • <!--- Tell the client that it will have to redirect. --->
  • <cfheader
  • statuscode="302"
  • statustext="Found"
  • />
  •  
  • <!--- Redirect user to next page. --->
  • <cfheader
  • name="location"
  • value="page2.cfm"
  • />
  •  
  • <!--- Flush header values to client. --->
  • <cfflush />
  •  
  • <!--- Log post-CFLocation value. --->
  • <cfset LogMessage( "Post-CFLocation" ) />

As you can see, we set the response status code and target location. The trick is then to call CFFlush directly afterwards. This immediately flushes the header values to the client (browser) which causes the redirect on the user's end. But, from ColdFusion's stand point, all we've done is committed the response so it keeps on processing the page. And, when we check out the log file, we can see that the post-CFLocation value is executed:

Pre-CFLocation
Post-CFLocation
Target Page

I don't think this is a solution that is all that critical; but, if you ever come to a scenario where you need an intermediary processing page, you can forward the user immediately with this technique without halting the processing of the current ColdFusion template.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page




Reader Comments

Apr 1, 2009 at 9:53 AM // reply »
35 Comments

In many cases, though we can expect someone to jump on the thread and list the exceptions, you could throw something like this off to CFThread for post location logging. The bigger question in my case is what was the use case someone had that they did not do the logging before changing the location. (or rather trigger a thread to log stuff as I said above)


Apr 1, 2009 at 9:57 AM // reply »
7,572 Comments

@John,

I was working with tracking some landing page information. Basically, someone get's a link, hits the site, data gets logged, and then user is forwarded to actual landing page. A campaign tracker of sorts (very dumbed down).

Like I said, the logging that was going on was really fast, so it didn't really matter. But, I wondered if I could forward the user first and then take care of the tracking second (as it wasn't related to the following landing page).

I would have gone CFThread, but I was on a CF7 box.


Apr 1, 2009 at 11:22 AM // reply »
44 Comments

You may want to version check this. I seem to remember older versions of CF that sniffed for Location in the cfheader, and automagically munged it to a cflocation.


Apr 1, 2009 at 2:42 PM // reply »
28 Comments

Reminds me of the old CF_location tag that was kicking around especially in the FuseBox circles, that did the same thing, which helped solve an earlier bug of Cookies not being set on a cflocation'ed page.

One thing that I wonder about though, is in many frameworks the content is saved as a variable, and if this is the case, you'd get an error trying to flush. Any way around that? (And on the side Ben, what framework do you prefer?)


Apr 1, 2009 at 4:41 PM // reply »
7,572 Comments

@Rick,

Really? That seems really funky and uncalled for.

@Tim,

I was actually playing around with a custom tag earlier (trying to write one). The problem, however, is that inside of a custom tag, you can't call CFFlush as the tags are build to gather generated output in full before returning control to the buffer (or something - I can't quite find a way around it).

As far as framework, I have a methodology that I like to follow, but no formalized framework at the time.


Apr 1, 2009 at 5:02 PM // reply »
44 Comments

To quote an old blog entry of mine:

http://rickosborne.org/blog/index.php/2006/09/14/the-perils-of-search-engine-spider-sessions/

"Here's a hint: CF5. On CF5, any and all header information is lost on a redirect - this includes cookies, which are set in the HTTP headers. I tried cheating by setting my own status code and Location headers with cfcontent and cfheader instead of cflocation tags, but it doesn't work. It turns out that CF5 converts all attempts at redirects into the same cflocation-like result. Thus, no matter how you do it, CF5 recognizes what you are trying to do and "helps" you do it correctly. And, oh yeah, discards any cookie headers you might have tried to set."


Apr 1, 2009 at 9:16 PM // reply »
12 Comments

There's a related issue that CF does not process onRequestEnd() on a cflocation. If you track the functions in application.cfc it goes:

onRequestStart for page 1
cflocation to page 2
onRequestStart for page 2
onRequestEnd for page2

which is the screwiest page lifecycle I can think of. Adobe agrees - their own JEE-level page request filters all clean up properly - but the same courtesy is not extended to CF code.

For this reason we use the old cf_location trick, but for us flushing isn't an issue so it's not something we've solved.


Apr 2, 2009 at 12:28 AM // reply »
78 Comments

@Ben's: "I have a methodology that I like to follow, but no formalized framework at the [moment]."

High ass 5. It's unbelievably refreshing to see an unofficial ColdFusion authority like yourself publicly reiterate the harsh reality that for a LOT of projects, the pure, unadulterated RAD "framework" that is ColdFusion ( paired with a personal, conscious development approach ) can be just as, if not MORE effective than blindly and consistently consigning your development to a formalized, public community framework or platform.

Now I'm not badmouthing formalized or community frameworks. They can offer fantastic benefits and/or fantastic limitations and drawbacks ( all depending on the scenario ).

On top of that, very few frameworks are useful if the person utilizing them doesn't know what they're doing. At the same time, if someone is completely expert and natural with a particular framework, they can often use it to develop at a higher speed and with less maintenance potential than they could, say, without using it.

I think formalized frameworks are particularly beneficial to huge teams or projects that will be maintained by many different developers within the same company.

Props for keeping it real Ben.


Apr 2, 2009 at 8:37 AM // reply »
7,572 Comments

@Rick,

That's bananas! I think that must have been gone since CF6 as I have never come up against it.

@Jaime,

Yeah, it does seem a bit odd, especially considering that the "refresh" is actually something performed on the client (browser) and not on the server.

@David,

I have the benefit (or drawback) of not working on real teams. As such, there is no need for a common language framework. Not to say that I am all willy-nilly with my code - far from it. I use a front-controller (index.cfm) and my directory structure is quite standardized. I even have my own dependency injection framework ... better known as a "Factory Method". I simply have not felt the "pain" needed to make me sit down an learn a framework.

My real "pain point" right now is understanding OOP. OOP, of course, is completely separate from the concept of a framework and can be learned / implemented independently. Now, if only it wasn't so gosh darn hard for me to wrap my head around!


May 18, 2009 at 5:37 AM // reply »
2 Comments

i can speak only for railo, but railo has adapt how other vendors handle this situation.
railo definty abort execution of the page, the same way as a cfabort does.

java code of cflocation in railo (stripped)
rsp.setHeader("Connection", "close");
rsp.setStatus(statuscode);
rsp.setHeader("location", url);


try {
pageContext.forceWrite("... html message");
} catch (IOException e) {
throw new NativeException(e);
}
pageContext.getDebugger().setOutput(false);
throw new Abort(Abort.SCOPE_REQUEST);


May 18, 2009 at 10:47 AM // reply »
78 Comments

I can speak only for myself when I say:

Railo Schmailo.


May 18, 2009 at 11:05 AM // reply »
35 Comments

Here we go...

My dad is stronger than your dad.

Yeah, well my dad uses Railo.

So what, my dad uses ColdFusion.

Blah, you guys bust me up... my dad uses Blue Dragon!

(This should be an interesting ride. LOL)


May 19, 2009 at 9:07 AM // reply »
7,572 Comments

Ha ha ha, fellas, fellas, no need to regress to middle school :)


May 19, 2009 at 9:23 AM // reply »
2 Comments

was never my idention to point in this direction, pherhaps i have made a failure in how i have written my text, sorry my english isn't so good to see the small nuance in the language.
wass just my 5c

greetings micha


May 19, 2009 at 9:26 AM // reply »
7,572 Comments

@Michael,

No worries at all.


May 19, 2009 at 12:36 PM // reply »
78 Comments

Michael: No man, don't worry about it. It was just a fun, harmless joke.

If I'd started saying things like, "Railo is an absolute bold-faced rip off of Adobe ColdFusion, that hired people right from the ColdFusion prerelease in probably the dirtiest competitive maneuver in the history of technology, and anyone that uses and supports it is directly contributing to the degradation and decline of the incredible future Adobe has for CF", then yeah, that would be something to address or freak out about. But who would say something like that? Not me.

Because I was, and I'm guessing John was too, just kidding around. Your English is fine.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »
Mar 21, 2010 at 3:42 AM
A New Wrist Pain
Chiropractic treatment is one of the best methods for treating numerous health problems naturally. After years of experience being a chiropractor, I have found that it is a powerful way to solve many ... read »
Mar 20, 2010 at 12:07 PM
Drawing On The iPhone Canvas With jQuery And ColdFusion
Simply awesome. Saved my day. ... read »
Mar 20, 2010 at 9:00 AM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
I would like to say thx for an easy way to create a bottom bar. I do have a ?. Is it possible to center the bar if i want to resize it to ex 85%. Regards Offenbach ... read »
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »
Jim
Mar 19, 2010 at 4:49 PM
Nobody Puts Baby In The Corner!
Wow. This is like suddenly finding a support group for your secret shame. I'm not alone! I always liked this movie, even though it is extremely cheesy. I just wish Jennifer Grey hadn't gotten the ... read »