Anwar
Anwar

Reputation: 4246

How to catch "too many attempt" exception in a middleware Laravel 5

I am building my API and I successfuly managed to catch some errors on a middleware I set up around my routes like following :

Route::group(['middleware' => \App\Http\Middleware\ExceptionHandlerMiddleware::class], function() {

    Route::resource('/address', 'AddressController');

    Route::resource('/country', 'CountryController');

    Route::resource('/phone', 'PhoneController');

    Route::resource('/user', 'UserController');
});

The middleware manage to catch the following exceptions :

Which is great. I am also aware of a throttle mecanism that control the number of attempt in a route. So with postman I attacked my route http://localhost:8000/api/user until I get the too many attemp error.

The exception is throwed in the file located at :

/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php

And I also managed to get the type of exception it throws thanks to this forum topic : Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException.

So in the end my middleware looks like this :

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
use Exception;

class ExceptionHandlerMiddleware
{
    public function handle($request, Closure $next)
    {
        $output = $next($request);

        try {
            if( ! is_null( $output->exception ) ) {
                throw new $output->exception;
            }

            return $output;
        }
        catch( TooManyRequestsHttpException $e ) {
            return response()->json('this string is never showed up', 429);
        }
        catch( ValidationException $e ) {           
            return response()->json('validation error' 400);
        }
        catch( ModelNotFoundException $e ) {            
            return response()->json('not found', 404);
        }
        catch( \Exception $e ) {            
            return response()->json('unknow', 500);
        }
    }
}

You see the line this string is never showed up ? In fact it is never showed up, the original throttle exception from Illuminate always take the front.

QUESTION

How can I properly override the base error in a way that I could possibly (if possible) catch any exception without having to modify the illuminate file (in case of updates...) ?

Runing laravel 5.4.

EDIT

I cannot afford manually updating app/Http/Exception files because my app will be shipped as a Service Provider for my futures others project. Also, I do not prefer taking the risk to erase some previous configuration on these files, as other "basic" routes in routes.php may have their own exception catching procedures.

Upvotes: 3

Views: 13002

Answers (1)

Kevin Patel
Kevin Patel

Reputation: 150

Best way to achieve that is to use app\Exceptions\Handler.php

public function render($request, Exception $exception)
{
    if ($this->isHttpException($exception)) {
        if (request()->expectsJson()) {
            switch ($exception->getStatusCode()) {
                case 404:
                    return response()->json(['message' => 'Invalid request or url.'], 404);
                    break;
                case '500':
                    return response()->json(['message' => 'Server error. Please contact admin.'], 500);
                    break;

                default:
                    return $this->renderHttpException($exception);
                    break;
            }
        }
    } else if ($exception instanceof ModelNotFoundException) {
        if (request()->expectsJson()) {
            return response()->json(['message' =>$exception->getMessage()], 404);
        }
    } {
        return parent::render($request, $exception);
    }
    return parent::render($request, $exception);
}

In this demo you can add more Exception like } else if ($exception instanceof ModelNotFoundException) { and tackle them.

Upvotes: 5

Related Questions