[HttpClient] fix race condition when reading response with informational status

This commit is contained in:
Nicolas Grekas 2019-09-24 19:56:24 +02:00
parent 1ccc970469
commit 450c3c4998
4 changed files with 13 additions and 5 deletions

View File

@ -355,7 +355,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface
*/
private static function acceptPushForRequest(string $method, array $options, PushedResponse $pushedResponse): bool
{
if ($options['body'] || $method !== $pushedResponse->requestHeaders[':method'][0]) {
if ('' !== $options['body'] || $method !== $pushedResponse->requestHeaders[':method'][0]) {
return false;
}

View File

@ -121,15 +121,17 @@ final class CurlResponse implements ResponseInterface
if (\in_array($waitFor, ['headers', 'destruct'], true)) {
try {
self::stream([$response])->current();
foreach (self::stream([$response]) as $chunk) {
if ($chunk->isFirst()) {
break;
}
}
} catch (\Throwable $e) {
// Persist timeouts thrown during initialization
$response->info['error'] = $e->getMessage();
$response->close();
throw $e;
}
} elseif ('content' === $waitFor && ($response->multi->handlesActivity[$response->id][0] ?? null) instanceof FirstChunk) {
self::stream([$response])->current();
}
curl_setopt($ch, CURLOPT_HEADERFUNCTION, null);

View File

@ -65,7 +65,11 @@ final class NativeResponse implements ResponseInterface
}
if (null === $response->remaining) {
self::stream([$response])->current();
foreach (self::stream([$response]) as $chunk) {
if ($chunk->isFirst()) {
break;
}
}
}
};
}

View File

@ -45,6 +45,8 @@ switch ($vars['REQUEST_URI']) {
header('HTTP/1.1 103 Early Hints');
header('Link: </style.css>; rel=preload; as=style', false);
header('Link: </script.js>; rel=preload; as=script', false);
flush();
usleep(1000);
echo "HTTP/1.1 200 OK\r\n";
echo "Date: Fri, 26 May 2017 10:02:11 GMT\r\n";
echo "Content-Length: 13\r\n";