Как изменить GET параметры в Guzzle middleware?

Как можно автоматизировать повторный запрос с изменением одного параметра, когда получены ошибочные HTTP-статусы с библиотеку Guzzle в PHP?
  • 14 июля 2024 г. 11:12
Ответы на вопрос 2
Для изменения GET параметров в Guzzle middleware можно использовать метод "setQuery" объекта Request. Пример кода:

```php
use GuzzleHttp\Client;

$client = new Client();

// создаем объект запроса
$request = $client->get('http://example.com', [
    'query' => ['param1' => 'value1']
]);

// изменяем GET параметры
$newParams = ['param2' => 'value2'];
$request = $request->setQuery($newParams);

// отправляем запрос
$response = $client->send($request);
```

Для автоматизации повторного запроса с изменением одного параметра при получении ошибочных HTTP-статусов, можно использовать middleware Guzzle. Пример кода:

```php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\ResponseInterface;

$client = new Client();

$handler = HandlerStack::create();

$errorHandler = function (callable $handler) {
    return function ($request, array $options) use ($handler) {
        return $handler($request, $options)->then(function (ResponseInterface $response) use ($handler) {
            if ($response->getStatusCode() >= 400) {
                $uri = $request->getUri();
                $query = $uri->getQuery();
                $newParams = ['param2' => 'value2'];

                $newRequest = $request->withUri($uri->withQuery(http_build_query($newParams)));
                
                return $handler($newRequest, $options);
            }
            return $response;
        });
    };
};

$handler->push(Middleware::mapRequest($errorHandler));

$client = new Client(['handler' => $handler]);

$response = $client->get('http://example.com');
```

Этот код добавляет middleware, которое будет перехватывать ответы с ошибочными HTTP-статусами и менять один из GET параметров перед повторной отправкой запроса.
C чистым <code>Middleware::retry</code> вы не решите задачу. Но можете скопировать класс <code>GuzzleHttp\RetryMiddleware</code> к себе в проект и подправить метод doRetry: <br/> <br/> <pre><code class="php">private function doRetry(RequestInterface $request, array $options, ?ResponseInterface $response = null): PromiseInterface
    {
        $options['delay'] = ($this-&gt;delay)(++$options['retries'], $response, $request);

        $uri = $request-&gt;getUri();
        $query = $uri-&gt;getQuery();
        // делаете какие нужно изменения в query
        $request = $request-&gt;withUri($uri-&gt;withQuery($query));

        return $this($request, $options);
    }</code></pre> <br/> <br/> А дальше добавляете в стек: <br/> <br/> <pre><code class="php">public function addRetryMiddleware($maxRetries)
    {
        $retryMiddleware = fn($handler) =&gt; new MyCustomRetryMiddleware(
            function (
                $retries,
                RequestInterface $request,
                ResponseInterface $response = null,
                TransferException $exception = null
            ) use ($maxRetries) {
                if ($retries &gt;= $maxRetries) {
                    return false;
                }
    
                if ($exception instanceof TransferException || ($response &amp;&amp; $response-&gt;getStatusCode() &gt;= 500)) {
                    return true;
                }
    
                return false;
            },
            $handler,
            function ($retries) {
                return $retries * 1000;
            }
        );
    
        $this-&gt;handlerStack-&gt;push($retryMiddleware);
    }</code></pre>
Похожие вопросы