eforce / throttle
(API) 在 CakePHP 中限制请求速率
Requires
- cakephp/cakephp: ^3.0
Requires (Dev)
- cakephp/cakephp-codesniffer: ~3.3
- phpunit/phpunit: ~5.7.14
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; }
上面的示例将允许每分钟/令牌100次请求,并首先尝试通过 JWT Bearer 令牌识别客户端,然后回退到基于 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->stopPropogation(); } } );
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); } } );
Throttle.beforeCacheSet
Throttle.beforeCacheSet
事件允许您观察中间件配置以及先前 Throttle.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 许可证 下许可。