[coldbox 3.5.2] Routing to single handler when method is OPTIONS

I’m setting up a REST service. I’m planning having this REST service respond to CORS request. Basically what this means is that a browser may do a “pre-flight” request the webservice using OPTIONS as the method. My webservice should respond with a few custom headers letting the browser know that this is a legit request. My Routes.cfm file is set up with about 50 mappings to various handlers. What I would like to be able to do in my routes file is specify just once that if the request coming in is using the OPTIONS method that it should execute one specific handler. My alternative would be to update each route with an OPTIONS action, which isn’t horrible, but not ideal. Thoughts on how to accomplish?

Thanks.
Brett

Hi Brett,

I did this as well and I used the onRequestStart or onRequest method in Application.cfc. I can send the code in a bit if you need. It seemed more suitable to put it here vs further down in the Request.

Nolan

Interceptors would be perfect here, especially the preEvent or preProcess because you could check this out and then route to the handler you want.

Detecting a REST event would be easy, as the method to get the information would only be successful of returning something if it is a RESTful call. I do this for Facebook callbacks, as this is a RESTful event it checks that the desired information is in the header then continues on doing what it does, and if it is a normal URL request then it just exist gracefully or redirects to something else in the public side of the site.

Andrew and Nolan,

These are both good suggestions. I was so focused on the routes file that it didn’t even occur to me to handle this in the application or as an interceptor.

Thanks.
Brett

I would go interceptor, then you have the whole ColdBox framework at your finger tips :slight_smile:

OK, I implemented an Interceptor for dealing with the incoming OPTIONS method. Very simple to do, on the interceptor preProcess event, I check to see if the HTTP method is OPTIONS, and if so I override the event being executed. However, the issue I’m now having is that when I call my getHTTPOptions even in my controller, the SES Interceptor kicks in and says that it can’t find the route for OPTIONS. I kind of have a chicken before the egg syndrome. I’m wondering if there is some setting that would allow me to bypass the SES Interceptor for the incoming request when I’m in my custom interceptor’s preProcess event.

Thanks in advance.
Brett

The ses interceptor runs at request capture not preprocess

Luis Majano
CEO
Ortus Solutions, Corp
Toll Free/Fax: 1-888-557-8057
Direct: 909-248-3408
www.ortussolutions.com
Twitter: @lmajano, @ortussolutions

How are you calling the override event?

My guess is that you are doing a runEvent which queues back into a full entry.

Andrew,

I’m using the event.overrideEvent() method.

Brett

Hi Luis,

The interceptor I created only inherits from the ‘coldbox.system.interceptor’. Are you suggesting that I inherit from the SES interceptor?

Thanks.
Brett

Ok, so what is the SES interceptor doing with the OPTIONS or is this coming from another interceptor. The reason I ask is that the SES interceptor should just authenticate, shouldn’t need to know about anything in the headers except for username and password from a form.

Which begs the question, are you using the username and password for a RESTful to authenticate the call?

If you want to clean up the code and paste here so we can see the work flow your trying to achieve minus anything that may pertain Intellectual Property, or you can contact me off list if you would like to keep it private.

I am hoping to get a feel for the process flow, as well as what you trying to achieve from it.

Hi Andrew,

First off, thanks for your help on this issue. My response is pretty long. I might have this working by the way, but I’m not 100% sure if I’m going the best route.

I’m using the base SES interceptor the comes with Coldbox 3.5.2. My routes file is pretty simple and looks like this:

`

with(pattern="/VendorAPI", handler=“rest.”)
//Clients
.addRoute(pattern="/clients/:client_id/emps",handler=“Emps”,action={
GET = “getEmpsByClientId”
})

.endWith();

`

I have no explicit ‘OPTIONS’ defined in any of my route actions.

I put together a custom interceptor called ‘OptionsInterceptor’. This new interceptor has one interception point called onRequestCapture, which looks like this:

`

<---************************************************************************ ---> <---************************************************************************ ---> /* We check to see if the http method is OPTIONS, if it is we redirecto to the interceptor's redirectto property */ var redirectto = getProperty('redirectto');

if(event.getHTTPMethod() eq “OPTIONS”){
event.overrideEvent(redirectto);
return true;
}

return false;

`

My interceptors declaration in Coldbox.cfc is this:

`

//Register interceptors as an array, we need order
interceptors = [
//OPTIONS Interceptor
{
class=“interceptors.OptionsInterceptor”,
properties = {
redirectto=“rest.Clients.getHTTPOPtions”
}
},
//SES
{class=“coldbox.system.interceptors.SES”}

];

`

Basically my OptionsInterceptor gets the onRequestCapture announcement first. If the HTTP method is OPTIONS it sets the Event to be ‘Rest.Client.getHTTPOptions’ which is exactly what I want. This method will return true if the HTTP method is OPTIONS, thereby preventing other interceptors in the chain from executing which in this case is the SES Interceptor. This is important because if the SES Interceptor does execute then it will attempt to look up my original route and see if the route will has an action defined for the OPTIONS verb which will cause the SES interceptor to throw an error. If the HTTP method is something other than OPTIONS then OptionsInterceptor.onRequestCapture return false thereby letting the SES interceptor function as normal.

This approach gets me what I need but there are a couple of issues:

  1. Because I’m breaking the interceptor execution chain on my onRequestCapture event, does this mean I’m breaking the execution chain for all interceptors regardless of interception point, or just breaking it for any interceptor that is registered for the onRequestCapture event. Currently this isn’t a big deal as I don’t have any other interceptors.
  2. Because I’m never getting to the SES interceptor with an OPTIONS method, there isn’t a way to validate if the route is actually a valid one or not. Not a huge deal but it would be nice if I had this.
    I have considered going a different way with my custom interceptor where instead of returning true if its an OPTIONS method, I add a variable into the rc collection. I would then customize the SES interceptor to look to see if the rc variable exists and is set to true and if so, bypass the check the SES interceptor does to see if the method is valid for the route. I’m sure I would bump into problems with this and I’m not wild about tweaking the SES interceptor anyways.

Of course I could always just add the OPTIONS action to each of my routes explicitly, but I’m a programmer and therefore lazy. Though at this point I probably should have just sucked it up.

Thanks in advance.
Brett

I am not sure you are breaking the chain, I am not aware of any interceptor acting on whether a true or false is returned. They are executed in order of registration.

That means that if you NEED the SES to execute first it needs to be at the top of the chain, this used to be documented inside the coldbox config file.

But otherwise it looks good.