如何在中间件 Laravel 5 中捕获“太多尝试”异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45419193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 16:24:46  来源:igfitidea点击:

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

phplaravellaravel-5middlewarethrottling

提问by Anwar

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

我正在构建我的 API 并且我成功地在我围绕我的路由设置的中间件上捕获了一些错误,如下所示:

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
  • 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/useruntil I get the too many attemperror.

这很棒。我还知道控制路线尝试次数的油门机制。因此,与邮递员一起,我攻击了我的路线,http://localhost:8000/api/user直到too many attemp出现错误为止。

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.

由于这个论坛主题,我还设法获得了它抛出的异常类型: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.

你看到这条线了this string is never showed up吗?事实上它从来没有出现过,来自Illuminate的原始油门例外总是走在前面。

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.

运行 Laravel 5.4。

EDIT

编辑

I cannot afford manually updating app/Http/Exceptionfiles 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.phpmay have their own exception catching procedures.

我无法承担手动更新app/Http/Exception文件的费用,因为我的应用程序将作为我的期货其他项目的服务提供商提供。此外,我不喜欢冒险删除这些文件上的一些先前配置,因为其他“基本”路由routes.php可能有自己的异常捕获程序。

回答by Kevin Patel

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

实现这一目标的最佳方法是使用 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.

在这个演示中,您可以添加更多类似的异常} else if ($exception instanceof ModelNotFoundException) {并解决它们。