@@ -8,46 +8,46 @@ |
||
| 8 | 8 | |
| 9 | 9 | class RedisAdapter implements StoreInterface |
| 10 | 10 | { |
| 11 | - /** @var Redis */ |
|
| 12 | - protected $redis; |
|
| 13 | - |
|
| 14 | - /** |
|
| 15 | - * @param Redis $redis - configured instance |
|
| 16 | - */ |
|
| 17 | - public function __construct(Redis $redis) |
|
| 18 | - { |
|
| 19 | - $this->redis = $redis; |
|
| 20 | - } |
|
| 21 | - |
|
| 22 | - public function get(string $key): int |
|
| 23 | - { |
|
| 24 | - return (int)$this->redis->get($key); |
|
| 25 | - } |
|
| 26 | - |
|
| 27 | - public function inc(string $key, int $ttl = 60): int |
|
| 28 | - { |
|
| 29 | - $value = $this->redis->incr($key); |
|
| 30 | - if ($value === 1) { |
|
| 31 | - $this->redis->expire($key, $ttl); |
|
| 32 | - } |
|
| 33 | - |
|
| 34 | - return $value; |
|
| 35 | - } |
|
| 36 | - |
|
| 37 | - public function reset(string $key): bool |
|
| 38 | - { |
|
| 39 | - return (bool)$this->redis->delete($key); |
|
| 40 | - } |
|
| 41 | - |
|
| 42 | - public function isExceeded(string $key, int $max): bool |
|
| 43 | - { |
|
| 44 | - $value = $this->get($key); |
|
| 45 | - return $value >= $max; |
|
| 46 | - } |
|
| 47 | - |
|
| 48 | - public function ttl(string $key): ?int |
|
| 49 | - { |
|
| 50 | - $ttl = $this->redis->ttl($key); |
|
| 51 | - return $ttl > 0 ? $ttl : null; |
|
| 52 | - } |
|
| 11 | + /** @var Redis */ |
|
| 12 | + protected $redis; |
|
| 13 | + |
|
| 14 | + /** |
|
| 15 | + * @param Redis $redis - configured instance |
|
| 16 | + */ |
|
| 17 | + public function __construct(Redis $redis) |
|
| 18 | + { |
|
| 19 | + $this->redis = $redis; |
|
| 20 | + } |
|
| 21 | + |
|
| 22 | + public function get(string $key): int |
|
| 23 | + { |
|
| 24 | + return (int)$this->redis->get($key); |
|
| 25 | + } |
|
| 26 | + |
|
| 27 | + public function inc(string $key, int $ttl = 60): int |
|
| 28 | + { |
|
| 29 | + $value = $this->redis->incr($key); |
|
| 30 | + if ($value === 1) { |
|
| 31 | + $this->redis->expire($key, $ttl); |
|
| 32 | + } |
|
| 33 | + |
|
| 34 | + return $value; |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + public function reset(string $key): bool |
|
| 38 | + { |
|
| 39 | + return (bool)$this->redis->delete($key); |
|
| 40 | + } |
|
| 41 | + |
|
| 42 | + public function isExceeded(string $key, int $max): bool |
|
| 43 | + { |
|
| 44 | + $value = $this->get($key); |
|
| 45 | + return $value >= $max; |
|
| 46 | + } |
|
| 47 | + |
|
| 48 | + public function ttl(string $key): ?int |
|
| 49 | + { |
|
| 50 | + $ttl = $this->redis->ttl($key); |
|
| 51 | + return $ttl > 0 ? $ttl : null; |
|
| 52 | + } |
|
| 53 | 53 | } |
| 54 | 54 | \ No newline at end of file |
@@ -21,7 +21,7 @@ discard block |
||
| 21 | 21 | |
| 22 | 22 | public function get(string $key): int |
| 23 | 23 | { |
| 24 | - return (int)$this->redis->get($key); |
|
| 24 | + return (int) $this->redis->get($key); |
|
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | public function inc(string $key, int $ttl = 60): int |
@@ -36,7 +36,7 @@ discard block |
||
| 36 | 36 | |
| 37 | 37 | public function reset(string $key): bool |
| 38 | 38 | { |
| 39 | - return (bool)$this->redis->delete($key); |
|
| 39 | + return (bool) $this->redis->delete($key); |
|
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | public function isExceeded(string $key, int $max): bool |
@@ -7,76 +7,76 @@ |
||
| 7 | 7 | |
| 8 | 8 | class MemoryAdapter implements StoreInterface |
| 9 | 9 | { |
| 10 | - protected $cleanExpired = 30; |
|
| 11 | - protected $lastClean = 0; |
|
| 12 | - |
|
| 13 | - protected $store = []; |
|
| 14 | - protected $ttlKeys = []; |
|
| 15 | - |
|
| 16 | - public function get(string $key): int |
|
| 17 | - { |
|
| 18 | - $this->isNeedCleanExpired() && $this->cleanExpired(); |
|
| 19 | - return $this->store[$key] ?? 0; |
|
| 20 | - } |
|
| 21 | - |
|
| 22 | - public function __construct(int $cleanExpired = 30) |
|
| 23 | - { |
|
| 24 | - $this->cleanExpired = $cleanExpired; |
|
| 25 | - $this->lastClean = time(); |
|
| 26 | - } |
|
| 27 | - |
|
| 28 | - public function inc(string $key, int $ttl = 60): int |
|
| 29 | - { |
|
| 30 | - $value = $this->get($key); |
|
| 31 | - $this->store[$key] = ++$value; |
|
| 32 | - |
|
| 33 | - if ($value === 1) { |
|
| 34 | - $this->ttlKeys[$key] = time() + $ttl; |
|
| 35 | - } |
|
| 36 | - |
|
| 37 | - return $value; |
|
| 38 | - } |
|
| 39 | - |
|
| 40 | - public function reset(string $key): bool |
|
| 41 | - { |
|
| 42 | - unset($this->store[$key], $this->ttlKeys[$key]); |
|
| 43 | - return true; |
|
| 44 | - } |
|
| 45 | - |
|
| 46 | - public function isExceeded(string $key, int $max): bool |
|
| 47 | - { |
|
| 48 | - $value = $this->get($key); |
|
| 49 | - return $value >= $max; |
|
| 50 | - } |
|
| 51 | - |
|
| 52 | - protected function isNeedCleanExpired(): bool |
|
| 53 | - { |
|
| 54 | - return ($this->lastClean + $this->cleanExpired) < time(); |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - protected function cleanExpired(): void |
|
| 58 | - { |
|
| 59 | - $current = time(); |
|
| 60 | - |
|
| 61 | - array_filter($this->ttlKeys, function(int $time, string $key) use ($current) { |
|
| 62 | - $isExpired = $time < $current; |
|
| 63 | - |
|
| 64 | - if ($time < $current) { |
|
| 65 | - unset($this->store[$key]); |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - return !$isExpired; |
|
| 69 | - }, ARRAY_FILTER_USE_BOTH); |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - public function ttl(string $key): ?int |
|
| 73 | - { |
|
| 74 | - if (array_key_exists($key, $this->ttlKeys)) { |
|
| 75 | - $ttl = $this->ttlKeys[$key] - time(); |
|
| 76 | - return $ttl > 0 ? $ttl : 0; |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - return null; |
|
| 80 | - } |
|
| 10 | + protected $cleanExpired = 30; |
|
| 11 | + protected $lastClean = 0; |
|
| 12 | + |
|
| 13 | + protected $store = []; |
|
| 14 | + protected $ttlKeys = []; |
|
| 15 | + |
|
| 16 | + public function get(string $key): int |
|
| 17 | + { |
|
| 18 | + $this->isNeedCleanExpired() && $this->cleanExpired(); |
|
| 19 | + return $this->store[$key] ?? 0; |
|
| 20 | + } |
|
| 21 | + |
|
| 22 | + public function __construct(int $cleanExpired = 30) |
|
| 23 | + { |
|
| 24 | + $this->cleanExpired = $cleanExpired; |
|
| 25 | + $this->lastClean = time(); |
|
| 26 | + } |
|
| 27 | + |
|
| 28 | + public function inc(string $key, int $ttl = 60): int |
|
| 29 | + { |
|
| 30 | + $value = $this->get($key); |
|
| 31 | + $this->store[$key] = ++$value; |
|
| 32 | + |
|
| 33 | + if ($value === 1) { |
|
| 34 | + $this->ttlKeys[$key] = time() + $ttl; |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + return $value; |
|
| 38 | + } |
|
| 39 | + |
|
| 40 | + public function reset(string $key): bool |
|
| 41 | + { |
|
| 42 | + unset($this->store[$key], $this->ttlKeys[$key]); |
|
| 43 | + return true; |
|
| 44 | + } |
|
| 45 | + |
|
| 46 | + public function isExceeded(string $key, int $max): bool |
|
| 47 | + { |
|
| 48 | + $value = $this->get($key); |
|
| 49 | + return $value >= $max; |
|
| 50 | + } |
|
| 51 | + |
|
| 52 | + protected function isNeedCleanExpired(): bool |
|
| 53 | + { |
|
| 54 | + return ($this->lastClean + $this->cleanExpired) < time(); |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + protected function cleanExpired(): void |
|
| 58 | + { |
|
| 59 | + $current = time(); |
|
| 60 | + |
|
| 61 | + array_filter($this->ttlKeys, function(int $time, string $key) use ($current) { |
|
| 62 | + $isExpired = $time < $current; |
|
| 63 | + |
|
| 64 | + if ($time < $current) { |
|
| 65 | + unset($this->store[$key]); |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + return !$isExpired; |
|
| 69 | + }, ARRAY_FILTER_USE_BOTH); |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + public function ttl(string $key): ?int |
|
| 73 | + { |
|
| 74 | + if (array_key_exists($key, $this->ttlKeys)) { |
|
| 75 | + $ttl = $this->ttlKeys[$key] - time(); |
|
| 76 | + return $ttl > 0 ? $ttl : 0; |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + return null; |
|
| 80 | + } |
|
| 81 | 81 | |
| 82 | 82 | } |
| 83 | 83 | \ No newline at end of file |
@@ -10,67 +10,67 @@ |
||
| 10 | 10 | |
| 11 | 11 | class RateLimitMiddleware implements MiddlewareInterface |
| 12 | 12 | { |
| 13 | - /** @var Limiter */ |
|
| 14 | - protected $limiter; |
|
| 15 | - /** @var int */ |
|
| 16 | - protected $ttl = 60; |
|
| 17 | - /** @var int */ |
|
| 18 | - protected $max = 60; |
|
| 19 | - /** @var string */ |
|
| 20 | - protected $keyPrefix = 'limiter'; |
|
| 21 | - /** @var ResponseInterface */ |
|
| 22 | - protected $responseTooManyRequest = ''; |
|
| 23 | - /** @var string */ |
|
| 24 | - protected $keyAttr = 'client-ip'; |
|
| 13 | + /** @var Limiter */ |
|
| 14 | + protected $limiter; |
|
| 15 | + /** @var int */ |
|
| 16 | + protected $ttl = 60; |
|
| 17 | + /** @var int */ |
|
| 18 | + protected $max = 60; |
|
| 19 | + /** @var string */ |
|
| 20 | + protected $keyPrefix = 'limiter'; |
|
| 21 | + /** @var ResponseInterface */ |
|
| 22 | + protected $responseTooManyRequest = ''; |
|
| 23 | + /** @var string */ |
|
| 24 | + protected $keyAttr = 'client-ip'; |
|
| 25 | 25 | |
| 26 | - public function __construct(Limiter $limiter, ResponseInterface $response) |
|
| 27 | - { |
|
| 28 | - $this->limiter = $limiter; |
|
| 29 | - $this->responseTooManyRequest = $response->withStatus(429, 'Too Many Requests'); |
|
| 30 | - } |
|
| 26 | + public function __construct(Limiter $limiter, ResponseInterface $response) |
|
| 27 | + { |
|
| 28 | + $this->limiter = $limiter; |
|
| 29 | + $this->responseTooManyRequest = $response->withStatus(429, 'Too Many Requests'); |
|
| 30 | + } |
|
| 31 | 31 | |
| 32 | - public function setKeyAttr(string $attr): void |
|
| 33 | - { |
|
| 34 | - $this->keyAttr = $attr; |
|
| 35 | - } |
|
| 32 | + public function setKeyAttr(string $attr): void |
|
| 33 | + { |
|
| 34 | + $this->keyAttr = $attr; |
|
| 35 | + } |
|
| 36 | 36 | |
| 37 | - public function setKeyPrefix(string $keyPrefix): void |
|
| 38 | - { |
|
| 39 | - $this->keyPrefix = $keyPrefix; |
|
| 40 | - } |
|
| 37 | + public function setKeyPrefix(string $keyPrefix): void |
|
| 38 | + { |
|
| 39 | + $this->keyPrefix = $keyPrefix; |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - public function setMax(int $max): void |
|
| 43 | - { |
|
| 44 | - $this->max = $max; |
|
| 45 | - } |
|
| 42 | + public function setMax(int $max): void |
|
| 43 | + { |
|
| 44 | + $this->max = $max; |
|
| 45 | + } |
|
| 46 | 46 | |
| 47 | - public function setTtl(int $ttl): void |
|
| 48 | - { |
|
| 49 | - $this->ttl = $ttl; |
|
| 50 | - } |
|
| 47 | + public function setTtl(int $ttl): void |
|
| 48 | + { |
|
| 49 | + $this->ttl = $ttl; |
|
| 50 | + } |
|
| 51 | 51 | |
| 52 | - public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface |
|
| 53 | - { |
|
| 54 | - $limiterKey = $this->getKey($request); |
|
| 52 | + public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface |
|
| 53 | + { |
|
| 54 | + $limiterKey = $this->getKey($request); |
|
| 55 | 55 | |
| 56 | - if ($this->limiter->isExceeded($limiterKey, $this->max)) { |
|
| 57 | - return $this->responseTooManyRequest; |
|
| 58 | - } |
|
| 56 | + if ($this->limiter->isExceeded($limiterKey, $this->max)) { |
|
| 57 | + return $this->responseTooManyRequest; |
|
| 58 | + } |
|
| 59 | 59 | |
| 60 | - $response = $next->handle($request); |
|
| 61 | - $this->limiter->inc($limiterKey, $this->ttl); |
|
| 60 | + $response = $next->handle($request); |
|
| 61 | + $this->limiter->inc($limiterKey, $this->ttl); |
|
| 62 | 62 | |
| 63 | - return $response; |
|
| 64 | - } |
|
| 63 | + return $response; |
|
| 64 | + } |
|
| 65 | 65 | |
| 66 | - /** |
|
| 67 | - * @param ServerRequestInterface $request |
|
| 68 | - * |
|
| 69 | - * @return string |
|
| 70 | - */ |
|
| 71 | - protected function getKey(ServerRequestInterface $request): string |
|
| 72 | - { |
|
| 73 | - $key = $request->getAttribute($this->keyAttr); |
|
| 74 | - return sprintf('%s.%s', $this->keyPrefix, $key); |
|
| 75 | - } |
|
| 66 | + /** |
|
| 67 | + * @param ServerRequestInterface $request |
|
| 68 | + * |
|
| 69 | + * @return string |
|
| 70 | + */ |
|
| 71 | + protected function getKey(ServerRequestInterface $request): string |
|
| 72 | + { |
|
| 73 | + $key = $request->getAttribute($this->keyAttr); |
|
| 74 | + return sprintf('%s.%s', $this->keyPrefix, $key); |
|
| 75 | + } |
|
| 76 | 76 | } |
@@ -5,36 +5,36 @@ |
||
| 5 | 5 | |
| 6 | 6 | class Limiter |
| 7 | 7 | { |
| 8 | - /** @var StoreInterface */ |
|
| 9 | - protected $store; |
|
| 10 | - |
|
| 11 | - public function __construct(StoreInterface $store) |
|
| 12 | - { |
|
| 13 | - $this->store = $store; |
|
| 14 | - } |
|
| 15 | - |
|
| 16 | - public function get(string $key): int |
|
| 17 | - { |
|
| 18 | - return $this->store->get($key); |
|
| 19 | - } |
|
| 20 | - |
|
| 21 | - public function inc(string $key, int $ttl = 60): int |
|
| 22 | - { |
|
| 23 | - return $this->store->inc($key, $ttl); |
|
| 24 | - } |
|
| 25 | - |
|
| 26 | - public function reset(string $key): bool |
|
| 27 | - { |
|
| 28 | - return $this->store->reset($key); |
|
| 29 | - } |
|
| 30 | - |
|
| 31 | - public function isExceeded(string $key, int $max): bool |
|
| 32 | - { |
|
| 33 | - return $this->store->isExceeded($key, $max); |
|
| 34 | - } |
|
| 35 | - |
|
| 36 | - public function ttl(string $key): ?int |
|
| 37 | - { |
|
| 38 | - return $this->store->ttl($key); |
|
| 39 | - } |
|
| 8 | + /** @var StoreInterface */ |
|
| 9 | + protected $store; |
|
| 10 | + |
|
| 11 | + public function __construct(StoreInterface $store) |
|
| 12 | + { |
|
| 13 | + $this->store = $store; |
|
| 14 | + } |
|
| 15 | + |
|
| 16 | + public function get(string $key): int |
|
| 17 | + { |
|
| 18 | + return $this->store->get($key); |
|
| 19 | + } |
|
| 20 | + |
|
| 21 | + public function inc(string $key, int $ttl = 60): int |
|
| 22 | + { |
|
| 23 | + return $this->store->inc($key, $ttl); |
|
| 24 | + } |
|
| 25 | + |
|
| 26 | + public function reset(string $key): bool |
|
| 27 | + { |
|
| 28 | + return $this->store->reset($key); |
|
| 29 | + } |
|
| 30 | + |
|
| 31 | + public function isExceeded(string $key, int $max): bool |
|
| 32 | + { |
|
| 33 | + return $this->store->isExceeded($key, $max); |
|
| 34 | + } |
|
| 35 | + |
|
| 36 | + public function ttl(string $key): ?int |
|
| 37 | + { |
|
| 38 | + return $this->store->ttl($key); |
|
| 39 | + } |
|
| 40 | 40 | } |
@@ -5,19 +5,19 @@ |
||
| 5 | 5 | |
| 6 | 6 | interface StoreInterface |
| 7 | 7 | { |
| 8 | - public function get(string $key): int; |
|
| 8 | + public function get(string $key): int; |
|
| 9 | 9 | |
| 10 | - /** |
|
| 11 | - * @param string $key |
|
| 12 | - * @param int $ttl |
|
| 13 | - * |
|
| 14 | - * @return int - new value |
|
| 15 | - */ |
|
| 16 | - public function inc(string $key, int $ttl = 60): int; |
|
| 10 | + /** |
|
| 11 | + * @param string $key |
|
| 12 | + * @param int $ttl |
|
| 13 | + * |
|
| 14 | + * @return int - new value |
|
| 15 | + */ |
|
| 16 | + public function inc(string $key, int $ttl = 60): int; |
|
| 17 | 17 | |
| 18 | - public function reset(string $key): bool; |
|
| 18 | + public function reset(string $key): bool; |
|
| 19 | 19 | |
| 20 | - public function isExceeded(string $key, int $max): bool; |
|
| 20 | + public function isExceeded(string $key, int $max): bool; |
|
| 21 | 21 | |
| 22 | - public function ttl(string $key): ?int; |
|
| 22 | + public function ttl(string $key): ?int; |
|
| 23 | 23 | } |
| 24 | 24 | \ No newline at end of file |