[HttpClient] Fix decorating progress info in AsyncResponse

This commit is contained in:
Jérémy Derussé 2020-10-19 18:27:34 +02:00 committed by Fabien Potencier
parent 6987862d97
commit e325f51fe2
6 changed files with 40 additions and 4 deletions

View File

@ -2097,7 +2097,7 @@ class FrameworkExtension extends Extension
$container
->register($name.'.retryable', RetryableHttpClient::class)
->setDecoratedService($name, null, -10) // lower priority than TraceableHttpClient
->setDecoratedService($name, null, 10) // higher priority than TraceableHttpClient
->setArguments([new Reference($name.'.retryable.inner'), $retryStrategy, $options['max_retries'], new Reference('logger')])
->addTag('monolog.logger', ['channel' => 'http_client']);
}

View File

@ -98,6 +98,7 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol
$errorCount = 0;
$baseInfo = [
'response_headers' => 1,
'retry_count' => 1,
'redirect_count' => 1,
'redirect_url' => 1,
'user_data' => 1,
@ -152,6 +153,11 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol
$content = [];
}
if (isset($info['retry_count'])) {
$content['retries'] = $info['previous_info'];
unset($info['previous_info']);
}
$debugInfo = array_diff_key($info, $baseInfo);
$info = ['info' => $debugInfo] + array_diff_key($info, $debugInfo) + $content;
unset($traces[$i]['info']); // break PHP reference used by TraceableHttpClient

View File

@ -151,6 +151,12 @@ final class AsyncContext
public function replaceRequest(string $method, string $url, array $options = []): ResponseInterface
{
$this->info['previous_info'][] = $this->response->getInfo();
if (null !== $onProgress = $options['on_progress'] ?? null) {
$thisInfo = &$this->info;
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
$onProgress($dlNow, $dlSize, $thisInfo + $info);
};
}
return $this->response = $this->client->request($method, $url, ['buffer' => false] + $options);
}

View File

@ -43,6 +43,13 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface
{
$this->client = $client;
$this->shouldBuffer = $options['buffer'] ?? true;
if (null !== $onProgress = $options['on_progress'] ?? null) {
$thisInfo = &$this->info;
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
$onProgress($dlNow, $dlSize, $thisInfo + $info);
};
}
$this->response = $client->request($method, $url, ['buffer' => false] + $options);
$this->passthru = $passthru;
$this->initializer = static function (self $response) {

View File

@ -66,7 +66,6 @@ class RetryableHttpClient implements HttpClientInterface
}
} catch (TransportExceptionInterface $exception) {
// catch TransportExceptionInterface to send it to the strategy
$context->setInfo('retry_count', $retryCount);
}
if (null !== $exception) {
// always retry request that fail to resolve DNS
@ -91,8 +90,6 @@ class RetryableHttpClient implements HttpClientInterface
}
}
} elseif ($chunk->isFirst()) {
$context->setInfo('retry_count', $retryCount);
if (false === $shouldRetry = $this->strategy->shouldRetry($context, null, null)) {
$context->passthru();
yield $chunk;
@ -138,6 +135,7 @@ class RetryableHttpClient implements HttpClientInterface
'delay' => $delay,
]);
$context->setInfo('retry_count', $retryCount);
$context->replaceRequest($method, $url, $options);
$context->pause($delay / 1000);

View File

@ -263,4 +263,23 @@ class AsyncDecoratorTraitTest extends NativeHttpClientTest
$this->assertSame('{"documents":[{"id":"\/json\/1"},{"id":"\/json\/2"},{"id":"\/json\/3"}]}', $content);
}
public function testInfoPassToDecorator()
{
$lastInfo = null;
$options = ['on_progress' => function (int $dlNow, int $dlSize, array $info) use (&$lastInfo) {
$lastInfo = $info;
}];
$client = $this->getHttpClient(__FUNCTION__, function (ChunkInterface $chunk, AsyncContext $context) use ($options) {
$context->setInfo('foo', 'test');
$context->getResponse()->cancel();
$context->replaceRequest('GET', 'http://localhost:8057/', $options);
$context->passthru();
});
$client->request('GET', 'http://localhost:8057')->getContent();
$this->assertArrayHasKey('foo', $lastInfo);
$this->assertSame('test', $lastInfo['foo']);
$this->assertArrayHasKey('previous_info', $lastInfo);
}
}