Completed
Push — master ( f8807b...5769db )
by Nikola
06:22
created

RateLimitMiddleware::process()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
c 0
b 0
f 0
rs 9.6333
cc 3
nc 3
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RateLimit\Http;
6
7
use Psr\Http\Message\ServerRequestInterface;
8
use Psr\Http\Server\RequestHandlerInterface;
9
use RateLimit\RateLimiter;
10
use Psr\Http\Message\ResponseInterface;
11
use RateLimit\Status;
12
13
final class RateLimitMiddleware
14
{
15
    public const HEADER_LIMIT = 'X-RateLimit-Limit';
16
    public const HEADER_REMAINING = 'X-RateLimit-Remaining';
17
    public const HEADER_RESET = 'X-RateLimit-Reset';
18
19
    /** @var RateLimiter */
20
    private $rateLimiter;
21
22
    /** @var GetQuotaPolicy */
23
    private $getQuotaPolicy;
24
25
    /** @var ResolveIdentifier */
26
    private $resolveIdentifier;
27
28
    /** @var RequestHandlerInterface */
29
    private $limitExceededHandler;
30
31
    public function __construct(
32
        RateLimiter $rateLimiter,
33
        GetQuotaPolicy $getQuotaPolicy,
34
        ResolveIdentifier $resolveIdentifier,
35
        RequestHandlerInterface $limitExceededHandler
36
    ) {
37
        $this->rateLimiter = $rateLimiter;
38
        $this->getQuotaPolicy = $getQuotaPolicy;
39
        $this->resolveIdentifier = $resolveIdentifier;
40
        $this->limitExceededHandler = $limitExceededHandler;
41
    }
42
43
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
44
    {
45
        $quotaPolicy = $this->getQuotaPolicy->forRequest($request);
46
47
        if (null === $quotaPolicy) {
48
            return $handler->handle($request);
49
        }
50
51
        $identifier = $this->resolveIdentifier->fromRequest($request);
52
53
        $status = $this->rateLimiter->handle($identifier, $quotaPolicy);
54
55
        if ($status->quotaExceeded()) {
56
            return $this->setRateLimitHeaders($this->limitExceededHandler->handle($request), $status)
57
                ->withStatus(429);
58
        }
59
60
        return $this->setRateLimitHeaders($handler->handle($request), $status);
61
    }
62
63
    private function setRateLimitHeaders(ResponseInterface $response, Status $rateLimitStatus): ResponseInterface
64
    {
65
        return $response
66
            ->withHeader(self::HEADER_LIMIT, (string) $rateLimitStatus->getQuota())
67
            ->withHeader(self::HEADER_REMAINING, (string) $rateLimitStatus->getRemainingAttempts())
68
            ->withHeader(self::HEADER_RESET, (string) $rateLimitStatus->getResetAt()->getTimestamp());
69
    }
70
}
71