php-http/throttle-plugin
PSR-7/PSR-18 HTTP client plugin that throttles outgoing requests to control rate and concurrency. Useful for API clients that must respect provider limits, avoid burst traffic, and smooth request flow.
Installation
composer require php-http/throttle-plugin
Ensure symfony/rate-limiter is also installed (dependency).
Basic Usage
use Http\Client\Common\Plugin\ThrottlePlugin;
use Symfony\Component\RateLimiter\RateLimiterFactory;
// Create a rate limiter (e.g., 10 requests per minute)
$rateLimiter = RateLimiterFactory::create(['10/minute']);
// Initialize the plugin
$throttlePlugin = new ThrottlePlugin($rateLimiter);
// Add to your HTTP client
$client = new \Http\Client\Common\PluginClient();
$client->addPlugin($throttlePlugin);
First Use Case Throttle API requests to avoid hitting rate limits:
$response = $client->sendRequest('GET', 'https://api.example.com/endpoint');
Centralized Throttling
$this->app->singleton(\Http\Client\Common\PluginClient::class, function ($app) {
$client = new \Http\Client\Common\PluginClient();
$client->addPlugin(new ThrottlePlugin(RateLimiterFactory::create(['10/minute'])));
return $client;
});
Dynamic Rate Limits
$limits = config('http.throttle');
$rateLimiter = RateLimiterFactory::create($limits['api.example.com']);
Retry Logic
Http\Client\Common\Plugin\RetryPlugin to retry throttled requests:
$client->addPlugin(new RetryPlugin());
$client->addPlugin($throttlePlugin);
Symfony\Component\RateLimiter\Storage\MemoryStorage for in-memory throttling (e.g., for testing).$throttlePlugin->onThrottled(function (Request $request, \DateInterval $wait) {
\Log::warning("Throttled: {$request->getUri()}. Retry after {$wait->s} seconds.");
});
Storage Backend
MemoryStorage is not persistent across requests. For distributed systems, use:
use Symfony\Component\RateLimiter\Storage\RedisStorage;
$storage = new RedisStorage(new \Redis());
$rateLimiter = RateLimiterFactory::create(['10/minute'], $storage);
Concurrency Issues
Plugin Order
ThrottlePlugin before other plugins that might modify requests (e.g., RetryPlugin).RateLimiterInterface::consume() to manually test limits:
$rateLimiter->consume(1)->wait(); // Simulate a request
onThrottled to log delays:
$throttlePlugin->onThrottled(function ($request, $wait) {
\Log::debug("Wait time: {$wait->s} seconds for {$request->getUri()}");
});
Symfony\Component\RateLimiter\RateLimiterInterface for custom logic (e.g., token buckets).ThrottlePlugin to trigger events before/after throttling:
$throttlePlugin->onBeforeThrottle(function ($request) {
// Pre-throttle logic
});
$client->addPlugin(new ThrottlePlugin(
RateLimiterFactory::create(['5/second'])
));
How can I help you explore Laravel packages today?