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

Anw*_*war 3 php middleware throttling laravel laravel-5

我正在构建我的 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');
});
Run Code Online (Sandbox Code Playgroud)

中间件设法捕获以下异常:

  • Illuminate\Database\Eloquent\ModelNotFoundException
  • Illuminate\Validation\ValidationException
  • Exception

这太棒了。我还知道控制路线中尝试次数的节流机制。因此,我通过邮递员攻击了我的路线http://localhost:8000/api/user,直到出现错误too many attemp

异常在位于以下位置的文件中引发:

/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php
Run Code Online (Sandbox Code Playgroud)

由于这个论坛主题,我还设法获得了它抛出的异常类型:Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException

所以最后我的中间件看起来像这样:

<?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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

问题

我怎样才能正确地覆盖基本错误,以便我可以(如果可能)捕获任何异常,而不必修改照亮文件(如果有更新......)?

运行 Laravel 5.4。

编辑

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

小智 5

实现这一目标的最佳方法是使用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);
}
Run Code Online (Sandbox Code Playgroud)

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