[HttpClient] Convert CurlHttpClient::handlePush() to instance method

Fix #37252
This commit is contained in:
Mikko Pesari 2020-06-17 11:19:44 +03:00
parent 943c630a94
commit 9497972500

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\HttpClient;
use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpClient\Exception\InvalidArgumentException; use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
use Symfony\Component\HttpClient\Exception\TransportException; use Symfony\Component\HttpClient\Exception\TransportException;
use Symfony\Component\HttpClient\Internal\CurlClientState; use Symfony\Component\HttpClient\Internal\CurlClientState;
@ -71,7 +70,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions); [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
} }
$this->multi = $multi = new CurlClientState(); $this->multi = new CurlClientState();
self::$curlVersion = self::$curlVersion ?? curl_version(); self::$curlVersion = self::$curlVersion ?? curl_version();
// Don't enable HTTP/1.1 pipelining: it forces responses to be sent in order // Don't enable HTTP/1.1 pipelining: it forces responses to be sent in order
@ -95,10 +94,8 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
return; return;
} }
$logger = &$this->logger; curl_multi_setopt($this->multi->handle, CURLMOPT_PUSHFUNCTION, function ($parent, $pushed, array $requestHeaders) use ($maxPendingPushes) {
return $this->handlePush($parent, $pushed, $requestHeaders, $maxPendingPushes);
curl_multi_setopt($this->multi->handle, CURLMOPT_PUSHFUNCTION, static function ($parent, $pushed, array $requestHeaders) use ($multi, $maxPendingPushes, &$logger) {
return self::handlePush($parent, $pushed, $requestHeaders, $multi, $maxPendingPushes, $logger);
}); });
} }
@ -361,7 +358,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
$this->reset(); $this->reset();
} }
private static function handlePush($parent, $pushed, array $requestHeaders, CurlClientState $multi, int $maxPendingPushes, ?LoggerInterface $logger): int private function handlePush($parent, $pushed, array $requestHeaders, int $maxPendingPushes): int
{ {
$headers = []; $headers = [];
$origin = curl_getinfo($parent, CURLINFO_EFFECTIVE_URL); $origin = curl_getinfo($parent, CURLINFO_EFFECTIVE_URL);
@ -373,7 +370,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
} }
if (!isset($headers[':method']) || !isset($headers[':scheme']) || !isset($headers[':authority']) || !isset($headers[':path'])) { if (!isset($headers[':method']) || !isset($headers[':scheme']) || !isset($headers[':authority']) || !isset($headers[':path'])) {
$logger && $logger->debug(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin)); $this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin));
return CURL_PUSH_DENY; return CURL_PUSH_DENY;
} }
@ -384,21 +381,21 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
// but this is a MUST in the HTTP/2 RFC; let's restrict pushes to the original host, // but this is a MUST in the HTTP/2 RFC; let's restrict pushes to the original host,
// ignoring domains mentioned as alt-name in the certificate for now (same as curl). // ignoring domains mentioned as alt-name in the certificate for now (same as curl).
if (0 !== strpos($origin, $url.'/')) { if (0 !== strpos($origin, $url.'/')) {
$logger && $logger->debug(sprintf('Rejecting pushed response from "%s": server is not authoritative for "%s"', $origin, $url)); $this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": server is not authoritative for "%s"', $origin, $url));
return CURL_PUSH_DENY; return CURL_PUSH_DENY;
} }
if ($maxPendingPushes <= \count($multi->pushedResponses)) { if ($maxPendingPushes <= \count($this->multi->pushedResponses)) {
$fifoUrl = key($multi->pushedResponses); $fifoUrl = key($this->multi->pushedResponses);
unset($multi->pushedResponses[$fifoUrl]); unset($this->multi->pushedResponses[$fifoUrl]);
$logger && $logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl)); $this->logger && $this->logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl));
} }
$url .= $headers[':path'][0]; $url .= $headers[':path'][0];
$logger && $logger->debug(sprintf('Queueing pushed response: "%s"', $url)); $this->logger && $this->logger->debug(sprintf('Queueing pushed response: "%s"', $url));
$multi->pushedResponses[$url] = new PushedResponse(new CurlResponse($multi, $pushed), $headers, $multi->openHandles[(int) $parent][1] ?? [], $pushed); $this->multi->pushedResponses[$url] = new PushedResponse(new CurlResponse($this->multi, $pushed), $headers, $this->multi->openHandles[(int) $parent][1] ?? [], $pushed);
return CURL_PUSH_OK; return CURL_PUSH_OK;
} }