noxlogic/ratelimit-bundle

此扩展包提供了基于速率限制限制操作调用功能

安装次数: 2,493,432

依赖: 8

建议者: 0

安全性: 0

星标: 331

关注者: 17

分支: 74

开放问题: 19

类型:symfony-bundle

2.0.0 2023-08-14 08:30 UTC

README

Build Status Code Coverage Scrutinizer Code Quality

Latest Stable Version Total Downloads Latest Unstable Version License

此扩展包提供启用#[RateLimit()]属性,允许您限制对操作的连接数。这在API中非常有用。

默认情况下,该扩展包已准备好与FOSOAuthServerBundle协同工作。它包含一个监听器,该监听器将OAuth令牌添加到缓存键中。但是,您可以根据请求创建自己的键生成器,以允许基于请求的自定义速率限制。请参阅下面的创建自定义键生成器

此扩展包部分灵感来源于Ruud Kamphuis在GitHub上的一个gist:https://gist.github.com/ruudk/3350405

特性

  • 通过属性简单使用
  • 按控制器、操作甚至按HTTP方法自定义速率
  • 多种存储后端:Redis、Memcached和Doctrine缓存

安装

安装只需几个简单步骤

步骤 1:使用composer安装扩展包

如果您还不熟悉Composer,请参阅 https://getcomposer.org.cn。通过运行以下命令让Composer下载扩展包:

composer require noxlogic/ratelimit-bundle

步骤 2:启用扩展包

如果您正在使用symfony/flex,您可以跳过此步骤,扩展包将自动启用。否则,您需要将扩展包添加到您项目的bundles.php文件中,以启用扩展包。

<?php // bundles.php

return [
    // ..
    Noxlogic\RateLimitBundle\NoxlogicRateLimitBundle::class => ['all' => true],
    // ..
];

步骤 3:安装存储引擎

Redis

如果您想使用Redis作为存储引擎,您可能需要安装SncRedisBundle

Memcache

如果您想使用Memcache,您可能需要安装LswMemcacheBundle

Doctrine缓存

如果您想使用Doctrine缓存作为存储引擎,您可能需要安装DoctrineCacheBundle

请参阅它们的文档以获取更多详细信息。您可以使用storage_engine配置参数更改存储引擎。请参阅配置参考

配置

仅在生产环境中启用扩展包

如果您只想在生产环境中启用扩展包(这样您可以在开发环境中测试而不用担心限制),您可以使用enabled配置设置完全启用/禁用扩展包。默认情况下已启用

# config_dev.yml
noxlogic_rate_limit:
    enabled: false

配置参考

这是默认的扩展包配置

noxlogic_rate_limit:
    enabled:              true

    # The storage engine where all the rates will be stored
    storage_engine:       ~ # One of "redis"; "memcache"; "doctrine"; "php_redis"; "php_redis_cluster"

    # The redis client to use for the redis storage engine
    redis_client:         default_client
    
    # The Redis service, use this if you dont use SncRedisBundle and want to specify a service to use
    # Should be instance of \Predis\Client
    redis_service:    null # Example: project.predis

    # The Redis client to use for the php_redis storage engine
    # Depending on storage_engine an instance of \Redis or \RedisCluster
    php_redis_service:    null # Example: project.redis

    # The memcache client to use for the memcache storage engine
    memcache_client:      default
    
    # The Memcached service, use this if you dont use LswMemcacheBundle and want to specify a service to use
    # Should be instance of \Memcached
    memcache_service:    null # Example: project.memcached

    # The Doctrine Cache provider to use for the doctrine storage engine
    doctrine_provider:    null # Example: my_apc_cache
    
    # The Doctrine Cache service, use this if you dont use DoctrineCacheBundle and want to specify a service to use
    # Should be an instance of \Doctrine\Common\Cache\Cache
    doctrine_service:    null # Example: project.my_apc_cache

    # The HTTP status code to return when a client hits the rate limit
    rate_response_code:   429

    # Optional exception class that will be returned when a client hits the rate limit
    rate_response_exception:  null

    # The HTTP message to return when a client hits the rate limit
    rate_response_message:  'You exceeded the rate limit'

    # Should the ratelimit headers be automatically added to the response?
    display_headers:      true

    # What are the different header names to add
    headers:
        limit:                X-RateLimit-Limit
        remaining:            X-RateLimit-Remaining
        reset:                X-RateLimit-Reset

    # Rate limits for paths
    path_limits:
        path:                 ~ # Required
        methods:

            # Default:
            - *
        limit:                ~ # Required
        period:               ~ # Required
        
    # - { path: /api, limit: 1000, period: 3600 }
    # - { path: /dashboard, limit: 100, period: 3600, methods: ['GET', 'POST']}

    # Should the FOS OAuthServerBundle listener be enabled 
    fos_oauth_key_listener: true

用法

简单的速率限制

要启用速率限制,您只需将属性添加到指定的操作

<?php

use Noxlogic\RateLimitBundle\Attribute\RateLimit;
use Symfony\Component\Routing\Annotation\Route;

#[Route(...)]
#[RateLimit(limit: 1000, period: 3600)]
public function someApiAction()
{
}

按方法限制

您还可以对特定的HTTP方法进行速率限制。这可以是字符串或方法的数组。如果没有指定方法参数,则对未定义的其他方法进行评级。这允许添加默认速率限制,如果需要的话。

<?php

use Noxlogic\RateLimitBundle\Attribute\RateLimit;
use Symfony\Component\Routing\Annotation\Route;

#[Route(...)]
#[RateLimit(methods: ["PUT", "POST"], limit: 1000, period: 3600)]
#[RateLimit(methods: ["GET"], limit: 1000, period: 3600)]
#[RateLimit(limit: 5000, period: 3600)]
public function someApiAction()
{
}

按控制器限制

您还可以将速率限制添加到控制器类,而不是单个操作。这将作为所有操作的默认速率限制,除非实际定义了自定义速率限制。

<?php

use Noxlogic\RateLimitBundle\Attribute\RateLimit;
use Symfony\Component\Routing\Annotation\Route;

#[RateLimit(methods: ["POST"], limit: 100, period: 10)] // 100 POST requests per 10 seconds
class DefaultController extends Controller
{
    #[RateLimit(methods: ["POST"], limit: 200, period: 10)] // 200 POST requests to indexAction allowed.
    public function indexAction()
    {
    }
}

创建自定义键生成器

注意

请注意,此套餐默认情况下不会基于用户IP进行速率限制。如果您想启用基于IP的速率限制或其他策略,自定义密钥生成器是最佳选择。

如果您需要创建自定义密钥生成器,您需要注册一个监听器来监听 ratelimit.generate.key 事件

services:
    mybundle.listener.rate_limit_generate_key:
        class: MyBundle\Listener\RateLimitGenerateKeyListener
        tags:
            - { name: kernel.event_listener, event: 'ratelimit.generate.key', method: 'onGenerateKey' }
<?php

namespace MyBundle\Listener;

use Noxlogic\RateLimitBundle\Events\GenerateKeyEvent;

class RateLimitGenerateKeyListener
{
    public function onGenerateKey(GenerateKeyEvent $event)
    {
        $key = $this->generateKey();

        $event->addToKey($key);
        // $event->setKey($key); // to overwrite key completely
    }
}

确保根据您的控制器中速率限制的内容生成密钥。

以下是一个基于IP的密钥生成器示例:

<?php

namespace MyBundle\Listener;

use Noxlogic\RateLimitBundle\Events\GenerateKeyEvent;

class IpBasedRateLimitGenerateKeyListener
{
    public function onGenerateKey(GenerateKeyEvent $event)
    {
        $request = $event->getRequest();
        $event->addToKey($request->getClientIp());
    }
}

抛出异常

当速率限制超出时,除了返回一个响应对象之外,还可以抛出一个异常。这允许您在另一级别轻松处理速率限制,例如通过捕获 kernel.exception 事件。

运行测试

如果您想运行测试,请使用

./vendor/bin/simple-phpunit