Laravel Throttle message - laravel

I'm using ThrottleRequest to throttle login attempts.
In Kendler.php i have
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
and my route in web.php
Route::post('login', ['middleware' => 'throttle:3,1', 'uses' => 'Auth\LoginController#authenticate']);
When i login fourth time, it return status 429 with message 'TOO MANY REQUESTS.'
(by default i guess)
But i just want to return error message, somethings like:
return redirect('/login')
->withErrors(['errors' => 'xxxxxxx']);
Anybody help me! THANK YOU!

You can either extend the middleware and override the buildException() method to change the message it passes when it throws a ThrottleRequestsException or you can use your exception handler to catch the ThrottleRequestsException and do whatever you want.
so in Exceptions/Handler.php you could do something like
use Illuminate\Http\Exceptions\ThrottleRequestsException;
public function render($request, Exception $exception)
{
if ($exception instanceof ThrottleRequestsException) {
//Do whatever you want here.
}
return parent::render($request, $exception);
}

Related

Laravel Passport How to show custom error message when invalid token is supplied

I am trying to create an API with Laravel passport, and I have to protect some routes so that only authenticated users can access these routes.
Route::post('register', [ApiAuthController::class, 'register']);
Route::post('login', [ApiAuthController::class, 'login']);
Route::middleware('auth:api')->group(function () {
Route::post('/task', [ApiControllerTaskController::class,'store']);
});
Now hereafter login, I got an access token, and I used this access token like this.
Everything is working fine here, but I want to show an invalid token error message when I removed the bearer token. Instead, I got this.
Make sure you added the Content-type : application/json in your headers in Postman before sending your request
This worked for me, If your laravel version is >= 8.* add this code to your Handler.php witch located in App/Exceptions/Handler.php
public function render($request, Throwable $e)
{
if ($e instanceof AuthenticationException) {
return response()->json($e->getMessage());
}
return parent::render($request, $e);
}
If you need more help, leave me a commment. I hope I can help:)
//this worked for me (laravel 5.5) App\Exceptions\Handler.php (CTRL render)
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson() || $request->header('Authorization')) {
$response = ['status' => false, 'message' => 'Invalid token supplied'];
return response()->json($response, 401);
}
return redirect()->guest(route('login'));
}

customize ExceptionHandler in findOrFail error message

Good morning all,
Laravel v7.+
I made a
$user = User::findOrFail($id);
on my controller, it works well but when I have no result it sends me to a 404 page.
I would like to be able to do a return back with error message.
Some are talking about try catch.
Do you have any other solution to optimize?
Thank you, good day, stay home!
If you are having this issue in a single Controller only, you can use try catch
If you need a more general solution, you can work with the exception render method (https://laravel.com/docs/master/errors#render-method) on the ModelNotFoundException
public function render($request, Throwable $exception)
{
if ($exception instanceof ModelNotFoundException) {
return response()->view('errors.custom', [], 404);
}
return parent::render($request, $exception);
}
Alternative to try/catch
$user = User::find($id);
if(!$user){
return redirect()->back()->with(['error' => 'Error message']);
}
... your other logic here

Exception Handling when using both web and token api gaurd

Using laravel5.8. Using both web and API(Token Gaurd).
when using api call with invalid api_token parameter receiving an error Route:Login not defined. I want the response in JSON. Read in Forum I need to use the below way in app\Exceptions\Handler.php and it works. I have web gaurd for some of the paths. I want the route:login to work when its a web gaurd and return json response when using api gaurd. How can I do it in Laravel 5.8?
public function render($request, Exception $exception)
{
// dd(get_class($exception));
// return parent::render($request, $exception);
return response()->json(
[
'errors' => [
'status' => 401,
'message' => 'Unauthenticated',
]
], 401
);
}
I put the logic in unauthenticated function, combines with expectsJson() should solve your problem
// in app\Exceptions\Handler.php
public function render($request, Exception $exception)
{
return parent::render($request, $exception);
}
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['status' => 401,'message' => 'Unauthenticated.'], 401);
}
return redirect()->guest('/');
}

How to catch all exceptions in Laravel

I was wondering if there is a way to catch all the exceptions that are thrown in a laravel app and store them in database ?
I have been looking at some packages but coudn't find anything that tells where and how to catch the exceptions.
for catch all errors and log them you need to edit App\Exceptions\Handler file like this
public function render($request, Exception $exception)
{
if ($exception){
// log the error
return response()->json([
'status' => $exception->getStatusCode(),
'error' => $exception->getMessage()
]);
}
return parent::render($request, $exception);
}
As stated in the Docs,
You need to have to customize the render() method of App\Exceptions\Handler.
Edit the app/Exceptions/Handler.php:
public function render($request, Exception $e)
{
$error =$e->getMessage();
//do your stuff with the error message
return parent::render($request, $exception);
}

Different Response(JSON and webpage) in API and Website for Laravel 404 and 500?

I want to show the different response for API and website. In api response I want to show json response with 404 and 500 for type of exception mainly for routes.
If a user try to request a route and route not found I want to show a response in json response for API and webpage for website.
I know and try the code into app/Exceptions/Handler.php
public function render($request, Exception $exception)
{
if ($exception instanceof NotFoundHttpException) {
if ($request->expectsJson()) {
return response()->json(['error' => 'Not Found'], 404);
}
return response()->view('404', [], 404);
}
return parent::render($request, $exception);
}
https://laravel.com/docs/5.4/errors#http-exceptions
but failed can anybody help me how can I set different responses for error pages.
Expects JSON is about headers, i do not like that solution for API errors, you can access the API through a browser. My solution is most of the times to filter by the URL route, because it starts with "api/...", which can be done like so $request->is('api/*').
If you have your routes that are not prefixes with /api, then this will not work. Change the logic to fit with your own structure.
public function render($request, Exception $exception)
{
if ($exception instanceof NotFoundHttpException) {
if ($request->is('api/*')) {
return response()->json(['error' => 'Not Found'], 404);
}
return response()->view('404', [], 404);
}
return parent::render($request, $exception);
}
Just wanted to add an alternative to the above answers, which all seem to work as well.
After having the same problem and digging deeper, I took a slightly different approach:
your exception handle calls parent::render(...). If you look into that function, it will render a json response if your request indicates that it wantsJson() [see hints how that works here]
now, to turn all responses (including exceptions) to json I used the Jsonify Middleware idea from here, but applied it to the api MiddlewareGroup, which is by default assigned to RouteServiceProvider::mapApiRoutes()
Here is one way to implement it (very similar to referenced answer from above):
Create the file app/Http/Middleware/Jsonify.php
<?php
namespace App\Http\Middleware;
use Closure;
class Jsonify
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ( $request->is('api/*') ) {
$request->headers->set('Accept', 'application/json');
}
return $next($request);
}
}
Add the middleware reference to your $routeMiddleware table of your app/Http/Kernel.php file:
protected $routeMiddleware = [
...
'jsonify' => \App\Http\Middleware\Jsonify::class,
...
];
In that same Kernel file, add the jsonify name to the api group:
protected $middlewareGroups = [
...
'api' => [
'jsonify',
'throttle:60,1',
'bindings',
],
...
];
Result is that the middleware gets loaded for any requests that fall into the 'api' group. If the request url begins with api/ (which is slightly redundant I think) then the header gets added by the Jsonify Middleware. This will tell the ExceptionHandler::render() that we want a json output.
No need to hustle again for Laravel upgrade. You just need to define this method in the routes/api.php
Route::fallback(function(){
return response()->json(['message' => 'Not Found!'], 404);
});
I'm using Laravel 5.5.28, and am adding this in app/Exceptions/Handler.php
public function render($request, Exception $exception)
{
// Give detailed stacktrace error info if APP_DEBUG is true in the .env
if ($request->wantsJson()) {
// Return reasonable response if trying to, for instance, delete nonexistent resource id.
if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
return response()->json(['data' => 'Resource not found'], 404);
}
if ($_ENV['APP_DEBUG'] == 'false') {
return response()->json(['error' => 'Unknown error'], 400);
}
}
return parent::render($request, $exception);
}
This expects that your API calls will be having a header with key Accept and value application/json.
Then a nonexistent web route returns the expected
Sorry, the page you are looking for could not be found
and a nonexistent API resource returns a JSON 404 payload.
Found the info here.
You could combine this with the answer looking for the instance of NotFoundHttpException to catch the 500. I imagine, however, that the stack trace would be preferred.
finally found this for 9.x
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Register the exception handling callbacks for the application.
*
* #return void
*/
public function register()
{
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'Record not found.'
], 404);
}
});
}
source: https://laravel.com/docs/9.x/errors#rendering-exceptions
try this.
public function render($request, Exception $exception)
{
if ($request->ajax()) {
return \Response::json([
'success' => false,
'message' => $exception->getMessage(),
], $exception->getCode());
} else {
return parent::render($request, $exception);
}
}

Resources