Adding OnMissingTemplate() ColdFusion Event Handler To Big Sexy Poems
In the ColdFusion Application.cfc framework component, the onError() event handler is invoked if an error goes un-handled in your CFML code. However, if the incoming request never makes it to your CFML code, the onError() event handler is moot. Such is the default behavior when a client requests a non-existent .cfm or .cfc template. For better insight into possible application bugs, I've add the onMissingTemplate() event handler to Big Sexy Poems.
To be honest, I went back-and-forth on whether or not I should do this. In my ColdFusion application architecture, every "normal" request is routed through the root index.cfm file. As such, any request to a different .cfm file is either malicious behavior or me experimenting with something.
That said, I'm always a little curious to see what type of malicious behavior is afoot. The more insight I have, the better I can tune my web server request filtering. Plus, I suppose there's always a tiny chance that I introduce a bug that links a user to a missing CFML template. So, better safe than sorry.
Since I'm mostly just curious, I'm putting next to no effort into my onMissingTemplate() event handler. All it does is proxy it through to the normal request processing. Here's a truncated version of my Application.cfc:
component {
// .... truncated .... /
/**
* I handle requests to non-existent CFML templates.
*/
public void function onMissingTemplate( required string scriptName ) {
// Requesting a non-existent, top-level CFML template is almost certainly a
// malicious activity in the context of this application (which routes every
// request through a single root index file). As such, I probably shouldn't care
// about this request. But, to get a sense of where and when this might be
// happening, I'm going to handle this like a normal request so that I can see the
// errors show up in the logs.
// Override the event so that we don't render a valid response at the wrong
// script name.
url.event = "onMissingTemplate";
// Simulate the normal ColdFusion application request life-cycle.
onRequestStart();
include "./index.cfm";
onRequestEnd();
}
}
In my application architecture, all requests are routed through the root index.cfm file. Internally, routing to various subsystems and views is managed by the url.event parameter. As such, in order to proxy this missing template request, all I have to do is override the url.event value and then explicitly invoke the request processing workflow.
Aside: the ColdFusion documentation states that the
onError()event handler won't be invoked for exceptions that are raised within theonMissingTemplate()event handler; and that your logic should be placed within atry/catchblock. But my testing (in Adobe ColdFusion 2025) shows this to be false. Meaning, theonError()event handler will be invoked. Which is why I have notry/catchmechanics.
Since I don't have any internal routing for the onMissingTemplate URL value, this proxied request will be handled like any other invalid url.event value. Which is to say that it'll result in an App.Routing.InvalidEvent error, which will then be logged.
So now, if I make a request to a non-existent xxx.cfm file, I get a standard application experience:
Again, I'm not sure that the onMissingTemplate() event handler holds much value in the grand scheme of things. But, it's so easy to implement this event handler that it seems silly not to try it and find out what shows up in the logs.
Some Mechanical Caveats
If the onMissingTemplate() event handler returns false, it will signal to the ColdFusion runtime that your application did not handle the missing request. In that case, ColdFusion will invoke the onError() event handler.
However, if you did not define the onMissingTemplate() event handler at all, requests to non-existent CFML templates will not invoke the onError() event handler. Instead, these requests will result in the native (and less sexy) request processing error:
So, if nothing else, it's worth implementing the onMissingTemplate() event handler just to provide a prettier user experience (UX).
Want to use code from this post? Check out the license.
Reader Comments
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →