Skip to content

Commit edd14b7

Browse files
committed
适配 thinkphp 5.1
1 parent daa5bac commit edd14b7

File tree

9 files changed

+42
-74
lines changed

9 files changed

+42
-74
lines changed

README.md

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
### 作用
22
通过本中间件可限定用户在一段时间内的访问次数,可用于保护接口防爬防爆破的目的。
33

4+
## 环境要求
5+
TP 从 `5.1.6+` 版本开始才有中间件的支持,控制器中间件则需要 `5.1.17+`
6+
47
### 安装
58
```
6-
composer require topthink/think-throttle
9+
composer require topthink/think-throttle:^0.5.*
710
```
8-
安装后会自动为项目生成 `conf/throttle.php` 配置文件,安装后组件不会自动启用,需要手动设置。
911

1012
### 开启
11-
组件以中间件的方式进行工作,因此它的开启与其他中间件一样,例如在全局中间件中使用 `app/middleware.php` :
13+
组件以中间件的方式进行工作,因此它的开启与其他中间件一样,例如在全局中间件中使用 `application/middleware.php` :
1214
```
1315
<?php
1416
return [
1517
\think\middleware\Throttle::class,
1618
];
1719
```
1820
### 配置说明
19-
`config/throttle.php` 配置选项:
21+
创建 `config/throttle.php` 配置选项:
2022
```
2123
<?php
2224
// 中间件配置
@@ -83,30 +85,8 @@ Route::group(function() {
8385
```
8486

8587
## 更新日志
86-
版本 1.3.x 的配置形式完全兼容版本 1.2.x 内容,可以无缝升级,
87-
88-
版本 1.2.x 的配置形式完全兼容版本 1.1.x 内容,可以无缝升级。
89-
90-
### 1.3.x 更新
91-
- 可通过配置 `visit_fail_response` 自定义限流响应;
92-
- 速率限制信息对响应头状态码20x生效;
93-
- 强类型声明(有自行继承扩展的需注意);
94-
- 默认配置文件中去除 `visit_fail_code``visit_fail_text` 配置项,但代码中依然保留这两项配置的兼容;
95-
- 新增响应体中设置速率限制的头部信息的开关;
96-
- 配置文件添加设置算法驱动;
97-
- 支持在路由定义中设置中间件配置;
98-
- 修复漏桶算法中计算等待时间的错误问题;
99-
100-
### 1.2.x 更新
101-
- 可对要限制的请求类型进行自定义设置
102-
- 默认配置请求频率设置 '100/m'
88+
0.5.0 由 1.3.0 版本为适配 thinkphp 5.1 修改而来。`0.5.x` 版本将只做问题修复,不再添加新功能。
10389

104-
### 1.1.x 更新
105-
- 添加漏桶限流算法, 令牌桶算法, 计数固定窗口, 滑动窗口共四种限流策略;
106-
- 公共数据改为静态属性,节省内存分配;
107-
- 重构中间件接口,便于扩展更多的限流算法;
108-
- 默认策略使用计数固定窗口的策略;
109-
- 时间取毫秒,某些限流算法需要;
110-
- 只使用一个缓存键完成计数固定窗口,减少缓存读取;
111-
- 开放更多 `set*` 方法,支持链式操作;
112-
- 禁止访问时,改用抛出 `HttpResponseException`
90+
### 0.5.0 更新
91+
- 适配 thinkphp 5.1;
92+
- 适配 php 5.6;

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"name": "topthink/think-throttle",
33
"description": "throttle middleware for thinkphp6",
44
"require": {
5-
"php": ">=7.1.0",
6-
"topthink/framework": "^6.0.0"
5+
"php": ">=5.6.0",
6+
"topthink/framework": "^5.1.6"
77
},
88
"license": "Apache-2.0",
99
"authors": [

src/Throttle.php

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
<?php
22

3-
declare (strict_types = 1);
4-
53
namespace think\middleware;
64

75
use Closure;
8-
use Psr\SimpleCache\CacheInterface;
96
use think\Cache;
107
use think\Config;
118
use think\Container;
@@ -48,7 +45,7 @@ class Throttle
4845

4946
/**
5047
* 缓存对象
51-
* @var CacheInterface
48+
* @var Cache
5249
*/
5350
protected $cache;
5451

@@ -77,15 +74,15 @@ class Throttle
7774
public function __construct(Cache $cache, Config $config)
7875
{
7976
$this->cache = $cache;
80-
$this->config = array_merge(static::$default_config, $config->get('throttle', []));
77+
$this->config = array_merge(static::$default_config, $config->load('throttle', 'throttle'));
8178
}
8279

8380
/**
8481
* 请求是否允许
8582
* @param Request $request
8683
* @return bool
8784
*/
88-
protected function allowRequest(Request $request): bool
85+
protected function allowRequest(Request $request)
8986
{
9087
// 若请求类型不在限制内
9188
if (!in_array($request->method(), $this->config['visit_method'])) {
@@ -96,7 +93,7 @@ protected function allowRequest(Request $request): bool
9693
if (null === $key) {
9794
return true;
9895
}
99-
[$max_requests, $duration] = $this->parseRate($this->config['visit_rate']);
96+
list($max_requests, $duration) = $this->parseRate($this->config['visit_rate']);
10097

10198
$micronow = microtime(true);
10299
$now = (int) $micronow;
@@ -127,12 +124,8 @@ protected function allowRequest(Request $request): bool
127124
* @param array $params
128125
* @return Response
129126
*/
130-
public function handle(Request $request, Closure $next, array $params=[]): Response
127+
public function handle(Request $request, Closure $next)
131128
{
132-
if ($params) {
133-
$this->config = array_merge($this->config, $params);
134-
}
135-
136129
$allow = $this->allowRequest($request);
137130
if (!$allow) {
138131
// 访问受限
@@ -151,7 +144,7 @@ public function handle(Request $request, Closure $next, array $params=[]): Respo
151144
* @param Request $request
152145
* @return null|string
153146
*/
154-
protected function getCacheKey(Request $request): ?string
147+
protected function getCacheKey(Request $request)
155148
{
156149
$key = $this->config['key'];
157150

@@ -178,11 +171,11 @@ protected function getCacheKey(Request $request): ?string
178171
* @param string $rate
179172
* @return int[]
180173
*/
181-
protected function parseRate($rate): array
174+
protected function parseRate($rate)
182175
{
183-
[$num, $period] = explode("/", $rate);
176+
list($num, $period) = explode("/", $rate);
184177
$max_requests = (int) $num;
185-
$duration = static::$duration[$period] ?? (int) $period;
178+
$duration = isset(static::$duration[$period]) ? (int) static::$duration[$period] : (int) $period;
186179
return [$max_requests, $duration];
187180
}
188181

@@ -191,18 +184,18 @@ protected function parseRate($rate): array
191184
* @param string $rate '10/m' '20/300'
192185
* @return $this
193186
*/
194-
public function setRate(string $rate): self
187+
public function setRate($rate)
195188
{
196189
$this->config['visit_rate'] = $rate;
197190
return $this;
198191
}
199192

200193
/**
201194
* 设置缓存驱动
202-
* @param CacheInterface $cache
195+
* @param Cache $cache
203196
* @return $this
204197
*/
205-
public function setCache(CacheInterface $cache): self
198+
public function setCache(Cache $cache)
206199
{
207200
$this->cache = $cache;
208201
return $this;
@@ -213,7 +206,7 @@ public function setCache(CacheInterface $cache): self
213206
* @param string $class_name
214207
* @return $this
215208
*/
216-
public function setDriverClass(string $class_name): self
209+
public function setDriverClass($class_name)
217210
{
218211
$this->config['driver_name'] = $class_name;
219212
return $this;
@@ -223,7 +216,7 @@ public function setDriverClass(string $class_name): self
223216
* 获取速率限制头
224217
* @return array
225218
*/
226-
public function getRateLimitHeaders(): array
219+
public function getRateLimitHeaders()
227220
{
228221
return [
229222
'X-Rate-Limit-Limit' => $this->max_requests,
@@ -238,8 +231,8 @@ public function getRateLimitHeaders(): array
238231
* @param Request $request
239232
* @return HttpResponseException
240233
*/
241-
public function buildLimitException(int $wait_seconds, Request $request): HttpResponseException {
242-
$visitFail = $this->config['visit_fail_response'] ?? null;
234+
public function buildLimitException($wait_seconds, Request $request) {
235+
$visitFail = isset($this->config['visit_fail_response']) ? $this->config['visit_fail_response'] : null;
243236
if ($visitFail instanceof \Closure) {
244237
$response = Container::getInstance()->invokeFunction($visitFail, [$this, $request, $wait_seconds]);
245238
if (!$response instanceof Response) {

src/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
// 响应体中设置速率限制的头部信息,含义见:https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
2828
'visit_enable_show_rate_limit' => true,
2929
// 访问受限时返回的响应
30-
'visit_fail_response' => function (Throttle $throttle, Request $request, int $wait_seconds) {
30+
'visit_fail_response' => function (Throttle $throttle, Request $request, $wait_seconds) {
3131
return Response::create('Too many requests, try again after ' . $wait_seconds . ' seconds.')->code(429);
3232
},
3333
];

src/throttle/CounterFixed.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<?php
22

3-
43
namespace think\middleware\throttle;
54

6-
use Psr\SimpleCache\CacheInterface;
5+
use think\Cache;
76

87
/**
98
* 计数器固定窗口算法
@@ -13,7 +12,7 @@
1312
class CounterFixed extends ThrottleAbstract
1413
{
1514

16-
public function allowRequest(string $key, float $micronow, int $max_requests, int $duration, CacheInterface $cache): bool
15+
public function allowRequest($key, $micronow, $max_requests, $duration, Cache $cache)
1716
{
1817
$cur_requests = (int) $cache->get($key, 0);
1918
$now = (int) $micronow;

src/throttle/CounterSlider.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<?php
22

3-
43
namespace think\middleware\throttle;
54

6-
use Psr\SimpleCache\CacheInterface;
5+
use think\Cache;
76

87
/**
98
* 计数器滑动窗口算法
@@ -12,7 +11,7 @@
1211
*/
1312
class CounterSlider extends ThrottleAbstract
1413
{
15-
public function allowRequest(string $key, float $micronow, int $max_requests, int $duration, CacheInterface $cache): bool
14+
public function allowRequest($key, $micronow, $max_requests, $duration, Cache $cache)
1615
{
1716
$history = $cache->get($key, []);
1817
$now = (int) $micronow;

src/throttle/LeakyBucket.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<?php
22

3-
43
namespace think\middleware\throttle;
54

6-
use Psr\SimpleCache\CacheInterface;
5+
use think\Cache;
76

87
/**
98
* 漏桶算法
@@ -13,7 +12,7 @@
1312
class LeakyBucket extends ThrottleAbstract
1413
{
1514

16-
public function allowRequest(string $key, float $micronow, int $max_requests, int $duration, CacheInterface $cache): bool
15+
public function allowRequest($key, $micronow, $max_requests, $duration, Cache $cache)
1716
{
1817
if ($max_requests <= 0) return false;
1918

src/throttle/ThrottleAbstract.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
<?php
22

3-
43
namespace think\middleware\throttle;
54

65

7-
use Psr\SimpleCache\CacheInterface;
6+
use think\Cache;
87

98
abstract class ThrottleAbstract
109
{
@@ -19,16 +18,16 @@ abstract class ThrottleAbstract
1918
* @param float $micronow 当前时间戳,可含毫秒
2019
* @param int $max_requests 允许最大请求数
2120
* @param int $duration 限流时长
22-
* @param CacheInterface $cache 缓存对象
21+
* @param Cache $cache 缓存对象
2322
* @return bool
2423
*/
25-
abstract public function allowRequest(string $key, float $micronow, int $max_requests, int $duration, CacheInterface $cache): bool;
24+
abstract public function allowRequest($key, $micronow, $max_requests, $duration, Cache $cache);
2625

2726
/**
2827
* 计算距离下次合法请求还有多少秒
2928
* @return int
3029
*/
31-
public function getWaitSeconds(): int
30+
public function getWaitSeconds()
3231
{
3332
return (int) $this->wait_seconds;
3433
}
@@ -37,7 +36,7 @@ public function getWaitSeconds(): int
3736
* 当前已有的请求数
3837
* @return int
3938
*/
40-
public function getCurRequests(): int
39+
public function getCurRequests()
4140
{
4241
return (int) $this->cur_requests;
4342
}

src/throttle/TokenBucket.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<?php
22

3-
43
namespace think\middleware\throttle;
54

6-
use Psr\SimpleCache\CacheInterface;
5+
use think\Cache;
76

87
/**
98
* 令牌桶算法
@@ -12,7 +11,7 @@
1211
*/
1312
class TokenBucket extends ThrottleAbstract
1413
{
15-
public function allowRequest(string $key, float $micronow, int $max_requests, int $duration, CacheInterface $cache): bool
14+
public function allowRequest($key, $micronow, $max_requests, $duration, Cache $cache)
1615
{
1716
if ($max_requests <= 0 || $duration <= 0) return false;
1817

0 commit comments

Comments
 (0)