Code Monkey home page Code Monkey logo

ratelimitbundle's Introduction

NoxlogicRateLimitBundle

Build Status Code Coverage Scrutinizer Code Quality

Latest Stable Version Total Downloads Latest Unstable Version License

This bundle provides enables the #[RateLimit()] attribute which allows you to limit the number of connections to actions. This is mostly useful in APIs.

The bundle is prepared to work by default in cooperation with the FOSOAuthServerBundle. It contains a listener that adds the OAuth token to the cache-key. However, you can create your own key generator to allow custom rate limiting based on the request. See Create a custom key generator below.

This bundle is partially inspired by a GitHub gist from Ruud Kamphuis: https://gist.github.com/ruudk/3350405

Features

  • Simple usage through attributes
  • Customize rates per controller, action and even per HTTP method
  • Multiple storage backends: Redis, Memcached and Doctrine cache

Installation

Installation takes just few easy steps:

Step 1: Install the bundle using composer

If you're not yet familiar with Composer see http://getcomposer.org. Tell composer to download the bundle by running the command:

composer require noxlogic/ratelimit-bundle

Step 2: Enable the bundle

If you are using symfony/flex you can skip this step, the bundle will be enabled automatically, otherwise you need to enable the bundle by adding it to the bundles.php file of your project.

<?php // bundles.php

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

Step 3: Install a storage engine

Redis

If you want to use Redis as your storage engine, you might want to install SncRedisBundle:

Memcache

If you want to use Memcache, you might want to install LswMemcacheBundle

Doctrine cache

If you want to use Doctrine cache as your storage engine, you might want to install DoctrineCacheBundle:

Referer to their documentations for more details. You can change your storage engine with the storage_engine configuration parameter. See Configuration reference.

Configuration

Enable bundle only in production

If you wish to enable the bundle only in production environment (so you can test without worrying about limit in your development environments), you can use the enabled configuration setting to enable/disable the bundle completely. It's enabled by default:

# config_dev.yml
noxlogic_rate_limit:
    enabled: false

Configuration reference

This is the default bundle configuration:

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

Usage

Simple rate limiting

To enable rate limiting, you only need to add the attribute to the specified action

<?php

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

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

Limit per method

It's possible to rate-limit specific HTTP methods as well. This can be either a string or an array of methods. When no method argument is given, all other methods not defined are rated. This allows to add a default rate limit if needed.

<?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()
{
}

Limit per controller

It's also possible to add rate-limits to a controller class instead of a single action. This will act as a default rate limit for all actions, except the ones that actually defines a custom rate-limit.

<?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()
    {
    }
}

Create a custom key generator

NOTE

Note that this bundle by default does not perform rate-limiting based on user's IP. If you wish to enable IP-based rate limiting or any other strategy, custom key generators are the way to go.

If you need to create a custom key generator, you need to register a listener to listen to the ratelimit.generate.key event:

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
    }
}

Make sure to generate a key based on what is rate limited in your controllers.

And example of a IP-based key generator can be:

<?php

namespace MyBundle\Listener;

use Noxlogic\RateLimitBundle\Events\GenerateKeyEvent;

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

Throwing exceptions

Instead of returning a Response object when a rate limit has exceeded, it's also possible to throw an exception. This allows you to easily handle the rate limit on another level, for instance by capturing the kernel.exception event.

Running tests

If you want to run the tests use:

./vendor/bin/simple-phpunit

ratelimitbundle's People

Contributors

abarkine avatar albertofem avatar axi avatar danrspencer avatar demigodcode avatar goetas avatar jaytaph avatar jmclean avatar joshk avatar kdederichs avatar koesie10 avatar marcaube avatar mcfedr avatar merk avatar mhor avatar odoucet avatar pborreli avatar peshi avatar pierniq avatar sarelvdwalt avatar sharykhin avatar verifiednetwork avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ratelimitbundle's Issues

Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template::setOwner() must be of the type array, object given

Hello,
How can i know how many calls are still available for each user ?
because for me , when a client exseeds the rate, this error is shown;

{
  "code": 500,
  "message": "Catchable Fatal Error: Argument 1 passed to Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template::setOwner() must be of the type array, object given, called in C:\\wamp\\www\\VCycle_API\\app\\cache\\dev\\classes.php on line 7678 and defined"
}

for me i want to give 429 TOO MANY REQUESTS error as result in this case

Calls # not increasing after 2

I have setup a rate limit in the controller like:
@Ratelimit(methods={"POST", "GET"}, limit=100, period=10);

Using memcached storage engine which seems to be saving correctly the key. I am inspecting it with the following command: memcdump --servers=localhost

POST.GET.api.locations.cities.MY-OAUTH2-TOKEN-XYZ

But it seems the $info variable within the Service/Storage/Memcache.php is not getting modified in the upcoming API calls

Array
(
[limit] => 100
[calls] => 2
[reset] => 1532080555
)

I am always getting the same result.
Is there anything I am doing wrong ?

Cache key contains reserved characters aka IPv6 support

I'm using the following RateLimit for the Route of one of my controllers:
@RateLimit(methods={"PUT", "POST"}, limit=35, period=3600)

and use the following storage backend:

## config/services.yaml
    rate_limit_cache_storage:
        class: Symfony\Component\Cache\Simple\FilesystemCache
        arguments: ['ratelimit', 0, '%kernel.cache_dir%']

## config/packages/noxlogic_rate_limit.yaml
noxlogic_rate_limit:
    storage_engine: simple_cache
    simple_cache_service: rate_limit_cache_storage
    rate_response_code: 429
    rate_response_message: 'You exceeded the rate limit'

Sadly, once I started getting IPv6 flowing my controller started failing badly:

Uncaught PHP Exception Symfony\Component\Cache\Exception\InvalidArgumentException:
"Cache key "PUT.POST.api_foo.2800:xxx:yyyy:zzzz:d141:zzzz:xxx:yyyy" contains reserved characters "{}()/\@:"." at
vendor/symfony/cache/CacheItem.php line 177
{"exception":"[object] (Symfony\\Component\\Cache\\Exception\\InvalidArgumentException(code: 0): Cache key \"PUT.POST.api_foo.2800:xxx:yyyy:zzzz:d141:zzzz:xxx:yyyy\" contains reserved characters \"{}()/\\@:\". at vendor/symfony/cache/CacheItem.php:177)"} []

This is really bad because:

  1. This basically kept requests from fullfiling even though such an exceptions must have failed safely (A failure of the RateLimit is not something that must block normal processing!).
  2. I've no (simple) way to create filesystem-compatible cache-key for IPv6 without rolling a custom cache-key generator.

Global API limit

Hi,

How to make a global rate limit. I can only make it work using Controller annotation per method. Here is my config :
capture d ecran 2018-08-01 a 17 33 02

Thanks in advance,
Julien

Limit not working on login url

Hi, I've tried to prevent brute forcing by add limit to post login action but it looks like it ommit it? I've passed limit to other action and it looks ok..

security.yml

security:
    firewalls:
        main:
            pattern:    ^/
            provider: user
            security: true
            anonymous:  true
            switch_user: true
            form_login:
                check_path: login
                login_path: login
                failure_path:    /
                csrf_token_generator: security.csrf.token_manager
                use_referer: true
                success_handler: user_security.success_handler
                failure_handler: user_security.failure_handler

controller

/**
 * @RateLimit(limit=2, period=60)
 *
 * @Route("/login", name="login")
 * @param Request $request
 * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
 */
public function loginAction(Request $request)
{
	$authenticationUtils = $this->get('security.authentication_utils');

	// get the login error if there is one
	$error = $authenticationUtils->getLastAuthenticationError();

	// last username entered by the user
	$lastUsername = $authenticationUtils->getLastUsername();

	return $this->render(
		'Acme:Demo:login.html.twig',
		[
			'last_username' => $lastUsername,
			'login_error' => $error,
		]
	);
}

Creating custom exception class for RateLimitException Handling

After the exhaustion of API limit, exception is not coming to kernel.exception as mentioned in the docs. Instead of this custom message is throwing from the config.yml. I am using Symfony 3.4. Please can someone guide how to use custom exception class to handle the exception when the API limit will exhaust

Conflict with FrameworkExtraBundle

Hello,
I have a problem, when it exceeds the rate limit,
I have this error

message": "Catchable Fatal Error: Argument 1 passed to Sensio\Bundle\FrameworkExtraBundle\Configuration\Template::setOwner() must be of the type array, object given
do you have an idea how to fixe that ?

Symfony 3.0 support.

Adding symfony 3 support.

<argument type="service" id="security.context" />

was removed.

Bumping requirements for bundle or add a backward compability layer?

Remaining hits allowed reduced by seconds, not hits

I've applied the rate limiting according to the docs and using the snc-redis bundle and predis.
The config is the same as in the readme. I tested it in development and it worked fine but when it's been rolled out to production there is an issue - every time the api gets hit the number of remaining hits allowed does not reduce by one, it reduces by the number of seconds since the last hit.

This means that the period directive is defunct and the rate is as many hits as you like within 1000 seconds! (The annotation was limit=1000, period=3600)

The production machine is using redis for resque jobs which is not happening in development. Could this be causing a conflict?

Thanks.

Notice: Undefined index: limit

Hi, I have an error in RateLimitBundle/Service/Storage/Redis.php. When a new Rate is created, the time of its destruction is established.
2017-11-29 12 04 55

when a new request is made, the presence of this key in Redis is checked,

2017-11-29 12 06 34

and is called GetRateInfo, but at that point the key can be deleted, because the expire function was called earlier.

2017-11-29 12 07 11

So there is an error Notice: Undefined index: limit.

Thanks!

Symfony cache support?

Hi,

Just tried to install this bundle on new Symfony 5 project and got following error.

The service "noxlogic_rate_limit.rate_limit_annotation_listener" has a dependency on a non-existent service "snc_redis.default_client".

Thing is I'm using Symfony cache component and to install other cache abstraction packages (most of them are unsupported or deprecated) is not so convenient way to do.
Adding Symfony cache as dependency it would solve most of the problems.

Invalid Test Namespaces

The following Test classes aren't in the correct namespace:

As far as i can see, those could be moved without issue

Deprecation Notice: Class Noxlogic\RateLimitBundle\EventListener\Tests\RateLimitAnnotationListenerTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/RateLimitAnnotationListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\BaseListenerTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/BaseListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\GenerateKeyEventsTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/Events/GenerateKeyEventsTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\HeaderModificationListenerTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/HeaderModificationListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\MockListener located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/BaseListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\OauthKeyGenerateListenerTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/OauthKeyGenerateListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitEventsTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/Events/RateLimitEventsTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitInfoTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/Service/RateLimitInfoTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitInfoTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/Service/RateLimitInfoTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201
Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitServiceTest located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/Service/RateLimitServiceTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///usr/local/bin/composer/src/Composer/Autoload/ClassMapGenerator.php:201

update dependency sensio/framework-extra-bundle 6.*

sensio/framework-extra-bundle has been updated to 6.*, we can't update as long as dependency restriction is not fixed.

in composer.json

    "require": {
        "php": "^7.2",
        "symfony/framework-bundle": "^3.4|^4.3|^5.0",
        "sensio/framework-extra-bundle": "^3.0|^4.0|^5.0"
    },

should be

    "require": {
        "php": "^7.2",
        "symfony/framework-bundle": "^3.4|^4.3|^5.0",
        "sensio/framework-extra-bundle": "^3.0|^4.0|^5.0|^6.0"
    },

thanks

DoctrineCache doesn't check status upon saving, causing silent fail of rate limiting

We discovered this quite by accident.

Background: Using Doctrine Filesystem cache we implemented rate limiting in two places and wrote tests for both. One passed, the second failed only in Docker on our CI environment. In the end it turns out there is a slightly lower limit of the filename size there which meant the cache wasn't saved.

In DoctrineCache.php:48 there is the following code:

$this->client->save($key, $info, $period);

However, the client returns bool to indicate success or failure:

Doctrine\Common\Cache\Cache

     * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise.
     */
    public function save($id, $data, $lifeTime = 0);

Since this status is not checked, there is no rate limit stored, thus not applied, without any errors given to indicate as such. Since a test on this might pass on one environment and fail on another there is no sure way to know the rate limit is working everywhere (Except manually spamming the production version to see if it hits the limit).

In my opinion the DoctrineCache class should throw an Exception when the returned status is false.

'' must inherit the \Exception class

Hi,

I have a problem with this bundle. I'm trying to install it in my Symfony 4.1 project and getting this error while trying to clear cache:

In Configuration.php line 86:                        
  '' must inherit the \Exception class  

Here is my config:

noxlogic_rate_limit:
    enabled:              true

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

    # 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
    # Should be an instance of \Redis
    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:              ~
        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

Allow wildcard in path for path_limit

Currently, only method wildcard works [here]. As a feature request, we can add the functionality for allowing wildcard in path matches.

Example use-case: Rate limit all POST requests

If my request is valid, I can create the PR for it.

expiry is set to null

When testing this bundle with DoctrineCache - making requests too fast sets the expiry ("e") to null which results in a non-reversable block of the site unless cache / collection is cleared.
Tried apc, array, file_system, php_file and MongoDBCache with various results.

[question] Multiple simultaneate ratelimits of different periods per route

Are multiple periods supported?

   /**
     * Up to 15 per 5 minutes 
     * @RateLimit(methods={"PUT", "POST"}, limit=15, period=300)
     * But, still, no more than 100 per hour (instead of 180 otherwise)
     * @RateLimit(methods={"PUT", "POST"}, limit=100, period=3600)
     */
    public function fooPost() {}

If yes, then this would be valuable to add to the documentation.

Another side question which the documentation does not make clear is whether built-in Route annotation's method is considered.

Eg, with :

   /**
     * @Route(
     *     name="foo",
     *     path="/api/foo",
     *     methods={"POST"}
     * )
     * @RateLimit(limit=10, period=3600)
     */

... is the rate-limit automatically restricted to POST?

Mention #4

symfony recipe

I don't think this bundle has a Symfony flex recipe yet. Maybe it would be a nice idea to create one?

Addition of fail open

Good day,

We have added in an option to fail open if for any reason the limitRate function fails. For example server dies or network failure etc.

We have added this to the annotation to make the fail open dynamic.

If you could we would like your thoughts on the implementation and whether or not you would be willing to include the change in your version

here is the link to the branch

Brandon

Include Retry-After header in response

The RFC 6585 states that the HTTP 429 status response MAY include the Retry-After header to inform the client how much time it needs to wait before making another request.

Maybe there could be an option in the bundle configuration to add or not this header in the response sent to the client when it reaches the specified limit.

RateLimitBundle\Service\Storage\Redis expects Predis\Client injection

\Noxlogic\RateLimitBundle\Service\Storage\Redis::__construct() type-hints the constructor parameter to Predis\Client.

When using phpredis on the snc/SncRedisBundle (see the config below) the following exception is thrown:

ErrorException: Catchable Fatal Error: Argument 1 passed to Noxlogic\RateLimitBundle\Service\Storage\Redis::__construct() must be an instance of Predis\Client, instance of Snc\RedisBundle\Client\Phpredis\Client given, called in ...app/cache/dev/appDevDebugProjectContainer.php on line 5157 and defined in ...vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Service/Storage/Redis.php line 15

FYI the RateLimitBundle works if the type-hint on the constructor is removed, but a proper fix is needed. Will see if I have time to dig into it and come up with a clean solution as a PR.

snc/SncRedisBundle config:

snc_redis:
    clients:
        default:
            type: phpredis
            alias: default
            dsn: redis://localhost

Support PSR-6 Cache engines

PSR6 is just being accepted (at least the vote is happening now). Would be nice to be able to use PSR6 compliant cache engines with this bundle.

Custom RateLimitAnnotationListener?

What would be the best way to override the RateLimitAnnotationListener with a custom one to delegate the rate limit handler (onKernelController).
For example, in some case it would be handy to redirect to a specific controller instead of issuing a 429 error code

$event->setController(function () use ($message, $code) {
       // @codeCoverageIgnoreStart
       return new Response($message, $code);
       // @codeCoverageIgnoreEnd
});

Since the service "noxlogic_rate_limit.rate_limit_annotation_listener" is not using tags, should I

  • extend the RateLimitAnnotationListener and override the service definition
  • override the class definition %noxlogic_rate_limit.rate_limit_annotation_listener.class%

Or would it make sense to define a delegate handler like RateLimiteResponseService which would by default keep the current behaviour but could be overrided if necessary ?

Thanks for your advice,
Eric

could not set path_limits

after setting path,following error is thrown

Invalid type for path "noxlogic_rate_limit.path_limits.path". Expected array, but got string

noxlogic_rate_limit:
    enabled:    true
    storage_engine: "redis"
    redis_client:   default
    rate_response_code: 429
    rate_response_exception:    Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
    rate_response_message:  'You exceeded the rate limit'
    display_headers:    true
    headers:
        limit:  X-RateLimit-Limit
        remaining:  X-RateLimit-Remaining
        reset:  X-RateLimit-Reset
    # Rate limits for paths
    path_limits:
        path:   /api
        methods:
            # Default:
            - *
        limit:  10
        period: 60

Could anyone provide correct example for path_limits configuration
like for /api route and 10 limit for 60 seconds

must be an instance of Predis\\Client, instance of Redis given

Hi,

I Installed SncRedis and RateLimit with Symfony 5. When I try a route I have the error:

Argument 1 passed to Noxlogic\RateLimitBundle\Service\Storage\Redis::__construct() must be an instance of Predis\Client, instance of Redis given, called in /var/application/var/cache/dev/ContainerEdVmABd/App_KernelDevDebugContainer.php on line 8263

snc_redis.yaml

snc_redis:
    clients:
        default:
            type: phpredis
            alias: default
            dsn: "%env(REDIS_URL)%"`

noxlogic_rate_limit.yaml:

noxlogic_rate_limit:
    enabled: true
    redis_client: default
    storage_engine: redis
    php_redis_service: default

Should I configure something else?

Period not works, never resetting

Hi,

Im trying this bundle but i notice that never resetRate, i´ve been searching in code an method resetRate is never called.

Whats wrong?

Update readme documentation

The readme documentation still talks about manually adding the bundle to Composer, updating your app/appKernel.php

we should make sure the documentation is up-to-date with the latest Symfony/Composer practices.

Problems using memcache

In this Service class:

https://github.com/jaytaph/RateLimitBundle/blob/master/Service/Storage/Memcache.php#L13

In the constructor argument, the \Memcached instance is expected. But when installing the latest https://github.com/LeaseWeb/LswMemcacheBundle, the class does not implement \Memcached, but \MemcachePool. I tried using previous versions, but with all of them I had similar problems and was unable to make this bundle to work properly. Can I get any suggestions? I can make some PR if there is any chance it might be accepted.

Regards, Tomaz

Support new `EventDispatcherInterface`

From version 4.3.0, EventDispatcherInterface has changed: now the dispatch() method, instead of taking an event name as first parameter, and an event object as second, takes only the event object itself. There is a fallback for applications using event names, consisting in passing an optional second parameter as event name, but it's marked as deprecated.

https://github.com/symfony/event-dispatcher/blob/v4.3.2/EventDispatcherInterface.php
https://github.com/symfony/event-dispatcher-contracts/blob/master/EventDispatcherInterface.php

Configurable default rate-limit

Add default x-rate limit to config (like: rate-limiting an /api directory for instance)

For instance:

ratelimitbundle:
   default:
     path: /api
     method: GET
     limit: 100
     period: 60

[Bug] RateLimitBundle will not autoload anymore in Composer v2.0

Basic information

Current installed version: 1.15.1 via packagist.

Description

As stated in the title, the RateLimitBundle will not autoload anymore in Composer v2.0 because it does not comply with the psr-0 autoloading standard.

In our current installation we are getting the following error for different (mostly test) classes:

Deprecation Notice: Class Noxlogic\RateLimitBundle\Tests\Annotation\MockListener located in ./vendor/noxlogic/ratelimit-bundle/Noxlogic/RateLimitBundle/Tests/EventListener/BaseListenerTest.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///opt/sources/composer/composer/src/Composer/Autoload/ClassMapGenerator.php:201

The whole list in our case is:

  • Noxlogic\RateLimitBundle\Tests\Annotation\MockListener
  • Noxlogic\RateLimitBundle\Tests\Annotation\BaseListenerTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\HeaderModificationListenerTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\OauthKeyGenerateListenerTest
  • Noxlogic\RateLimitBundle\EventListener\Tests\MockController
  • Noxlogic\RateLimitBundle\EventListener\Tests\RateLimitAnnotationListenerTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\CheckedRateLimitEventsTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\GenerateKeyEventsTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitEventsTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitInfoTest
  • Noxlogic\RateLimitBundle\Tests\Annotation\RateLimitServiceTest

Possible fix

The easiest way to fix this is either to move the test classes to the respective directory or adapt the namespace.
If you want, I can hand in a pull request. But I first want to make sure the way you want to adapt this.

configuration by path with path_limits is not working

I don't understand why the limit path defined in the configuration is not working whereas it is working with annotation in the controller.

i set
path_limits: - { path: '^/api', limit: 1, period: 3600 }
and nothing in the header with an /api/* url :
image

whereas is it working with the controller if defined for a specific one :
image

Do you have an idea?

Allow Ip Range

Is it posible to add a Block of IP Range ? We want to prevent someone scan the web but allow google index us.

Thank you

I still have Lsw\MemcacheBundle\DataCollector\MemcacheDataCollector::addClient() must be an instance of Lsw\MemcacheBundle\Cache\LoggingMemcacheInterface, instance of Lsw\MemcacheBundle\Cache\AntiDogPileMemcache given

Hello,

I have try to use this bundle and add it to my project but I can't use it with memcach because I have the same error I seen in another issue
Lsw\MemcacheBundle\DataCollector\MemcacheDataCollector::addClient() must be an instance of Lsw\MemcacheBundle\Cache\LoggingMemcacheInterface, instance of Lsw\MemcacheBundle\Cache\AntiDogPileMemcache given
the problem is the only solution given is to change to cacheDoctrine which it use APC and I didn't want to use it and Redis is a paying solution.
Someone have maybe a fix or a way to correct this?
Maybe an alternative?

Thanks!

Just wanted to say Thank you.

Installed the bundle, configured it and installed redis, inserted the annotation on a rest endpoint...

Done! Just works!

Time spent: 15 minutes (mostly waiting stuff to be downloaded)

🎉 🎉 🎉

The service "noxlogic_rate_limit.storage" has a dependency on a non-existent service "snc_redis.default_client".

Hi, after updating from 1.7.0 to newer versions I've get an error when clearCache is called:

The service "noxlogic_rate_limit.storage" has a dependency on a non-existent service "snc_redis.default_client".

Bug starts from updating to 1.81. I don't need to snc bundle because im using doctrine_cache. My config looks ok and it's working fine now:

doctrine_cache:
    providers:
        memcached_cache:
            memcached:
                connection_id: memcached
        redis_cache:
            redis:
                connection_id: redis

noxlogic_rate_limit:
    enabled: true
    storage_engine: "doctrine"
    doctrine_provider: redis_cache
    rate_response_exception: Api\AppBundle\Exception\RateExceededException
    rate_response_code: 429
    rate_response_message: 'You exceeded the rate limit'
    display_headers: true
    headers:
        limit: X-RateLimit-Limit
        remaining: X-RateLimit-Remaining
        reset: X-RateLimit-Reset

Redis Reset ERR wrong number of arguments for 'hdel' command

Service/Storage/Redis.php::resetRate($myKey) is throwing an error:

ERR wrong number of arguments for 'hdel' command

I believe the problem is that the hdel command is for removing a field from the hash and not the whole key.

I think we should be calling the del command to remove the whole hash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.