Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with:

Creating A "Down For Maintenance" Page Using Application.cfc

By Ben Nadel on

As some of you may or may not noticed, my site was down earlier for maintenance (more on that later). None of the ColdFusion pages on my site were available, no matter what URLs you used. Creating a page like this is insanely easy when you are using ColdFusion's Application.cfc component. If you have ever examined the application event methods available in the Application.cfc, you will notice that several of them return a boolean value. This value, while tiny, plays a huge part in the page processing. Anytime that one of the event methods returns false, it kills the rest of the page / application processing.

Using this information, we can easily build our "Down For Maintenance" page directly into the architecture of the Application.cfc component. Since we want to display this page for every request, it feels natural to put this functionality in the OnRequestStart() event method:

  • <cffunction
  • name="OnRequestStart"
  • access="public"
  • returntype="boolean"
  • output="true"
  • hint="Fires at the beginning of a page requested before the requested template is processed.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • hint="The template that was requested by the user."
  • />
  •  
  • <!--- Define the local scope. --->
  • <cfset var LOCAL = StructNew() />
  •  
  •  
  • <!--- Set header code. --->
  • <cfheader
  • statuscode="503"
  • statustext="Service Temporarily Unavailable"
  • />
  •  
  • <!--- Set retry time. --->
  • <cfheader
  • name="retry-after"
  • value="3600"
  • />
  •  
  •  
  • <h1>
  • Down For Maintenance
  • </h1>
  •  
  • <p>
  • The web site is current down for maintenance and will
  • be back up shortly. Sorry for the inconvenience.
  • </p>
  •  
  •  
  • <!---
  • By returning false, the rest of the page
  • rendering will hault.
  • --->
  • <cfreturn false />
  • </cffunction>

When creating a Down For Maintenance page, we have to be concerned with more than just the visual aspects; we also want to make sure that search engines such as Google and Yahoo respect that fact that our site is down and don't just assume that our site no longer has content! To do this, we explicitly set the Status Code of the page header to be:

503 - Service Temporarily Unavailable

This will alert the search engine bots and spiders that the site is down and to ignore the pages. But, we also want to take it one step further - we want to reassure the search engine bots that the site will be back up and that the bots should re-index the site shortly. To do this, we set another header value, retry-after. This returns the number of seconds (3,600 in our case) the search engine bots should wait before trying to re-index the site. While I am not sure about this, I have read that if you do NOT return a retry-after header value, the client (browser / bot) should treat this as a 500 - Internal Server Error, so be sure to set this properly!

After our header values, we output our HTML content and then return false. Returning "false" here is a huge point because by returning false, the ColdFusion application server knows not to even bother calling the OnRequest() event method which would have processed the requested template.

If you are using ColdFusion's Application.cfm template instead of Application.cfc, the same thing can be done, but with slightly less elegance. Instead of using any event methods (which don't exist in Application.cfc), you could simply put the header and output code directly into the Applicaiton.cfm:

  • <!--- Set header code. --->
  • <cfheader
  • statuscode="503"
  • statustext="Service Temporarily Unavailable"
  • />
  •  
  • <!--- Set retry time. --->
  • <cfheader
  • name="retry-after"
  • value="3600"
  • />
  •  
  • <h1>
  • Down For Maintenance
  • </h1>
  •  
  • <p>
  • The web site is current down for maintenance and will
  • be back up shortly. Sorry for the inconvenience.
  • </p>
  •  
  • <!--- Abort page. --->
  • <cfabort />

Then, instead of returning false, simply stop the page processing by executing a ColdFusion CFAbort tag.

While we put our output and header logic directly into our Application templates, there is nothing to say that we couldn't wrap this functionality into a template of its own which could then be included in the Application templates.



Reader Comments

Your site kept coming up in my google search for an cfajaxproxy issue I was running into and YOU WERE NOT THERE FOR ME! :( :(

;)

Reply to this Comment

@Todd,

Switching some name server stuff and it's causing a huge hassle. Never done this before, so trying to figure out how to get it done :)

I think by tomorrow, everything should be propagated and stuff will work smoothly going forward.

Reply to this Comment

This is a nice method, but I prefer to do it at the webserver level, as this obviously only works for coldfusion pages. Just create a second website that points to a page with the Maintenance message (use the 404 handler to do this too), set it up with all the same domains as the original site, stop the original site and start the second site.

Assuming you have access to the webserver.

Reply to this Comment

@Duncan,

Yeah. I am only recently getting more access to the server / IIS, so until then, this would have been my only option (without having to talk to management).

One of the things that I like about the ColdFusion method is that you can easily put in some logic to allow access from certain IP addresses. I am sure that you can do this via IIS, but I don't know how off-hand.

Reply to this Comment

You can also do this in the onRequest method. If you use on request, you can, by default, include the #targetPage# to have it function normally. Then, if you need to repoint, just change the include to the sorry page.

Same idea, different method.

Reply to this Comment

Hi guys,
I'm new to ColdFusion and perhaps my question will seem a bit stupid -- but why not just replace the index page with an html page with 'temporarily unavailable' text ?

Reply to this Comment

@Alexander,

The difference is that people might access pages that are NOT the index page. By marshaling the request itself, we can make sure to block all requests - not just that to the index page.

Reply to this Comment

This is very helpful. One minor problem I came across is that setting the status code to 503 seems to automatically output "The service is unavailable." to the body of the response as well as the header. Since the site I'm working on has to be down for a significant amount of time, and I have a pretty page to display while it's down, this is inconvenient. I got around this by setting the text color to the same color as the background, but I'm wondering if anyone know how to get ColdFusion to suppress the output in the response body? I'm using ColdFusion 8. Thanks!

Reply to this Comment

Well, to follow up on my previous comment ... I tried the same thing on the different server and "The service is unavailable." was not included in the response body. The only significant difference between the two servers that I can think of is that the one displaying the text is Windows 2008, and the other one is Windows 2003. I can only assume at this point that it's IIS7 that is to blame, but I don't really know at this point.

Reply to this Comment

@David,

I don't think I've ever played with a Windows 2008 server, so there could easily be differences in the IIS versions being used. Thanks for the input.

Reply to this Comment

Hi guys,
I'm new to ColdFusion and perhaps my question will seem a bit stupid -- but why not just replace the index page with an html page with 'temporarily unavailable' text ?

Reply to this Comment

@A,

You can do that if you want; but the reason behind a CFM page is that all requests to the server will be routed through the Application.cfc, which can manage the request in any way that it sees fit.

Reply to this Comment

Has anyone managed to get this working on IIS 7 or 8 without the system generating a 500 error ?

Each time we try this it seems to generate a 500 error screen on the page.

no matter what we do it always seems to generate the error screen...

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.