sunspikes / php-ratelimiter
A framework agnostic rate limiter for PHP
Installs: 592 384
Dependents: 1
Suggesters: 0
Security: 0
Stars: 66
Watchers: 6
Forks: 12
Open Issues: 2
Requires
- php: >=5.5
- desarrolla2/cache: ~2.0
Requires (Dev)
- mockery/mockery: ^0.9.4
- phpunit/phpunit: ^4.7.6
- scrutinizer/ocular: ^1.1
This package is auto-updated.
Last update: 2024-12-02 09:44:58 UTC
README
A framework independent, flexible and highly extensible rate limiter for PHP.
Installation
With Composer
It is best installed it through packagist
by including sunspikes/php-ratelimiter
in your project composer.json require:
"require": { "sunspikes/php-ratelimiter": "dev-master" }
Without Composer
You can also download it from Github, but no autoloader is provided so you'll need to register it with your own PSR-4 compatible autoloader.
Usage
Overview
// 1. Make a rate limiter with limit 3 attempts in 10 minutes $cacheAdapter = new DesarrollaCacheAdapter((new DesarrollaCacheFactory())->make()); $settings = new ElasticWindowSettings(3, 600); $ratelimiter = new RateLimiter(new ThrottlerFactory($cacheAdapter), new HydratorFactory(), $settings); // 2. Get a throttler for path /login $loginThrottler = $ratelimiter->get('/login'); // 3. Register a hit $loginThrottler->hit() // 4. Check if it reached the limit if ($loginThrottler->check()) { // access permitted } else { // access denied } // Or combine the steps 3 & 4 if ($loginThrottler->access()) { // access permitted } else { // access denied } // To get the number of hits print $loginThrottler->count(); // or count($throttler)
Configuration
By default PHP Ratelimiter uses the desarolla2 cache adapter, the sample configuration provided in config/config.php
You can configure the drivers in config.php
, for example to use memcache change the driver to 'memcache'
return [ 'default_ttl' => 3600, 'driver' => 'memcache', 'memcache' => [ //.... ], ];
Extending
The PHP Ratelimiter is highly extensible, you can have custom adapters by implementing Sunspikes\Ratelimit\Cache\Adapter\CacheAdapterInterface
For example to use Doctrine cache adapter
class DoctrineCacheAdapter implements CacheAdapterInterface { public function __construct($cache) { $this->cache = $cache; } // Implement the methods } // Build adapter using APC cache driver $adapter = new DoctrineCacheAdapter(new \Doctrine\Common\Cache\ApcCache());
Also you can have custom hydrators by implementing Sunspikes\Ratelimit\Throttle\Hydrator\DataHydratorInterface
For example to use a Symfony Request object instead of custom URL for ratelimiting
class RequestHydrator implements DataHydratorInterface { public function hydrate($data, $limit, $ttl) { // Make the key string $key = $data->getClientIp() . $data->getPathInfo(); return new Data($key, $limit, $ttl); } } // Hydrate the request to Data object $hydrator = new RequestHydrator();
Then decorate or extend the HydratorFactory to recognize your data
use Hydrator\FactoryInterface; class MyHydratorFactory implements FactoryInterface { private $defaultFactory; public function __construct(FactoryInterface $defaultFactory) { $this->defaultFactory = $defaultFactory; } public function make($data) { if ($data instanceof Request) { return new RequestHydrator(); } return $this->defaultFactory->make($data); } }
Throttler types
Elastic Window
An elastic window throttler will allow X requests in Y seconds. Any further access attempts will be counted, but return false as status. Note that the window will be extended with Y seconds on every hit. This means there need to be no hits during Y seconds for the counter to be reset to 0.
See Overview example for instantiation.
Time-based throttlers
All the following throttlers use time functions, thus needing a different factory for construction:
$cacheAdapter = new DesarrollaCacheAdapter((new DesarrollaCacheFactory())->make()); $timeAdapter = new PhpTimeAdapter(); $throttlerFactory = new TimeAwareThrottlerFactory($cacheAdapter, $timeAdapter); $hydratorFactory = new HydratorFactory(); //$settings = ... $ratelimiter = new RateLimiter($throttlerFactory, $hydratorFactory, $settings);
Fixed Window
A fixed window throttler will allow X requests in the Y seconds since the first request. Any further access attempts will be counted, but return false as status. The window will not be extended at all.
// Make a rate limiter with limit 120 attempts per minute $settings = new FixedWindowSettings(120, 60);
Moving Window
A moving window throttler will allow X requests during the previous Y seconds. Any further access attempts will be counted, but return false as status. The window is never extended beyond Y seconds.
// Make a rate limiter with limit 120 attempts per minute $settings = new MovingWindowSettings(120, 60);
Leaky Bucket
A leaky bucket throttler will allow X requests divided over time Y.
Any access attempts past the threshold T (default: 0) will be delayed by Y / (X - T)
access()
will return false if delayed, hit()
will return the number of milliseconds waited
Note: Time limit for this throttler is in milliseconds, where it is seconds for the other throttler types!
// Make a rate limiter with limit 120 attempts per minute, start delaying after 30 requests $settings = new LeakyBucketSettings(120, 60000, 30);
Retrial Queue
The retrial queue encapsulates another throttler. When this throttler receives a hit which would fail on the internal throttler, the request is delayed until the internal throttler has capacity again.
// Make a leaky bucket ratelimiter which delays any overflow $settings = new RetrialQueueSettings(new LeakyBucketSettings(120, 60000, 120));
Author
Krishnaprasad MG [@sunspikes]
Contributing
Please feel free to send pull requests.
License
This is an open-sourced software licensed under the MIT license.