csarrazi / CsaGuzzleBundle

A bundle integrating Guzzle >=4.0 in Symfony
250 stars 76 forks source link

How register a retry middleware? #256

Closed fernandops26 closed 4 years ago

fernandops26 commented 4 years ago

How I can to specify a retry middleware using the yaml file?

Currently I have this config:

csa_guzzle:
    ...
    clients:
        myClient:
            config:
                ...
                lazy: true
                verify: true
            middleware: ['request_middleware', 'renew_middleware']
services:
    app.retry_middleware:
        class: \Closure
        factory: ['Ghs\Application\Guzzle\RenewTokenMiddleware', 'requestMiddleware']
        tags: [{ name: csa_guzzle.middleware, alias: renew_middleware, priority: 100 }]

I need to set a new access token when the request response is 401, so I want to use a retry middleware to do it.

andreicio commented 4 years ago

I can show you how I integrated sainsburys/guzzle-oauth2-plugin that plugs in both before the request is made and on failure, and a simple custom auth plugin Relevant bits from various files:

csa_guzzle.yaml:

csa_guzzle:
    clients:
        hub:
            config:
                base_uri: '%env(HUB_DOMAIN)%'
                auth: oauth2
            middleware: ['oauth2_before', 'oauth2_failure']
        netopia:
            config:
                base_uri: 'https://www.web2sms.ro'
                timeout: 20
            middleware: ['netopia_auth']

services.yaml:

guzzle.oauth2.before:
    class: Closure
    factory: App\Services\HUB\Oauth2MiddlewareFactory:onBefore
    arguments: ['@hub.oauth2.middleware']
    tags: [{ name: "csa_guzzle.middleware", alias: "oauth2_before", priority: "100" }]
guzzle.oauth2.failure:
    class: Closure
    factory: App\Services\HUB\Oauth2MiddlewareFactory:onFailure
    arguments: ['@hub.oauth2.middleware']
    tags: [{ name: "csa_guzzle.middleware", alias: "oauth2_failure", priority: "100" }]

guzzle.middleware.netopia:
    class: App\Services\Netopia\NetopiaAuthorizationMiddleware
    arguments: [ '%netopia.secret%' ]
    tags: [{ name: "csa_guzzle.middleware", alias: "netopia_auth", priority: "100" }]

The factory:

use Sainsburys\Guzzle\Oauth2\Middleware\OAuthMiddleware;

class Oauth2MiddlewareFactory
{

    public static function onBefore(OAuthMiddleware $middleware)
    {
        return $middleware->onBefore();
    }

    public static function onFailure(OAuthMiddleware $middleware, int $retryLimit = 5)
    {
        return $middleware->onFailure($retryLimit);
    }
}

The other plugin:

use Psr\Http\Message\RequestInterface;

/**
 * Class NetopiaAuthorizationMiddleware
 */
class NetopiaAuthorizationMiddleware
{
    /**
     * @var string
     */
    private $secret;

    /**
     * NetopiaAuthorizationMiddleware constructor.
     *
     * @param string $secret
     */
    public function __construct(string $secret)
    {
        $this->secret = $secret;
    }

    /**
     * @param callable $handler
     * @return \Closure
     */
    public function __invoke(callable $handler)
    {
        return function (RequestInterface $request, array $options) use ($handler) {
            $jsonBody = $request->getBody();
            $data = json_decode($jsonBody, true);
            $hashParamOrder = [
                $data['apiKey'],
                $data['nonce'],
                $request->getMethod(),
                $request->getUri()->getPath(),
                $data['sender'],
                $data['recipient'],
                $data['message'],
                $data['visibleMessage'] ?? null,
                $data['scheduleDatetime'] ?? null,
                $data['validityDatetime'] ?? null,
                $data['callbackUrl'] ?? null,
                $this->secret,
            ];
            $string = implode('', $hashParamOrder);
            $signature = hash('sha512', $string);
            $authorization = 'Basic '.base64_encode($data['apiKey'].':'.$signature);

            return $handler($request->withAddedHeader('Authorization', $authorization), $options);
        };
    }
}

Hope it helps both you any anyone who needs a Netopia Web2SMS auth middleware :)

csarrazi commented 4 years ago

Indeed. You could also try the Tolerance middleware, which I believe is able to handle retries, with different strategies.

csarrazi commented 4 years ago

FYI: https://tolerance.readthedocs.io/en/latest/bridges/symfony-bundle/guzzle.html