@@ -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 |