Package Data | |
---|---|
Maintainer Username: | Chroma91 |
Maintainer Contact: | chroma91@gmail.com (Timo) |
Package Create Date: | 2018-01-27 |
Package Last Update: | 2021-09-21 |
Home Page: | |
Language: | PHP |
License: | MIT |
Last Refreshed: | 2024-04-26 03:02:55 |
Package Statistics | |
---|---|
Total Downloads: | 32,543 |
Monthly Downloads: | 138 |
Daily Downloads: | 12 |
Total Stars: | 129 |
Total Watchers: | 7 |
Total Forks: | 17 |
Total Open Issues: | 1 |
A Guzzle middleware that can throttle requests according to (multiple) defined rules.
It is also possible to define a caching strategy, e.g. get the response from cache when the rate limit is exceeded or always get a cached value to spare your rate limits.
Using wildcards in host names is also supported.
You have to use the v2 branch
if you are using Laravel or any Illuminate component below version 5.7
.
Via Composer
$ composer require hamburgscleanest/guzzle-advanced-throttle
Let's say you wanted to implement the following rules:
20 requests every 1 seconds
100 requests every 2 minutes
hamburgscleanest\GuzzleAdvancedThrottle\RequestLimitRuleset
:$rules = new RequestLimitRuleset([
'https://www.google.com' => [
[
'max_requests' => 20,
'request_interval' => 1
],
[
'max_requests' => 100,
'request_interval' => 120
]
]
]);
Make sure the host name does not end with a trailing slash. It should
be https://www.google.com
not https://www.google.com/
.
$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
hamburgscleanest\GuzzleAdvancedThrottle\Middleware\ThrottleMiddleware
to the stack.It should always be the first middleware on the stack.
$throttle = new ThrottleMiddleware($rules);
// Invoke the middleware
$stack->push($throttle());
// OR: alternatively call the handle method directly
$stack->push($throttle->handle());
$client = new Client(['base_uri' => 'https://www.google.com', 'handler' => $stack]);
Either the base_uri
has to be the same as the defined host in the rules array or you have to request absolute URLs for the middleware to have an effect.
// relative
$response = $client->get('test');
// absolute
$response = $client->get('https://www.google.com/test');
Responses with an error status code 4xx
or 5xx
will not be cached (even with force-cache
enabled)!
array
(default)Works out of the box. However it does not persist
anything.
This one will only work within the same scope.
It's set as a default because it doesn't need extra configuration.
The recommended adapter is the laravel
one.
laravel
(Illuminate/Cache) - recommendedYou need to provide a config (Illuminate\Config\Repository
) for this adapter.
custom
(Implements hamburgscleanest\GuzzleAdvancedThrottle\Cache\Interfaces\StorageInterface
)When you create a new implementation, pass the class name to the RequestLimitRuleset::create
method.
You'll also need to implement any sort of configuration parsing your instance needs.
Please see LaravelAdapter
for an example.
$rules = new RequestLimitRuleset(
[ ... ],
'force-cache', // caching strategy
MyCustomAdapter::class // storage adapter
);
$throttle = new ThrottleMiddleware($rules);
// Invoke the middleware
$stack->push($throttle());
These values can be set for every adapter.
'cache' => [
'ttl' => 900, // How long should responses be cached for (in seconds)?
'allow_empty' => true // When this is set to false, empty responses won't be cached.
]
'cache' => [
'driver' => 'file',
'options' => [
'path' => './cache'
],
...
]
'cache' => [
'driver' => 'redis',
'options' => [
'database' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
],
]
],
...
]
'cache' => [
'driver' => 'memcached',
'options' => [
'servers' => [
[
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 100,
],
]
],
...
]
$rules = new RequestLimitRuleset(
[ ... ],
'cache', // caching strategy
'laravel', // storage adapter
new Repository(require '../config/laravel-guzzle-limiter.php') // config repository
);
The same adapter will be used to store the internal request timers.
$rules = new RequestLimitRuleset(
[ ... ],
'cache', // caching strategy
'array' // storage adapter
);
no-cache
Just throttle the requests. No caching is done. When the limit is exceeded, a 429 - Too Many Requests
exception will be thrown.
$rules = new RequestLimitRuleset(
[ ... ],
'no-cache', // caching strategy
'array' // storage adapter
);
cache
Use cached responses when your defined rate limit is exceeded. The middleware will try to fallback to a cached response before throwing 429 - Too Many Requests
.
$rules = new RequestLimitRuleset(
[ ... ],
'cache', // caching strategy
'array' // storage adapter
);
force-cache
Always use cached responses when available to spare your rate limits.
As long as there is a response in cache for the current request it will return the cached response.
It will only actually send the request when it is not cached.
If there is no cached response and the request limits are exceeded, it will throw 429 - Too Many Requests
.
You might want to disable the caching of empty responses with this option (see General Driver Settings).
$rules = new RequestLimitRuleset(
[ ... ],
'force-cache', // caching strategy
'array' // storage adapter
);
Your custom caching strategy must implement CacheStrategy
.
It is suggested you use Cacheable
for a parent class.
This will give a good head start, see ForceCache
and Cache
for ideas.
To use your custom caching strategy, you'll need to pass the fully qualified cache name to RequestLimitRuleset
.
$rules = new RequestLimitRuleset([ ... ],
MyCustomCacheStrategy::class,
'array',
new Repository(...));
$throttle = new ThrottleMiddleware($rules);
...
If you want to define the same rules for multiple different hosts, you can use wildcards. A possible use case can be subdomains:
$rules = new RequestLimitRuleset([
'https://www.{subdomain}.mysite.com' => [
[
'max_requests' => 50,
'request_interval' => 2
]
]
]);
This host
will match https://www.en.mysite.com
, https://www.de.mysite.com
, https://www.fr.mysite.com
, etc.
Please see CHANGELOG for more information on what has changed recently.
$ composer test
Please see CONTRIBUTING and CODE_OF_CONDUCT for details.
If you discover any security related issues, please email chroma91@gmail.com instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.