I have seen many customers getting confused in custom error pages and onMissingTemplate feature in ColdFusion and IIS. So I thought of blogging it for the use of larger audience. Before starting let me setup a platform.
Customer Eddard(name assumed) is using ColdFusion10(valid for ColdFusion11 too) configured with IIS. He has setup onMissingTemplate in Administrator of ColdFusion. Now Eddard expects ColdFusion to run this error page(mentioned in onMissinTemplate), let's call it 404.cfm, whenever user hits a page which doesn't exist. But suprisingly his browser is not showing the contents of 404.cfm and instead showing IIS 404 error page which is a static file(html file). After a lot of struggle he finds another confusing behavior that when he access the non existing page from machine where server is running(localhost) then his 404.cfm is getting executed. It's clear from the behavior that there is somehting in IIS which is handling this behavior.
In IIS settings he finds out that in "Site->Error pages->Edit feature settings->Error Responses" 3rd option was selected which says "Detailed error for local requests and custom error pages for remote requests". This option clearly explains that if the request will come from localhost then detailed error page will be executed whereas if the requests will come from Remote server then custom error page will be executed, which explains different behavior.
So Eddard is curious about two things now that what exactly is custom error or detailed error and how will he show his own error page 404.cfm to his users. So Eddard did a further research and found some answers like this. Custom error page is the feature in IIS by which you can tell IIS to execute a particular page based on particular error code. Eddard saw these settings in "IIS->site->error pages". He clicked on 404 and entered a cfm url in "Execute a URL on this site" setting. This URL pointed to the same page 404.cfm. And Bingo, hitting a request to non existing page executed his 404.cfm and contents were displayed as expected. So Eddard defintely know now that how to show his own error page to a user. But he still was thinking about difference between detailed error pages and custom error pages. Another question that came to Eddard was why onMissingTemplate even exists if he has to use custom error page.
Here I will give Eddard some rest and I will explain internal behavior of what all is happening. First of all I will explain custom error vs detailed error. In IIS when you select detailed error, IIS gives the server(ColdFusion) in this case full control of displaying the error message. And with that it also reveals a lot of server information which can be fatal if stolen or misused. So it is always recommended to not use detailed error messages for remote requests on production server. ColdFusion was charmingly executing onMissingTemplate in case of detailed error messages and IIS was dispaying the contents without any problem. But as I explained detailed error messages should not be used in production then how to execute onMissingTemplate. Well for that let me explain custom error messages, IIS asks you to execute a particular custom error page based on the status code. By default it will be IIS static page for all codes, you can see this in "IIS->site->error pages". Now in case of Eddard by default it was IIS static 404 html page mentioned in custom error which is why remote user was not seeing his own error page, remember this option "Detailed error for local requests and custom error pages for remote requests". So if you want your users to see your own custom pages then mention those url's in custom error page against that particular status code.
Since we have a good understanding of detailed error page and custom error page I will explain why onMissingTemplate was not getting executed for custom error page making it useless feature in production environment. What if I tell you it is being executed even in case of custom error page? You will ask then why Eddard's users were not able to see them? That is because IIS is discarding the contents of onMissingTemplate. Yes that's true, onMissingTemplate is not that useless, it is always executed even in case of custom error page. No matter what, if user hits a page which doesn't exist, onMissingTemplate will always be executed. It's just that onMissingTemplate responds with a status code of 404 to IIS. And when custom error page is setup, IIS detects that it's a 404 status code, so it discards the content of onMissingTemplate and executes the page mentioned with it. If it's static page then it will show static content or if it's .cfm url, then it will send the request back to ColdFusion to execute it. So in case of Eddard, 404.cfm page was getting executed twice, once by onMissingTemplate and next time by IIS because in custom error page he has again mentioned the same page. Not exactly a smart choice huh Eddard? A little knowledge is a dangerous thing(Eddard says - so is a lot).
You guys must be thinking what is the right approach then. I will give three scenarios and you can chose any one depending upon your requirements.
1. Custom error page - Simply use custom error page and do not use onMissingTemplate. You have to opt for "Custom error pages" in "IIS->site->error pages->edit feature settings". And give a 404.cfm url against required status code like 404 in "IIS->site->error pages". This cfm will be executed whenever that error has been hit like a user requested for non existing page. The page will not be executed twice since you have not mentioned anything in onMissingtemplate.
2. onMissingTemplate - Do not mention any .cfm url in custom error page rather mention it in onMissingTemplate. This will be useful in case you are not interested in showing contents to remote user rather you are just interested in some monitoring/logging. You can try to output somehting but IIS will discard it anyways and show contents of custom page(static html page by default). But for monitoring/logging purposes it should be fine because onMissingtemplate page will always be executed.
Note: There is a small hack to output content by using onMissingTemplate which you should not use but making you aware is my duty. If you explicitly set the status header as 200 OK using <cfheader> tag in onMissingTemplate, then IIS will never know that an error has occurred. It will always think that the page has properly executed and onMissingTemplate contents will not be discarded by IIS. So why is it a hack, because sending status code 200 OK in actually 404 NOT FOUND page is just wrong, it's like cheating your users in some manner. But yes, this is a way to bypass IIS discarding contents.
3. Custom error page + onMissingTemplate - Use can wisely use this option if you want to do some logging and also want to show contents to remote user only. In onMissingTemplate you give a URL of 404log.cfm and in custom error setting of IIS you give a URL of 404.cfm. So firstly 404log.cfm will be executed and then IIS will execute custom error page that is 404.cfm and will show the contents to user. This is a smart way of handling it.
4. onMissingTemplate(other webserver) - onMissingTemplate has a main advantage here as there are other webservers which are not as smart as IIS to detect error code and execute a custom error page. If you are using them, then without relying on web server's behavior you can simply give 404.cfm in onMissingTemplate and it will be executed and contents will not be discarded.
I hope that explains how to configure your ColdFusion servers and webservers smartly to handle your own error pages.
- Some customers complains that in CF9 the content of onMissingTemplate was not discarded by IIS. Fellow friends that is because in CF9 we were not returning the status code of 404 from onMissingTemplate so IIS didn't knew that it has to be handled. It was fixed as a part of bug in CF10. And CF10/CF11 behavior is the correct behavior as I explained in a note in point#2
- Thanks to Eddard(if he exists)