How to catch "too many attempt" exception in a middleware Laravel 5
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.
Comments
-
Anwar almost 2 years
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 :
Illuminate\Database\Eloquent\ModelNotFoundException
Illuminate\Validation\ValidationException
Exception
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 thetoo 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 inroutes.php
may have their own exception catching procedures.-
Kyslik almost 7 yearsExact version of Laravel is needed, since error handling has changed over the years.
-
Kyslik almost 7 yearsYou may want to re-read laravel.com/docs/5.4/errors#the-exception-handler that part and come back if that does not work for you.
-
Kyslik almost 7 yearsI read updated question, take a step back what if multiple packages want to "handle too many requests" what will Laravel do? Well it will break, so you need to handle HTTP based exceptions at application level not at service provider level and do not
try..catch
in middleware its not good solution. Think about it out of the box for a while. "Global" handler is the only way, you may check for request data and determine that it was meant for "your package" and handle it and if not just re-throw it as is. -
Misbah Ahmad over 4 yearsFor laravel 5.6, you just have to handle the laravel.com/api/5.8/Illuminate/Http/Exceptions/…