204 Status Codes And ColdFusion CFHttp Calls

Posted December 4, 2007 at 9:50 AM

Tags: ColdFusion

The other day, in a comment to my caveman-style asynchronous ColdFusion page execution, JAlpino told me to look into the use of the 204 status code to help the CFHttp call return faster. I haven't done a ton with different status codes (mostly 200 and 301/302), so I did a quick Google search for status code 204. According to this page, the 204 status code represents a page that has no content:

204 No Content. This code is used in cases where the request was successfully processed, but the response doesn't have a message body.

According to JAlpino, when a browser receives this status code in the header, it closes the request because it thinks the request will not render any content. In the context of a CFHttp call, the hope is that the CFHttp request will close out immediately and allow the parent ColdFusion page to continue executing with little delay.

To test this, I set up a small ColdFusion page with a 204 status code definition:

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

  • <!---
  • Tell the browser there is no content by using the
  • status code, 204 - No content.
  • --->
  • <cfheader
  • statuscode="204"
  • statustext="No Content"
  • />
  •  
  • <!--- Set the content type and reset the output stream. --->
  • <cfcontent
  • type="text/html"
  • reset="true"
  • />
  •  
  • <!--- Flush headers. --->
  • <cfflush />
  •  
  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>Status Code Test: 204 No Content</title>
  • </head>
  • <body>
  •  
  • <h1>
  • Status Code Test: 204 No Content
  • </h1>
  •  
  • <p>
  • There is content on this page, but the header
  • information should tell the browser that no
  • content could be found.
  • </p>
  •  
  • <!---
  • To make sure that the page doesn't execute
  • instantaneously, let's get the page to sleep
  • for a few seconds.
  • --->
  • <cfthread
  • action="sleep"
  • duration="#(5 * 1000)#"
  • />
  •  
  • <p>
  • Done building page.
  • </p>
  •  
  • </body>
  • </html>

Here, you can see that I am setting the status code to 204 using ColdFusion's CFHeader tag. Then, I flush the header to make sure we don't build the whole page on the server before returning the header data. To make sure that this header status works, I am sleeping the page for 5 seconds, which would be a noticeable delay in the calling page.

Then, I set up a ColdFusion page to execute a CFHttp request to the 204.cfm page I built above:

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

  • <!--- Get the page that we want to call. --->
  • <cfset strURL = (
  • GetDirectoryFromPath(
  • "http://#CGI.server_name#:8#CGI.script_name#"
  • ) &
  • "204.cfm"
  • ) />
  •  
  •  
  • <!--- Mark the time that we are starting the request. --->
  • <cfset intStartTick = GetTickCount() />
  •  
  • <!---
  • Grab page that we know has a 204 no content header
  • and a long delay. This will test to see how fast the
  • CFHttp call returns based on header information.
  • --->
  • <cfhttp
  • url="#strURL#"
  • method="get"
  • result="objGET"
  • />
  •  
  •  
  • <!--- Output time to wait. --->
  • <cfoutput>
  •  
  • <p>
  • Wait Duration:
  •  
  • #DecimalFormat(
  • ((GetTickCount() - intStartTick) / 1000)
  • )#
  •  
  • Seconds
  • </p>
  •  
  • <p>
  • Content: [#objGET.FileContent#]
  • </p>
  •  
  • </cfoutput>

After the ColdFusion CFHttp quest returns, I am outputting the time of execution as well as the content that was returned. The execution time is obvious, but the content I am outputting to make sure that the CFHttp really does cut out of the request before the page is fully rendered.

When I run the calling page, I get the following output:

Wait Duration: 5.01 Seconds

Content: []

Ok, so what does this tell us? The 5.01 second execution time tells us that the CFHttp call did have to wait for the CFThread call on the 204.cfm template. But, the empty content tells us that the CFHttp call did not bring back any content with it. In a way, these are two conflicting properties of the call. It should have either returned instantly with no content, or it should have returned after 5 seconds with the content of the 204.cfm template.

At first, I thought that JAlpino was simply wrong in his assessment of how a 204 status code would interact with a ColdFusion CFHttp call. But the fact that we have conflicting behaviors as defined above didn't sit well with me. I kept going over it in my mind, and then I realized what the problem was: CFFlush!

CFFlush, as amazing of a tag as it is, is a bit buggy when it comes to flushing minimal amounts of data. If you look at where we are calling CFFlush in our 204.cfm ColdFusion template, you will notice that it is before any HTML and just after we cleared the output stream (content buffer). As such, at that point, we'd be flushing a few spaces and maybe a line return at best. CFFlush, however, doesn't always like to flush so little data.

To experiment, I moved the CFFlush to right after the doc type declaration:

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

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <!--- Flush headers. --->
  • <cfflush />
  • <html>

Now, the hope is that the text characters in the doc type would provide enough data such that the ColdFusion server would be happy to fully execute the CFFlush command. And indeed, running the page again, we get the following output:

Wait Duration: 0.02 Seconds

Content: []

Ok, now we're getting the results that we were hoping for. Looks like JAlpino dropped a great tip on me; using a status code of 204 will allow the ColdFusion CFHttp call to return much faster than the 1 second timeout hack that I was using. We just have to be very careful on how soon the Headers are flushed to the client.

And, on a related note, this just goes to show you how important it is to have a framework that allows CFFlush in the page rendering. Case in point, if you want to leverage header values before the page has fully rendered, you need to allow it.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page





Reader Comments

Dec 4, 2007 at 11:49 AM // reply »
14 Comments

Nice write up Ben! As usual, you go above an beyond in your research and gratefully share it with the rest of us. I've typically used 204 status codes instead of AJAX requests when it wasn't (absolutely) necessary to receive a response from the server, items like 'watch this item' or 'flag this site' kind of situations. - Justin


Dec 4, 2007 at 11:51 AM // reply »
6,516 Comments

@Justin,

That sounds like a good technique. And sorry about calling you JAlpino - I didn't know what your first name was :) Thanks for the hot tip and glad that I could echo it back out there.


Dec 4, 2007 at 1:28 PM // reply »
14 Comments

@ Ben, no problem about the name thing, I usually sign with JAlpino instead of my full name. Here is the article that I first learned about using 204 for async processing (http://cfdj.sys-con.com/read/46789.htm). This article piqued my interest in learning more about status codes and various request\response headers.


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 21, 2009 at 1:13 PM
My First ColdFusion Builder Extension - Encrypting And Decrypting CFM / CFC Files
@Ben, Because I am pedantic, I just want to make sure that everyone knows there is absolutely no encryption going on. There is only encoding and obfuscation. The cfencode tool only obfuscates your C ... read »
Nov 21, 2009 at 12:28 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jody I can't seem to get your code sample to work. If you are still having problems, try this code out and see if it gets you what you wanted. <!--- Comma delimited list with various duplicates ... read »
Nov 21, 2009 at 11:03 AM
Groovy Operator Overloading Does Not Work In The ColdFusion Context
Hi Ben, Thanks for this informative post. Now I am reading ur old posts too ... read »
Nov 21, 2009 at 10:56 AM
HostMySite.com Has The Best ColdFusion Hosting
@Mehul, Yes very nice people, however several downtimes per day which was not acceptable. Hence we had to move out. I am glad you are having good luck with them so far. ... read »
Nov 20, 2009 at 11:32 PM
Five Months Without Hungarian Notation And I'm Loving It
I've used headless camel case for years for not only ColdFusion variables, but also SQL tables and fields... pretty much everything involving code. I also subscribe to the "don't abbreviate and clea ... read »
Nov 20, 2009 at 11:00 PM
Five Months Without Hungarian Notation And I'm Loving It
@Marcel, Yeah, I always err on the side of longer but more readable variable names. As for the camel casing of CF methods and the headless camel casing of custom items, I get around this by always ... read »
Nov 20, 2009 at 10:56 PM
Five Months Without Hungarian Notation And I'm Loving It
I use the following and love it: my.namespace.MyComponents.functionMethodsOrUDF() CONSTANT_VALUES_OR_PROPERTIES One thing I always try is to CamelCaseBuiltInColdFusionFunctions() so others can tell ... read »