muffin / throttle
(API) 在 CakePHP 中限制请求速率
Requires
- cakephp/cakephp: ^5.0.0
Requires (Dev)
- cakephp/cakephp-codesniffer: ^5.0
- phpunit/phpunit: ^10.1.0
This package is auto-updated.
Last update: 2024-09-23 10:38:22 UTC
README
(API) 在 CakePHP 中限制请求速率
此插件允许您限制客户端在指定时间段内对您的应用程序发起的请求数量。
安装
composer require muffin/throttle
要使您的应用程序加载此插件,可以运行
./bin/cake plugin load Muffin/Throttle
配置
在您的 config/app.php
文件中,在 Cache
键下添加一个名为 throttle
的缓存配置,并包含所需的配置。例如:
'throttle' => [ 'className' => 'Apcu', 'prefix' => 'throttle_' ],
使用中间件
将中间件添加到队列中,并传递您的自定义配置
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { // Various other middlewares for error handling, routing etc. added here. $throttleMiddleware = new \Muffin\Throttle\Middleware\ThrottleMiddleware([ // Data used to generate response with HTTP code 429 when limit is exceeded. 'response' => [ 'body' => 'Rate limit exceeded', ], // Time period as number of seconds 'period' => 60, // Number of requests allowed within the above time period 'limit' => 100, // Client identifier 'identifier' => function ($request) { if (!empty($request->getHeaderLine('Authorization'))) { return str_replace('Bearer ', '', $request->getHeaderLine('Authorization')); } return $request->clientIp(); } ]); $middlewareQueue->add($throttleMiddleware); return $middlewareQueue; }
上面的示例将允许每个token每分钟100个请求,并且首先尝试通过JWT Bearer token识别客户端,然后回退到基于IP地址的识别。
事件
中间件还触发以下事件,这实际上允许您拥有多个速率限制
Throttle.beforeThrottle
这是在中间件处理请求之前首先触发的事件。如果停止此事件,则所有速率限制过程都将绕过。
\Cake\Event\EventManager::instance()->on( \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_THROTTLE, function ($event, $request) { if (/* check for something here, most likely using $request */) { $event->stopPropagation(); } } );
Throttle.getIdentifier
除了使用 identifier
配置之外,您还可以为 Throttle.getIdentifier
事件设置监听器。事件的回调函数将接收一个请求实例作为参数,并必须返回一个标识符字符串。
Throttle.getThrottleInfo
Throttle.getThrottleInfo
事件允许您为请求自定义 period
和 limit
配置,以及用于存储速率限制信息的缓存键。
这允许您根据应用程序的需求设置多个速率限制。
以下是一个示例
\Cake\Event\EventManager::instance()->on( \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_GET_THROTTLE_INFO, function ($event, $request, \Muffin\Throttle\ValueObject\ThrottleInfo $throttle) { // Set a different period for POST request. if ($request->is('POST')) { // This will change the cache key from default "{identifer}" to "{identifer}.post". $throttle->appendToKey('post'); $throttle->setPeriod(30); } // Modify limit for logged in user $identity = $request->getAttribute('identity'); if ($identity) { $throttle->appendToKey($identity->get('role')); $throttle->setLimit(200); } } );
Throtttle.beforeCacheSet
Throtttle.beforeCacheSet
事件允许您观察中间件配置的结果以及之前 Throtttle.getIdentifier
和 Throttle.getThrottleInfo
事件的输出。
您还可以使用此事件修改缓存的 $rateLimit
和 $ttl
值,在此事件中修改 $throttleInfo
无效。
示例
\Cake\Event\EventManager::instance()->on( \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_CACHE_SET, function ($event, \Muffin\Throttle\ValueObject\RateLimitInfo $rateLimit, int $ttl, \Muffin\Throttle\ValueObject\ThrottleInfo $throttleInfo) { \Cake\Log\Log::debug(sprintf("key(%s) remaining(%d) resetTimestamp(%d) ttl(%d)", $throttleInfo->getKey(), $rateLimit->getRemaining(), $rateLimit->getResetTimestamp(), $ttl)); } );
X-headers
默认情况下,Throttle 将向所有响应添加包含速率限制信息的X-headers
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1438434161
要自定义头部名称,只需在配置数组中的 headers
键下传递(所有)它们即可
'headers' => [ 'limit' => 'X-MyRateLimit-Limit', 'remaining' => 'X-MyRateLimit-Remaining', 'reset' => 'X-MyRateLimit-Reset', ]
要禁用头部,将 headers
键设置为 false
。
自定义响应对象
如果您想返回不同的消息而不是默认消息,可以使用 response
数组的 type
和 headers
子键(就像使用 Response
对象一样)。
new \Muffin\Throttle\Middleware\ThrottleMiddleware([ 'response' => [ 'body' => json_encode(['error' => 'Rate limit exceeded']), 'type' => 'json', 'headers' => [ 'Custom-Header' => 'custom_value', ] ], 'limit' => 300, ]);
补丁 & 功能
- 分支
- 修改、修复
- 测试 - 这很重要,所以不要无意中将其破坏
- 提交 - 不要修改许可证、todo、版本等(如果您更改了它们,请将它们放入自己的提交中,这样我拉取时可以忽略它们)
- 拉取请求 - 主题分支将获得额外积分
为确保您的PR被考虑,您必须遵循 CakePHP 编码标准。
错误 & 反馈
http://github.com/usemuffin/throttle/issues
许可证
版权所有 (c) 2015-现在,[Use Muffin] 并许可于 MIT 许可证。