Search code examples
iiscoldfusioncoldfusion-11mura

How do you handle 404 errors with Mura and your web server?


I have searched for an answer but I have not been able to find a definitive source of information. What I am after is the ability to log/notify for EVERY 404 error. The information that I have found online solves some 404 errors but not all. I have done some testing and below are the results of that testing. How are you handling 404 errors with your Mura sites?

I am using IIS and Adobe ColdFusion and Mura 6.2.6338.
I created my own onSite404 function to capture that event from Mura.
I created my own ColdFusion page to capture when IIS fires it’s 404 handler.

Based on my testing it appears that there is some built-in Mura functionality to handle 404’s from the web root. They do not seem to follow the standard 404 execution pattern. Not sure I have seen that documented anywhere?

I received a couple of timeout errors during some of my testing. Not sure why. Probably in the way I am trying to call the normal Mura processing from my custom IIS 404 page.

Basically what I want is to have all IIS 404 errors call my own custom ColdFusion page where I can log/notify the error and then display the normal Mura 404 page (without using a redirect as that negates the 404 status code to the user).

Here are the results of my testing:

With only the Mura 404 page defined:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       n/a    shows home page
/filedoesnotexist.htm                       No       n/a    shows home page
/filedoesnotexist.asp                       No       n/a    shows iis 404 error
/folderdoesnotexist/                        Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       n/a    shows iis 404 error

With the Mura 404 page defined and the IIS 404 pointing to the same Mura 404 page /index.cfm/404/:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No     Unknown  shows home page
/filedoesnotexist.htm                       No     Unknown  shows home page
/filedoesnotexist.asp                       No     Unknown  shows mura 404 page
/folderdoesnotexist/                        Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No     Unknown  shows mura 404 page

With the Mura 404 page defined and the IIS 404 pointing to it’s own 404 page /iis404.cfm:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     shows home page
/filedoesnotexist.asp                       No       Yes    shows custom iis 404 page
/folderdoesnotexist/                        Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows custom iis 404 page

With the Mura 404 page defined and IIS 404 pointing to it’s own 404 page /iis404.cfm in the web root that calls Mura processing via application.contentServer.handleRootRequest():

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     500 Internal server error – coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       Yes    shows home page
/folderdoesnotexist/                        Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows home page

With the Mura 404 page defined and IIS 404 pointing to it’s own 404 page /siteid/iis404.cfm in the site id root that calls Mura processing via application.contentServer.parseURLLocal():

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     500 Internal server error – coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       Yes    shows home page
/folderdoesnotexist/                        Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows home page

Mura seems to be handling any ColdFusion 404 errors except in the web root and I can do my processing within the onSite404 method. But I can't figure out how to get other 404 errors to do my processing AND call the Mura 404 page to display to the user.

Just documenting some more findings. I have found mention on a couple of blog posts online that for IIS you should set existingResponse to PassThrough under the httpErrors section of the configuration and it will fix some 404 issues. Well here are my test results after making that change:

With the Mura 404 page defined and the IIS 404 pointing to its own 404 page /iis404.cfm and IIS httpErrors set to PassThrough for existingResponse:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       No     shows blank 404 page
/folderdoesnotexist/                        Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       No     shows blank 404 page

So with this configuration it appears that the IIS 404 never actually calls my ColdFusion template. And worse on some requests it just sends a blank 404 response. Working as designed I suppose as the PassThrough tells it to just pass the response along.

Documenting another result after the answer from @Grant. I had already experimented with Mura's standard404Handler method but did not want to override all of it's functionality because honestly, I'm not sure what all it is doing and did not want to break some standard Mura functionality. Also, I saw that it is from within this method that the onSite404 method is called. So I would assume that the test results from overrriding the standard404Handler method would be no different than when using the 'onSite404` method. My test results support that.

With the Mura 404 page defined and the IIS 404 pointing to it’s own 404 page /iis404.cfm and overriding the Mura standard404Handler:

Requested URL                           onSite404  IIS 404  standard404Handler  Displayed
                                         called     called    called
/filedoesnotexist.cfm                       No        No        No              shows home page
/filedoesnotexist.htm                       No        No        No              shows home page
/filedoesnotexist.asp                       No        Yes       No              shows custom iis 404 page  
/folderdoesnotexist/                        No        No        Yes             shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    No        No        Yes             shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    No        No        Yes             shows mura 404 page  
/folderdoesnotexist/filedoesnotexist.asp    No        Yes       No              shows custom iis 404 page  

It is obvious now that I need to use both the Mura onSite404 method and some sort of custom 404 handler from my IIS configuration. So if I can just find a way to display the Mura 404 page, while keeping the 404 status code, after my custom 404 handler runs that will resolve my issue.


Solution

  • Thanks for the responses. I played around with this a bit more and think I may have found a solution. It will need to be tested further but so far so good. Remember - what I was after here was to log and/or notify for any 404 errors, return the Mura 404 page content and return a proper 404 status code.

    It turns out that Mura has a pretty solid solution already in place for handling ColdFusion 404 errors like /some_non_existent_folder/some_non_existent_file.cfm. If you have created a page named "404" then Mura will display that page and return a proper 404 status code.

    The issue is that Mura does not, and should not, handle 404 errors for non-cfm pages like /some_non_existent_folder/some_non_existent_file.jpg. Instead those are handled by your web server (IIS in my case). So we need to define a custom page to handle these IIS 404 errors. That way we can log/notify and finally display the 404 page content to the user and return a proper 404 status code.

    First let me reiterate that I still do not have a solution for 404 errors that occur for files in the web root like /some_non_existent_file.cfm or /some_non_existent_file.jpg. Mura itself does not display the 404 page that is defined. Instead the home page is displayed. I think the IIS URL rewrite rules are catching these before any error handling can take place. But I am okay with this.

    For all of the other 404 errors this is what I have done. I found in my testing that when I had the onSite404 method defined and a custom IIS 404 handler defined, both were being fired for ColdFusion missing files and only the IIS handler for non-cfm files. I don't need to process these twice so I removed the onSite404 method that I had defined. This leaves only the custom IIS 404 handler pointing to a ColdFusion page that I have created (outside of Mura).

    The final piece for me was to find a way of calling the Mura 404 page that we have created but still return a proper 404 status code. This is where the built-in Mura processing kicks in. As I mentioned, Mura will already handle missing .cfm files correctly. So I dug around the Mura code to see how they were calling the 404 page and see if I could copy that. This is the code that I found and seems to be working for me. I placed this at the end of my custom ColdFusion page that the IIS 404 handler is calling.

    <cfinvoke component="/requirements/mura/content/contentServer" method="render404" />
    

    The render404 method of the contentServer.cfc seems to be working perfectly to display the Mura 404 page content and still return a proper 404 status code.

    If anyone knows of any issues calling this method this way then please let me know.