• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

miaoxing / services / 12451995076

22 Dec 2024 06:23AM UTC coverage: 5.115% (-0.05%) from 5.16%
12451995076

push

github

twinh
feat(services): `RateLimit` 支持操作返回错误时才增加计数器

0 of 11 new or added lines in 1 file covered. (0.0%)

29 of 567 relevant lines covered (5.11%)

1.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Middleware/RateLimit.php
1
<?php
2

3
namespace Miaoxing\Services\Middleware;
4

5
use Miaoxing\Plugin\Service\Ret;
6

7
/**
8
 * 限制用户在一段请求时间内(如每分钟,每小时,每天)最多的请求次数
9
 *
10
 * @mixin \UserPropMixin
11
 * @mixin \CounterPropMixin
12
 */
13
class RateLimit extends BaseMiddleware
14
{
15
    /**
16
     * 每分钟作为一个时间窗口
17
     */
18
    public const MINUTE = 60;
19

20
    /**
21
     * 每小时作为一个时间窗口
22
     */
23
    public const HOUR = 3600;
24

25
    /**
26
     * 每天作为一个时间窗口
27
     */
28
    public const DAY = 86400;
29

30
    /**
31
     * 一个时间窗口的长度
32
     *
33
     * @var int
34
     */
35
    protected $timeWindow;
36

37
    /**
38
     * 在一个时间窗口内,最多请求的次数
39
     *
40
     * @var int
41
     */
42
    protected $max;
43

44
    /**
45
     * 超出请求次数返回的提示信息
46
     *
47
     * @var string
48
     */
49
    protected $responseText;
50

51
    /**
52
     * 操作返回错误时才增加计数器
53
     *
54
     * @var bool
55
     */
56
    protected $incrOnErr = false;
57

58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function __invoke($next)
62
    {
63
        $key = 'rate-limit' . $this->getIdentifier() . '-' . (int) (time() / $this->timeWindow);
×
64

NEW
65
        if ($this->incrOnErr) {
×
66
            // 先检查是否超过
NEW
67
            if ($this->counter->get($key) >= $this->max) {
×
NEW
68
                return $this->buildErr();
×
69
            }
70

71
            // 不超过才运行
NEW
72
            $ret = $next();
×
73

74
            // 运行错误才计数
NEW
75
            if ($ret instanceof Ret && $ret->isErr()) {
×
NEW
76
                $this->counter->incr($key);
×
77
            }
NEW
78
            return $ret;
×
79
        }
80

81
        // 先计数,超过则返回错误,不执行操作
NEW
82
        if ($this->counter->incr($key) > $this->max) {
×
NEW
83
            return $this->buildErr();
×
84
        }
85

86
        return $next();
×
87
    }
88

89
    /**
90
     * 获取客户端唯一标识
91
     *
92
     * @return string
93
     */
94
    public function getIdentifier()
95
    {
NEW
96
        return $this->user->id() ?: $this->req->getIp();
×
97
    }
98

99
    protected function buildErr(): Ret
100
    {
NEW
101
        return err($this->responseText ?: '您的操作太频繁,请稍候再试', -2003);
×
102
    }
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc