在Laravel中,节流中间件用于限制应用对特定路由的请求频率。以下是一个简单的自定义节流中间件示例:
// app/Http/Middleware/ThrottleMiddleware.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Redis;
class ThrottleMiddleware
{
/**
* 处理传入的请求。
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int $maxAttempts
* @param int $decayMinutes
* @return mixed
*/
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
$key = $this->getCacheKey($request);
if ($this->hasTooManyAttempts($key, $maxAttempts)) {
return response()->json(['error' => 'Too Many Attempts.'], 429);
}
$this->incrementAttempts($key, $decayMinutes);
$response = $next($request);
$response->headers->set(
'X-RateLimit-Limit', $maxAttempts
);
$response->headers->set(
'X-RateLimit-Remaining', $this->getRemainingAttempts($key, $maxAttempts)
);
return $response;
}
protected function getCacheKey($request)
{
return $request->ip() . $request->path();
}
protected function hasTooManyAttempts($key, $maxAttempts)
{
return Redis::exists($key) && Redis::get($key) >= $maxAttempts;
}
protected function incrementAttempts($key, $decayMinutes)
{
Redis::incr($key);
Redis::expire($key, $decayMinutes);
}
protected function getRemainingAttempts($key, $maxAttempts)
{
$remaining = $maxAttempts - Redis::get($key);
return $remaining < 0 ? 0 : $remaining;
}
}
然后,在 app/Http/Kernel.php
中注册中间件:
protected $routeMiddleware = [
// ...
'throttle' => \App\Http\Middleware\ThrottleMiddleware::class,
];
使用方法:
在路由中使用 throttle
中间件,并指定最大尝试次数和时间。
Route::middleware('throttle:60,1')->group(function () {
// 这个组里的所有路由将会被节流
});
这个自定义节流中间件使用Redis来存储请求计数,并且可以通过路由群组来应用。每次请求时,中间件都会检查是否超过了指定的最大尝试次数,如果是,则返回429状态码。如果没有超过尝试次数,则增加计数并允许请求通过。在响应头中还会返回剩余尝试次数和最大尝试次数。