Throwing exceptions vs returning response

Published 2 years ago by poma

I've recently tried to use FormRequest and found out that it returns 403 response instead of throwing HttpException when authorisation fails:

https://github.com/laravel/framework/blob/5.1/src/Illuminate/Foundation/Http/FormRequest.php#L147

Is it a bug or intended behaviour? I'm building a REST API and need unified JSON format for all errors. I've already customised my exception handler for that. But how am I supposed to track down all random pieces of code that decide to return a response by themselves?

deltasolutions

There is a global error handler in Laravel ( handler.php ) , i think this one returns the response , you could customize it

poma
poma
2 years ago (1,255 XP)

I did. The problem is that errors in FormRequest validation don't throw exceptions that go through the handler. Instead they are wrapped in HttpResponseException that is rendered directly in illuminate/routing/route.php#136 and that is the problem I'm talking about.

minorgod

Don't know if this will help your situation, but I wanted to handle authorization failures a little differently in my app, so I added a forbiddenResponse() method to my formrequest that does a redirect with a custom error message. You could also return your own custom response using the same logic...

     class myRequest extends Request{
        
        protected $forbiddenMessage = "Forbidden";

        public function authorize()
    {
        if($some_unauthorized_condition){
            $this->forbiddenMessage = "You tried to do something you aren't authorized to do.";
            return false;
        }elseif($some_other_unauthorized_condition){
            $this->forbiddenMessage = "You tried to do some other thing you aren't authorized to do.";
            return false;
        }
        return true;
        }

    public function forbiddenResponse()
        {
            return \Redirect::back()->withMessage($this->forbiddenMessage);
        //or you could return your own response....
            //return new \Illuminate\Http\Response($this->forbiddenMessage, 403);
        }
}

Sorry for the poor formatting...I'm not so good with markdown.

skliche
skliche
2 years ago (148,090 XP)

@poma "Is it a bug or intended behaviour?" The answer is intended and documented behavior: "If the authorize method returns false, a HTTP response with a 403 status code will automatically be returned and your controller method will not execute." (http://laravel.com/docs/5.1/validation#form-request-validation)
Just throw an exception instead of returning false.

Regarding "how am I supposed to track down all random pieces of code", if you do a full search of "return new response" you will find that it's just a handful of places that actually make sense.

If you don't like all of that default behavior there are other options: Manually create a validator (Validator::make()) and use the fails() method or extend the FormRequest class and override the methods you don't like.

poma
poma
2 years ago (1,255 XP)

@skliche can you explain why developers of laravel did it this way? I can't see any advantages of returning response directly. Throwing http exception will also result in "HTTP response with a 403 status code will automatically be returned and your controller method will not execute" but will also be consistent with the rest of code base which also throws exceptions in unexpected situations.

Roni
Roni
1 week ago (52,380 XP)

@skliche I know it's 2 years later. I just somehow needed to read "extend the class and override the method". It's been a 10 hour day and my brain just wasn't going there on it's own. :)

cheers !

Please sign in or create an account to participate in this conversation.