Completed
Push — master ( d162d5...c2b5c8 )
by Razon
05:19 queued 03:32
created

BaseRateLimiter   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
eloc 28
c 1
b 0
f 0
dl 0
loc 90
rs 10
ccs 25
cts 25
cp 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getLogger() 0 7 2
A init() 0 9 2
A getName() 0 12 3
A beforeAction() 0 12 2
1
<?php
2
namespace RazonYang\Yii2\RateLimiter;
3
4
use yii\base\Action;
5
use yii\filters\RateLimiter;
6
use yii\web\IdentityInterface;
7
use yii\web\Request;
8
use yii\web\TooManyRequestsHttpException;
9
use yii\web\User;
10
use Psr\Log\LoggerInterface;
11
use RazonYang\TokenBucket\ManagerInterface;
12
use RazonYang\Yii2\Psr\Log\Logger;
13
use Yii;
14
15
abstract class BaseRateLimiter extends RateLimiter
16
{
17
    /**
18
     * @var User $user
19
     */
20
    public $user;
21
22
    /**
23
     * @var int $capacity token bucket capacity.
24
     */
25
    public $capacity = 5000;
26
27
    /**
28
     * @var float $rate token rate.
29
     */
30
    public $rate = 0.72;
31
32
    /**
33
     * @var \Closure $nameCallback bucket name callback.
34
     */
35
    public $nameCallback;
36
37
    /**
38
     * @var int $limitPeriod calculates the maximum count of requests during the period.
39
     */
40
    public $limitPeriod = 3600;
41
42
    /**
43
     * @var ManagerInterface $manager
44
     */
45
    private $manager;
46
47 10
    public function init()
48
    {
49 10
        parent::init();
50
51 10
        if ($this->user === null) {
52 10
            $this->user = Yii::$app->getUser();
53
        }
54
55 10
        $this->manager = $this->initManager();
56 10
    }
57
58
    abstract protected function initManager(): ManagerInterface;
59
60 1
    public function beforeAction($action)
61
    {
62 1
        $limit = $this->manager->getLimit($this->limitPeriod);
63
64 1
        $name = $this->getName($this->user, $this->request, $action);
65 1
        $comsumed = $this->manager->consume($name, $remaining, $reset);
66 1
        $this->addRateLimitHeaders($this->response, $limit, $remaining, $reset);
67 1
        if (!$comsumed) {
68 1
            throw new TooManyRequestsHttpException($this->errorMessage);
69
        }
70
71 1
        return true;
72
    }
73
74
    /**
75
     * @param User $user
76
     * @param Request $request
77
     * @param Action $action
78
     */
79 3
    public function getName(User $user, Request $request, Action $action): string
80
    {
81 3
        if ($this->nameCallback !== null) {
82 1
            return call_user_func($this->nameCallback, $user, $request, $action);
83
        }
84
85 2
        $route = $action->getUniqueId();
86 2
        if (!$user->getIsGuest()) {
87 1
            return $user->getId() . ':' . $route;
88
        }
89
90 2
        return $request->getUserIP() . ':' . $route;
91
    }
92
93
    /**
94
     * @var LoggerInterface
95
     */
96
    private $logger;
97
98 10
    protected function getLogger(): LoggerInterface
99
    {
100 10
        if ($this->logger === null) {
101 10
            $this->logger = new Logger();
102
        }
103
        
104 10
        return $this->logger;
105
    }
106
}
107