今天碰到過這樣一個狀況,我須要限制用戶請求某個API
接口的頻率,好比登陸、反饋等提交操做,通過一番搜索+折騰,總算是實現了。javascript
在
Laravel 5.2
的新特性中增長了一個throttle
中間件,經過它能夠在路由層限制API
訪問的頻率。例如限制頻率爲1分鐘50次,若是一分鐘內超過了這個限制,它就會響應:429: Too Many Attempts。php
但我在項目中使用的是Lumen
框架(它只有Laravel
中的一部分功能),它並無集成這個中間件,因此本文主要是講述如何在Lumen
框架中加入throttle
中間件。java
首先咱們要在app\Http\Middleware
中新建ThrottleRequests.php
文件。git
而且把如下連接中的代碼拷貝到這個文件中:github
github.com/illuminate/…bootstrap
接着修改文件中的命名空間:app
namespace App\Http\Middleware;
複製代碼
由於Lumen
框架缺失部分功能,咱們須要修改ThrottleRequests.php
中的resolveRequestSignature
方法:框架
protected function resolveRequestSignature($request){
return sha1(
$request->method() .
'|' . $request->server('SERVER_NAME') .
'|' . $request->path() .
'|' . $request->ip()
);
}
複製代碼
throttle
超過限制時拋出的是Illuminate\Http\Exceptions\ThrottleRequestsException
,一樣Lumen
框架缺乏這個文件,須要本身定義一下,在app/Exceptions
中新建ThrottleException.php
,寫入如下代碼:post
<?php
namespace App\Exceptions;
use Exception;
class ThrottleException extends Exception{
protected $isReport = false;
public function isReport(){
return $this->isReport;
}
}
複製代碼
在app/Exceptions/Handler.php
捕獲該拋出異常,在render
方法增長如下判斷:ui
if ($exception instanceof ThrottleException) {
return response([
'code' => $exception->getCode(),
'msg' => $exception->getMessage()
], 429);
}
複製代碼
修改ThrottleRequests.php
文件中的buildException
方法:
protected function buildException($key, $maxAttempts){
$retryAfter = $this->getTimeUntilNextRetry($key);
$headers = $this->getHeaders(
$maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
$retryAfter
);
// 修改了這一行
return new ThrottleException('Too Many Attempts.', 429);
}
複製代碼
需在文件頭部中添加這一行:
use App\Exceptions\ThrottleException;
在bootstrap/app.php
中註冊:
$app->routeMiddleware([
'throttle' => App\Http\Middleware\ThrottleRequests::class,
]);
複製代碼
到這裏咱們就加入成功了,接着在路由中添加中間件便可:
$router->group(['middleware' => ['throttle:10,2']],function() use ($router){
$router->post('feedback','UserController@addFeedback');
});
複製代碼
其中throttle:10,2
表示的是2分鐘內訪問10次。
注:此文爲原創文章,如需轉載,請註明出處。