PHP Rate Limiting library with both Token Bucket and Leaky Bucket Algorithms, minimal external dependencies, and many storage backends.
-
Token Bucket Algorithm Token Bucket is an algorithm which works as follows:
- There is a bucket.
- A token is added to the bucket every 1/r seconds.
- The bucket can hold at the most b tokens. If a token arrives when the bucket is full, it is discarded.
- When a packet (network layer PDU) of n bytes arrives,
- If at least n tokens are in the bucket, n tokens are removed from the bucket, and the packet is sent to the network.
- if fewer than n tokens are available, no tokens are removed from the bucket, and the packet is considered to be non-conformant.
-
Leaky Bucket Algorithm Leaky Bucket is an algorithm which works as follows:
- There is a bucket.
- The bucket has a defined leak and defined capacity.
- The bucket leaks at a constant rate.
- Overflows when full, will not add other drops to the bucket.
The RateLimiter needs to know where to get/set data.
Depending on which adapter you install, you may need to install additional libraries (predis/predis or tedivm/stash) or PHP extensions (e.g. Redis, Memcache, APCu)
- APCu
- Redis or Predis
- Stash (This supports many drivers - see http://www.stashphp.com/Drivers.html )
- Memcached
curl -sS https://getcomposer.org/installer | php
composer.phar require detain/rate-limit
require 'vendor/autoload.php';
use \Detain\RateLimit\RateLimit;
use \Detain\RateLimit\Adapter\APCu as APCAdapter;
use \Detain\RateLimit\Adapter\Redis as RedisAdapter;
use \Detain\RateLimit\Adapter\Predis as PredisAdapter;
use \Detain\RateLimit\Adapter\Memcached as MemcachedAdapter;
use \Detain\RateLimit\Adapter\Stash as StashAdapter;
$adapter = new APCAdapter(); // Use APC as Storage
// Alternatives:
//
// $adapter = new RedisAdapter((new \Redis()->connect('localhost'))); // Use Redis as Storage
//
// $adapter = new PredisAdapter(new \Predis\Predis(['tcp://127.0.0.1:6379'])); // Use Predis as Storage
//
// $memcache = new \Memcached();
// $memcache->addServer('localhost', 11211);
// $adapter = new MemcacheAdapter($memcache);
//
// $stash = new \Stash\Pool(new \Stash\Driver\FileSystem());
// $adapter = new StashAdapter($stash);
$rateLimit = new RateLimit("myratelimit", 100, 3600, $adapter); // 100 Requests / Hour
$id = $_SERVER['REMOTE_ADDR']; // Use client IP as identity
if ($rateLimit->check($id)) {
echo "passed";
} else {
echo "rate limit exceeded";
}
<?php
use \Detain\RateLimit\LeakyBucket;
use \Detain\RateLimit\Adapter\Redis as RedisAdapter;
$adapter = new RedisAdapter((new \Redis()->connect('localhost'))); // Use Redis as Storage
// Define the bucket
$settings = [
'capacity' => 10,
'leak' => 1
];
// Create the bucket
$bucket = new LeakyBucket('example-bucket', $storage, $settings);
// Fill the bucket
$bucket->fill();
// Check if it's full
if ($bucket->isFull()) {
header('HTTP/1.1 429 Too Many Requests');
exit '<!doctype html><html><body><h1>429 Too Many Requests</h1><p>You seem to be doing a lot of requests. You\'re now cooling down.</p></body></html>';
}
// ...
You can also do great stuff with it through the methods that LeakyBucket provides.
// Get capacity information
$capacityTotal = $bucket->getCapacity();
$capacityLeft = $bucket->getCapacityLeft();
$capacityUsed = $bucket->getCapacityUsed();
// Get the drops/second that the bucket leaks
$leakPerSecond = $bucket->getLeak();
// Get the last timestamp from when the bucket was updated
$timestamp = $bucket->getLastTimestamp();
// Set additional data
$bucket->setData(
[
'timeout' => 3600
]
);
// Get additional data
$data = $bucket->getData();
// Update the bucket with the leaked drops
$bucket->leak();
// Remove excess drops
$bucket->overflow();
// Update the bucket's timestamp manually
$bucket->touch();
// Fill the bucket with one drop
$bucket->fill();
// Fill the bucket with 5 drops
$bucket->fill(5);
// Spill one drop from the bucket
$bucket->spill();
// Spill 5 drops from the bucket
$bucket->spill(5);
// Remove the bucket's content
$bucket->reset();
// Force save
$bucket->save();
- this code is forked from DavidGoodwin/RateLimit
- which was built on touhonoob/RateLimit
- and then i merged it with jeroenvisser101/LeakyBucket
- nikolaposa/rate-limit 🚔 Standalone component that facilitates rate-limiting functionality. Also provides a middleware designed for API and/or other application endpoints.
- robwittman/leaky-bucket-rate-limiter PSR-7 Leaky Bucket Rate Limiter - This middleware enables API Rate-Limiting based on a Leaky Bucket algorithm.