muffin/throttle

(API) 在 CakePHP 中限制请求速率

安装次数: 186794

依赖: 0

建议者: 0

安全: 0

星标: 63

关注者: 5

分支: 13

类型:cakephp-plugin

3.0.0 2023-09-23 08:43 UTC

This package is auto-updated.

Last update: 2024-09-23 10:38:22 UTC


README

Build Status Coverage Status Total Downloads License

(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 事件允许您为请求自定义 periodlimit 配置,以及用于存储速率限制信息的缓存键。

这允许您根据应用程序的需求设置多个速率限制。

以下是一个示例

\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.getIdentifierThrottle.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 数组的 typeheaders 子键(就像使用 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 许可证