Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Return response in Before Method in REST Controller
  • It seems that it isnt possible to return a response using the before method when used in the rest controller.

    It is successful when calling the base method, in this case /api/ but if you call a sub method, such as /api/test/ it skips the response from the before and runs the get_test method.

    If you swap out the return response with a die('test'); it works as expected.

    The following is an example:

    class Controller_Api extends \Controller_Rest
    {

        public function before()
        {
            parent::before();

    //API KEY CHECK
            return $this->response(array('message' => 'Unauthorized', 401);
        }

    get_test($param)
    {
    return $this->response(array('message' => $param), 200);
    }
     
    }
  • I think the before function is not designed for return response. You can use redirect or router method
  • Correct. The before() method is a prepping method, you can't alter the request flow in it. If you want that, use router().
  • I appreciate your input on this. I am still trying to solve this.

    The basic idea is that the before method checks for the presence of the api key and does validation before every other request. It seems like a clean logical place to put this repeated function.

    Redirecting from there to an "unauthorized" method would work, except for the fact that the before method is then called again when the unauthorized method is called.

    I suppose I could pass a dummy API key to the authorized method, but that seems a little hackish.

    Am I going about this wrong?


    Thank you again for your input. 
  • As I said: do not use before() to alter the flow. Use router().

    In there you can validate the request, return a json error if the API key doesn't validate, and call parent::router() to process the request if it does.
  • Thank you so much for your direction.

    What you are saying can be done with the router and what the docs say the router can do, dont line up, so I never considered that as an option.

    Can you point me to a quick example of using the router to do things other than create routes?

    Thats all I can see from here:



    Again, I areally appreciate your help here.
  • HarroHarro
    Accepted Answer
    The router() method in the controller has nothing to do with the Router class?

    The router method is documented here: http://fuelphp.com/docs/general/controllers/base.html#/router

    The routing process determines which controller/method to call. If that controller contains a router() method, it will be called instead of the determined method. The name of this method will be passed to router(), so after you have done your validation, you can still call the method originally requested.
        public function router($method, $params)
        {
            // do some validation here
            if ($something_is_true)
            {
    // call the REST router to process the request
            return parent::router($method, $params);
            }

    // validation failed, return a HTTP 401 and a message
    $this->response(array('status'=> 0, 'error'=> 'Not Authorized'), 401);
        }
    In case of the REST controller, simply call the parent router() method to process the request.
  • Thank you so much. You really helped to clarify that for me.
  • Hey Harro/Nearo,

    I've encountered an odd error doing this which I just solved.  The response function only determines formatting of $this->response after the call to parent::router();, therefore this functionality will either need to be duplicated before $this->response or some degree of refactoring would be necessary.

    Tony
  • Formatting of the response happens in the REST controllers after() method, if your action returns an array. It does so based on the format (defined or detected), and that happens in the router() method.

    Perhaps it would be an idea to extend the functionality of the auth config (currently only 'basic' and 'digest') to allow you to define a method name. This method should return true/false.

    The router() can call this method, and handle the result internally, Then no overloading of the router is needed, just configure your auth method name in the rest config file.
  • Thought this was such a great idea I just added it to 1.6/develop.

    You can now define an internal auth method in the config file. If this method exists it will be called by the router() to verify authorization. If should return true if authorized, and false if not.

    Now you don't have to overload router() anymore to do custom auth checks...
  • This is perfect.  Thanks Harro!

    Tony
  • I was looking at your solution and wanted to show how I did it. 

    Basically I have a rest controller named main which handles all of the leg work but I want to do some authentication before any requests are routed. I do this by setting a bool property $auth to false in the main controller and unless it's true in the router method no request will get processed. Here is a link to a gist since I can't paste it all here


    Feedback would be appreciated as well, I think this is a "secure" way of doing it.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion