Hoping somebody can spot where this is going sidew...
# box-products
n
Hoping somebody can spot where this is going sideways for me... All of our APIs are in a module, separate from the main web app. We have various API handlers that all extend our BaseRest.cfc, which in turn extends coldbox.system.RestHandler. Inside our BaseRest.cfc we have an aroundHandler() which does some security checks. Our API endpoints all contain code that looks about like so: event.getResponse() .setdata( rslt.data ) .setPagination( offset = rslt.pagination.offset, maxRows = 7, page = rslt.pagination.page, totalRecords = rslt.pagination.totalRecords, totalPages = rslt.pagination.totalPages ); If I comment out the aroundHandler(), it works fine -- I get the JSON back that I expect. If I un-comment aroundHandler() (even if the method itself is totally empty -- no running code, just the method signature), it stops returning JSON, and instead treats my API handler as a regular page in a ColdBox app -- it tries loading a layout, then a view, etc. With aroundHandler() turned on, I have to manually call event.renderData() in order to get the JSON back as expected. Clearly something is wrong. I think I need a fresh set of eyes -- any ideas, gang? Thanks for the help.
j
@nolanerck did you try using prc.response instead of event.getResponse() to see if it still exhibits the same behavior?
These are the conditions that need to be met for it to render the data: https://github.com/ColdBox/coldbox-platform/blob/master/system/RestHandler.cfc#L109 Is it possible something is being generated by the methods you are using in assembling that response that prevents the render?
b
@nolanerck I don't think an empty aroundHandler() does what you think it does. Having an empty around actually short circuits the entire action so it doesn't run at all! What would then occur is ColdBox would attempt to render a view and layout based on convention.
So when you say
With aroundHandler() turned on, I have to manually call event.renderData() in order to get the JSON back as expected.
I'm unclear if you mean an empty around handler, or an around handler which actually invokes the action as required with
Copy code
arguments.targetAction( argumentCollection=args )
n
I'll add more clarification... One thing we tried was tearing all the code out of aroundHandler() to see if something inside it was triggering the JSON-to-regular-View switch. What we found was that the problem happens regardless of what code is/isn't inside aroundHandler(). Even if I have standard code in aroundHandler() like so: var args = { event = arguments.event, rc = arguments.rc, prc = arguments.prc }; structAppend( args, eventArguments ); // execute the action now return arguments.targetAction( argumentCollection=args ); ...we still have the same problem. @jclausen in the code you linked to above, I see this comment: // Did the controllers set a view to be rendered? If not use renderdata, else just delegate to view. ...which sounds like I'm supposed to call event.renderData() in my handler. However in all of the examples I see in this repo: https://github.com/coldbox-templates/rest/blob/v7.x/handlers/Auth.cfc ...that's not the case. The Coldbox-templates stuff just uses event.getResponse().setData() -- but never calls event.renderData(), so it feels like something is off among these points of reference. Or maybe I'm misunderstanding something (entirely possible). Hope that helps. Thanks again for the assistance.
j
@nolanerck Are you overloading the
aroundHandler
method from
coldbox.system.RestHandler
? Because if you are, then you will need to manually replicate the rendering routines that are in the
aroundHandler
method of that. See brad’s link above, and mine to the rendering routines in the system.
You shouldn’t really have a need to declare your own
aroundHandler
method unless you want the outbound payload to be formatted differently.
n
@jclausen Yes we are. We're using aroundHandler() to run some authentication checks before the API handlers fire. I looked thru the links you posted above; nothing jumps out to me as "do this for API endpoints instead of Views". For reference, the current version of our aroundHandler() looks like so but I've been trying different variations of things this week, so really this is just a snapshot of how it happens to look at the moment:
Copy code
function aroundHandler ( event, targetAction, eventArguments, rc, prc )
    {
        event.noLayout();

        var args = {
            event = arguments.event,
            rc    = arguments.rc,
            prc   = arguments.prc
        };

        if( rc.testBoxAPIToken != application.TESTBOXAPITOKEN )
        {
            if( !AuthService.isLoggedIn() )
            {
               try {
                throw(type="InvalidCredentials", messages="Not logged in.");
               } catch (InvalidCredentials e ) {

               }
            }
        }

        structAppend( args, eventArguments );

        // execute the action now
        return arguments.targetAction( argumentCollection=args );

    }
...if I call event.renderData() in my Handler, I do indeed get back JSON, but according to the examples I've read thus far, I shouldn't have to do that since I'm already using event.getResponse().setdata( rslt.data )
hth
j
Because you have overloaded the aroundHandler method, you will need to perform the rendering in your custom method. See how that’s done in the Coldbox RESTHandler. The work that you are doing in that method, though, is much better suited to an interceptor. The preProcess interception point is a great place for this work because you can override the event before you even get to the handler
n
Meaning that I do need to call event.renderData()? But should do so in aroundHandler() itself instead of in the API endpoint handler?
j
Yes. Look at the Coldbox RESTHandler for an example. I still think you could remove your custom aroundHandler method, though and use a preProcess or preEvent interception to do those checks. Then it would “just work” 🙂
n
Thanks for the clarification, much appreciated! I'll give this a shot and see what happens.
b
Yeah, if you're not using the REST handler's built in aroundHandler method, there's not a lot of reason to use the REST handler at all IMO. Most of what it does is in its around handler. From your logic above, there doesn't seem to be any need to use around, I'd just use prehandler like John said or an interceptor.
n
Yeah I think we (i.e. another developer on my team that was doing a bit of trial and error on this) came to the same realization over the weekend. 🙂