2017-07-31 88 views
0

我建設我的API和我successfuly設法趕上中間件我周圍設置了我的路線就像下面一些誤區:如何捕捉「過多嘗試」例外中間件Laravel 5

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'); 
}); 

的中間件設法抓住以下情況除外:

  • 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 

而且我也設法得到異常的類型,它拋出感謝這個forum topicSymfony\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); 
     } 
    } 
} 

你看行this string is never showed up?實際上它從來沒有出現過,來自Illuminate的原始節氣門例外總是佔據前面。

問題

我怎樣才能正確地重寫的方式,我可能(如果可能)捕獲任何異常,而無需修改的照射文件(在更新的情況下...)基本誤差?

Runing laravel 5.4。

編輯

我不能手動更新app/Http/Exception文件,因爲我的應用程序將被運爲服務供應商對我的期貨其他項目。另外,我不喜歡冒這些風險來清除這些文件的一些以前的配置,因爲routes.php中的其他「基本」路由可能有它們自己的異常捕獲程序。爲實現這一

+0

需要精確版本的Laravel,因爲多年來錯誤處理已經發生了變化。 – Kyslik

+0

您可能需要重新閱讀https://laravel.com/docs/5.4/errors#the-exception-handler該部分,如果這不適合您,請返回。 – Kyslik

+0

我看過更新的問題,退一步說如果多個軟件包想「處理太多的請求」,Laravel會做什麼?那麼它會中斷,所以你需要在*應用程序級別處理基於HTTP的異常*而不是服務提供者級別,並且不要在中間件中嘗試...... catch。一段時間後想想它。「全局」處理程序是唯一的方法,你可以檢查請求數據,並確定它是爲了「你的軟件包」並處理它,如果不是隻是重新拋出它。 – Kyslik

回答

0

最好的辦法是使用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); 
} 

在本演示中,你可以添加更多的例外像} else if ($exception instanceof ModelNotFoundException) {和解決這些問題。

+0

不幸的是,這意味着即使位於'routes.php'中的「基本」路線也會受到影響,而不僅僅是API,這對我來說是一個問題。 –