Dave Carabetta Blog Banner


March 8, 2006

HTTP Status Codes Are Important!!


So I was pushing some files over to our staging environment so that I could run some initial load testing on a project I've been working on, and my rsync script was missing a file. So when I hit the staging area, I received the Missing Template Error Handler that I specified in the ColdFusion Administrator. Great. However, I also happened to have the LiveHTTPHeaders Firefox plugin open because I was checking some HTTP header information a few minutes earlier. In checking the header information for the response, I noticed that a status of "200 OK" was being returned rather than the expected "404 Not Found" status. That's not good. I checked the LiveDocs page for the Missing Template Error Handler setting, and I didn't see any indication as to what the expected status code should be. I had just assumed that since ColdFusion was "smart" enough to know the page was missing, that it would set the 404 status code for me. Apparently not.

The HTTP status code of a request is important, particularly for web crawlers like Google or Yahoo! indexing your site. If you get rid of some files (and don't do anything at the IIS or Apache level to redirect users), then you're effectively telling the crawlers that the page still exists with the 200 OK status code.

The fix to the page was easy. Just drop this at the top of your Missing Template Error Handler template:

<cfheader statuscode="404" statustext="Not Found" />

Note: It's critical that the statustext attribute say "Not Found" and nothing else.

A verification with my handy LiveHTTPHeaders plugin showed that the status code was indeed changed to 404 Not Found.

However, a missing template isn't the only situation where a status code is important. If you move a bunch of files around to better organize your site, keep in mind that search engines have likely already indexed your site or visitors may have bookmarked its location. Since you don't want to generate a bunch of missing template exceptions (regardless of the status code), a cleaner solution (again, barring directives being set in your web server configuration file) would be to specify a status code of 301, which notes that the requested file has been moved permanently. I've seen a lot of code where the developer has just used cflocation to do this. However, cflocation is notably different from a 301 redirect. A cflocation generates a 302 status code, which means that the file has been moved temporarily to a different URL. Hence, search engines will keep the "old" page in its index. However, with this code snippet below at the top of the old page, you can both redirect the user while specifying the more appropriate 301 error code:

<cfheader statuscode="301" statustext="Moved Permanently" />
<cfheader name="Location" value="http://www.mycompany.com/path/to/new/file.cfm" />

For a list of HTTP status codes and their definitions, I highly recommend you bookmark this page (or del.icio.us it or whatever the kids are doing these days).

And remember, the cfheader tag is your friend in these situations.



Comments
Steven Erat's Gravatar Dave,

Have you noticed the CFMX Admin setting for Enable HTTP Status Codes?

-------
Enable HTTP status codes:
Enables ColdFusion to set HTTP error status codes when ColdFusion errors are returned to the browser. ColdFusion sets an error status code of 404 if the template is not found and an error status code of 500 for server errors.
-------

This is on the Settings page, a few lines above the missing template handler.
# Posted By Steven Erat on 3/8/06 at 11:21 AM
Dave Carabetta's Gravatar Ya know, Steven, I have seen that before, but I had been told a really long time ago to disable that setting, and I have no idea why right now! I think the tip might have applied only to development machines, but I think it just became on habit on all setups I've done. Here's one reference to disabling it:

http://www.forta.com/blog/index.cfm?mode=entry&...

Are there any reasons (from your support experience) why this might need to be turned off? Otherwise, I'll certainly make sure it's on in production.
# Posted By Dave Carabetta on 3/8/06 at 12:34 PM
James Antill's Gravatar """Note: It's critical that the statustext attribute say "Not Found" and nothing else."""

Err, no. See:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.h...
# Posted By James Antill on 3/9/06 at 12:01 AM
Scott Krebs's Gravatar Hi Dave,
Your 301 example is straight from the documentation, however in my experience it does not work. The second cfheader tag (location) causes CF to reset to the 302 status code. We had a client who was catching fits with Google because of this. The workaround which I found was:
<cfheader statuscode="301" statustext="Moved Permanently#Chr(13)##Chr(10)#Location:site/index.cfm">
# Posted By Scott Krebs on 3/24/06 at 5:50 PM
Peter Maceli's Gravatar Scott, thanks for the tip. I have been running into the situation where in Firefox, a 301 in CF5 was returning processed HTML code. I searched around and came across this post, and your code example solved that problem.
# Posted By Peter Maceli on 1/5/07 at 12:40 AM
Scott Krebs's Gravatar No problem, Peter. I'm glad it's getting some mileage. I should note here for posterity, since I didn't mention it initially and obviously others are finding this information, that this addresses a bug in *CF5* where the first cfheader tag did set the buffer to send a 301 status code in the http headers but the second cfheader tag for location would reset that to a 302. The issue is fixed in CFMX, however the workaround does work in CFMX too so it's "forward-compatible" when upgrade time rolls around.
# Posted By Scott Krebs on 1/5/07 at 3:39 PM
Peter J. Farrell's Gravatar I'm really late into this post...

FYI, if you issue those two cfheaders, CF continues processing the page. You must manually call cfabort.

This is quite unlike using cflocation which implicitly does a "cfabort" after the cflocation tag is encountered. Just wanted to point this out for anybody using a framework like Mach-II -- without the cfabort there could be some disastrous effects.
# Posted By Peter J. Farrell on 2/23/07 at 12:48 PM
Strand's Gravatar I detected the same problem with 301 becoming a 302 in CF5. Scott Krebs has the fix in his comment. Nice work Scott! I'd add one thing. After the single line for CFHEADER 301, use the CFEXIT tag. CFABORT can be used but that throws a record to the CF admin log and is less graceful than CFEXIT. Remember, if you are in a CFINCLUDE then CFABORT must be used. If you do not stop execution, the result is a 404 and that's a lot worse than the 302 temporary redirect.
# Posted By Strand on 4/10/07 at 7:51 AM
Sheetal's Gravatar Thanks soooo much...You just saved my day by 301 code. All my 301's were showing as 302... Thanks a bunch!!!
# Posted By Sheetal on 8/9/07 at 12:21 PM
Dave Carabetta's Gravatar Your welcome Sheetal!
# Posted By Dave Carabetta on 8/9/07 at 3:13 PM
DTepe's Gravatar I've also noticed it's handy to use <CFHEADER> if you've set up IIS to use a CFM error message (through an absoulte URL.) I guess since the error is thrown by IIS and not by CF, the "Enable HTTP Status Codes" setting is ignored.
# Posted By DTepe on 10/29/07 at 1:17 PM
Edward Beckett's Gravatar Thanks ... I am supposed to have known better ... I set up a 404 handler on my site and forgot to set the header response ... could have me some problems had not Google Webmaster tools remind me that they couldn't verify my site due to all pages returning a 200 ...

Thanks for the help on the <cfheader tag ... I forgot what the correct content"" was supposed to be ...

E
# Posted By Edward Beckett on 2/14/08 at 3:19 AM
chris's Gravatar to Scott: what about switching the order of both cfheaders? i've done it this way for a while and haven't noticed any problems:

<cfheader name="location" value="http://www.domain.com/">
<cfheader statuscode="301" statustext="Moved Permanently">
<cfabort>

as you were saying that the second cfheader tag (location) causes CF to reset to the 302 status code. if the last cfheader tag is returning 301 then that should be what is ultimately returned in the header response.
# Posted By chris on 4/13/08 at 6:35 PM

© Dave Carabetta, 2005-2008. This blog licensed under the Creative Commons License. Some rights reserved. This is a personal weblog. The opinions expressed here represent my own and not those of my employer. Blog software provided by Raymond Camden.