Search code examples
laravelabortcustom-errors

Laravel - catch the custom abort message


I'm using the abort function to send a custom exception message from my service layer.

if($max_users < $client->users()->count()){
    return abort(401, "Max User Limit Exceeded");
}

But how do I catch this message in my controller, which is in a different application

try{

    $clientRequest = $client->request(
        'POST',
        "api/saveClientDetails",
        [
            'headers' => [
                'accept' => 'application/json',
                'authorization' => 'Bearer ' . $user['tokens']->access_token
            ],
            'form_params' => $data, 
        ]
    );

} catch ( \GuzzleHttp\Exception\ClientException $clientException ){

    switch($clientException->getCode()){
        case 401:       
            \Log::info($clientException->getCode());
            \Log::info($clientException->getMessage());

            abort(401);
            break;
        default:
            abort(500);
            break;
    }

}

The above code prints the following for the message:

But it prints

Client error: `POST http://project-service.dev/api/saveClientDetails` resulted in a `401 Unauthorized` response:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="robots" content="noindex,nofollow (truncated...)

Solution

  • Well you are trying to catch a Guzzle Exception instead when you should be catching a Symfony HttpException. Maybe try something like this:

    catch(\Symfony\Component\HttpKernel\Exception\HttpException $e)
    {
      \Log::info($e->getMessage());
    }
    

    Based on your comment, I tried the following:

    public function test()
    {
        try 
        {
            $this->doAbort();
        } 
        catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) 
        {
            dd($e->getStatusCode(), $e->getMessage());
        }
    }
    
    public function doAbort()
    {
        abort(401, 'custom error message');
    }
    

    and the output is:

    401
    "custom error message"
    

    Based on your comment, here's how it works for me.

    Route::get('api', function() {
    
        return response()->json([
            'success' => false,
            'message' => 'An error occured'
        ], 401);
    
    });
    
    Route::get('test', function() {
    
        $client   = new \GuzzleHttp\Client();
    
        try
        {
            $client->request('GET', 'http://app.local/api');
        }
        catch (\Exception $e)
        {
            $response = $e->getResponse();
            dd($response->getStatusCode(), (string) $response->getBody());
        }
    
    });
    

    This outputs the status code and the correct error message. If you use abort it will still return the full HTML response. A better approach would be to return a well-formatted JSON response.

    Let me know if it works for you now :)