37 lines
952 B
PHP
37 lines
952 B
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Middleware;
|
|
|
|
use App\Core\{Request, Response, Redis};
|
|
|
|
final class RateLimitMiddleware
|
|
{
|
|
/**
|
|
* @param int $limit Requests allowed
|
|
* @param int $window Seconds window
|
|
*/
|
|
public function handle(Request $request, callable $next, int $limit = 60, int $window = 60): mixed
|
|
{
|
|
$redis = Redis::getInstance();
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
$key = "ratelimit:" . md5($request->getPath() . "|" . $ip);
|
|
|
|
$current = $redis->get($key);
|
|
|
|
if ($current && (int)$current >= $limit) {
|
|
Response::error('لقد تجاوزت الحد المسموح من الطلبات، يرجى المحاولة لاحقاً', 'RATE_LIMIT_EXCEEDED', 429);
|
|
return null;
|
|
}
|
|
|
|
if (!$current) {
|
|
$redis->setex($key, $window, 1);
|
|
} else {
|
|
$redis->incr($key);
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
}
|