Skip to content

Use RateLimiter to build a GuzzleRateLimiter middleware #40504

Closed
@kdefives

Description

@kdefives

Description
Seems the new feature RateLimiter has been designed to limit the number of request that is coming to an application (inbound). What do you think to use this new feature to control the RateLimit for http request outbound? In order to never reach the rate limit when we are calling an external API which limit the number of request per second, per minute...

Example
I had the idea to use that because existing rate limiter middleware for Guzzle (i.e. https://github.com/spatie/guzzle-rate-limiter-middleware) does not manage "shared rate limiter" across several processes running in same time in parallel. Seems symfony/rate-limiter manages that natively. I tested and seems it works but I would like feedback from experts :-).

The code of the RateLimiterMiddleware for guzzle:

<?php
namespace App\GuzzleMiddleware\RateLimiterMiddleware;
use Closure;
use Psr\Http\Message\RequestInterface;
use Symfony\Component\RateLimiter\RateLimiterFactory;
class RateLimiter
{
    /** @var RateLimiterFactory */
    protected $guzzleRateLimiter;
    /**
     * RateLimiter constructor.
     * @param RateLimiterFactory $guzzleRateLimiter
     */
    public function __construct(RateLimiterFactory $guzzleRateLimiter)
    {
        $this->guzzleRateLimiter = $guzzleRateLimiter;
    }
    /**
     * @param callable $handler
     * @return Closure
     */
    public function __invoke(callable $handler): Closure
    {
        return function (RequestInterface $request, array $options) use ($handler) {
            $limiter = $this->guzzleRateLimiter->create('custom-guzzle-rate-limiter');
            while(!$limiter->consume()->isAccepted()){
                sleep(1);
            }
            return $handler($request, $options);
        };
    }
}

How to add the middleware to guzzle (inside services.yaml:

GuzzleMiddleware\GuzzleLimiterMiddleware\RateLimiter:
        class: App\GuzzleMiddleware\RateLimiterMiddleware\RateLimiter

    GuzzleHttp\HandlerStack:
        class: GuzzleHttp\HandlerStack
        factory: [ 'GuzzleHttp\HandlerStack', create ]
        calls:
            - [ push, [ '@log_middleware', 'log' ] ]
            - [ push, [ '@GuzzleMiddleware\GuzzleLimiterMiddleware\RateLimiter' ] ]

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions