From c2864f65ab6cbca6b2bed5448f8af1908f822df1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 16 Dec 2019 23:02:54 +0100 Subject: [PATCH] [HttpClient] make pushed responses retry-able --- .../Component/HttpClient/CurlHttpClient.php | 42 ++++++++++--------- .../HttpClient/Internal/PushedResponse.php | 5 ++- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 683b08da461f..494bf76a1043 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -116,23 +116,6 @@ public function request(string $method, string $url, array $options = []): Respo $options['normalized_headers']['user-agent'][] = $options['headers'][] = 'User-Agent: Symfony HttpClient/Curl'; } - if ($pushedResponse = $this->multi->pushedResponses[$url] ?? null) { - unset($this->multi->pushedResponses[$url]); - - if (self::acceptPushForRequest($method, $options, $pushedResponse)) { - $this->logger && $this->logger->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url)); - - // Reinitialize the pushed response with request's options - $pushedResponse->response->__construct($this->multi, $url, $options, $this->logger); - - return $pushedResponse->response; - } - - $this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s".', $url)); - } - - $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url)); - $curlopts = [ CURLOPT_URL => $url, CURLOPT_TCP_NODELAY => true, @@ -267,7 +250,26 @@ public function request(string $method, string $url, array $options = []): Respo $curlopts[file_exists($options['bindto']) ? CURLOPT_UNIX_SOCKET_PATH : CURLOPT_INTERFACE] = $options['bindto']; } - $ch = curl_init(); + if ($pushedResponse = $this->multi->pushedResponses[$url] ?? null) { + unset($this->multi->pushedResponses[$url]); + + if (self::acceptPushForRequest($method, $options, $pushedResponse)) { + $this->logger && $this->logger->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url)); + + // Reinitialize the pushed response with request's options + $ch = $pushedResponse->handle; + $pushedResponse = $pushedResponse->response; + $pushedResponse->__construct($this->multi, $url, $options, $this->logger); + } else { + $this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s".', $url)); + $pushedResponse = null; + } + } + + if (!$pushedResponse) { + $ch = curl_init(); + $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url)); + } foreach ($curlopts as $opt => $value) { if (null !== $value && !curl_setopt($ch, $opt, $value) && CURLOPT_CERTINFO !== $opt) { @@ -279,7 +281,7 @@ public function request(string $method, string $url, array $options = []): Respo } } - return new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host)); + return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host)); } /** @@ -369,7 +371,7 @@ private static function handlePush($parent, $pushed, array $requestHeaders, Curl $url .= $headers[':path'][0]; $logger && $logger->debug(sprintf('Queueing pushed response: "%s"', $url)); - $multi->pushedResponses[$url] = new PushedResponse(new CurlResponse($multi, $pushed), $headers, $multi->openHandles[(int) $parent][1] ?? []); + $multi->pushedResponses[$url] = new PushedResponse(new CurlResponse($multi, $pushed), $headers, $multi->openHandles[(int) $parent][1] ?? [], $pushed); return CURL_PUSH_OK; } diff --git a/src/Symfony/Component/HttpClient/Internal/PushedResponse.php b/src/Symfony/Component/HttpClient/Internal/PushedResponse.php index 6f8e8fda3a6b..08fca60dcb96 100644 --- a/src/Symfony/Component/HttpClient/Internal/PushedResponse.php +++ b/src/Symfony/Component/HttpClient/Internal/PushedResponse.php @@ -29,10 +29,13 @@ final class PushedResponse public $parentOptions = []; - public function __construct(CurlResponse $response, array $requestHeaders, array $parentOptions) + public $handle; + + public function __construct(CurlResponse $response, array $requestHeaders, array $parentOptions, $handle) { $this->response = $response; $this->requestHeaders = $requestHeaders; $this->parentOptions = $parentOptions; + $this->handle = $handle; } }