Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4966c75

Browse filesBrowse files
arjenmnicolas-grekas
authored andcommitted
[HttpClient] Lazily initialize CurlClientState
1 parent c6506c4 commit 4966c75
Copy full SHA for 4966c75

File tree

Expand file treeCollapse file tree

2 files changed

+44
-21
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+44
-21
lines changed

‎src/Symfony/Component/HttpClient/CurlHttpClient.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/CurlHttpClient.php
+42-19Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
5050
*/
5151
private $logger;
5252

53+
private $maxHostConnections;
54+
private $maxPendingPushes;
55+
5356
/**
5457
* An internal object to share state between the client and its responses.
5558
*
@@ -70,18 +73,22 @@ public function __construct(array $defaultOptions = [], int $maxHostConnections
7073
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\CurlHttpClient" as the "curl" extension is not installed.');
7174
}
7275

76+
$this->maxHostConnections = $maxHostConnections;
77+
$this->maxPendingPushes = $maxPendingPushes;
78+
7379
$this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']);
7480

7581
if ($defaultOptions) {
7682
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
7783
}
78-
79-
$this->multi = new CurlClientState($maxHostConnections, $maxPendingPushes);
8084
}
8185

8286
public function setLogger(LoggerInterface $logger): void
8387
{
84-
$this->logger = $this->multi->logger = $logger;
88+
$this->logger = $logger;
89+
if (isset($this->multi)) {
90+
$this->multi->logger = $logger;
91+
}
8592
}
8693

8794
/**
@@ -91,6 +98,8 @@ public function setLogger(LoggerInterface $logger): void
9198
*/
9299
public function request(string $method, string $url, array $options = []): ResponseInterface
93100
{
101+
$multi = $this->ensureState();
102+
94103
[$url, $options] = self::prepareRequest($method, $url, $options, $this->defaultOptions);
95104
$scheme = $url['scheme'];
96105
$authority = $url['authority'];
@@ -161,25 +170,25 @@ public function request(string $method, string $url, array $options = []): Respo
161170
}
162171

163172
// curl's resolve feature varies by host:port but ours varies by host only, let's handle this with our own DNS map
164-
if (isset($this->multi->dnsCache->hostnames[$host])) {
165-
$options['resolve'] += [$host => $this->multi->dnsCache->hostnames[$host]];
173+
if (isset($multi->dnsCache->hostnames[$host])) {
174+
$options['resolve'] += [$host => $multi->dnsCache->hostnames[$host]];
166175
}
167176

168-
if ($options['resolve'] || $this->multi->dnsCache->evictions) {
177+
if ($options['resolve'] || $multi->dnsCache->evictions) {
169178
// First reset any old DNS cache entries then add the new ones
170-
$resolve = $this->multi->dnsCache->evictions;
171-
$this->multi->dnsCache->evictions = [];
179+
$resolve = $multi->dnsCache->evictions;
180+
$multi->dnsCache->evictions = [];
172181
$port = parse_url($authority, \PHP_URL_PORT) ?: ('http:' === $scheme ? 80 : 443);
173182

174183
if ($resolve && 0x072A00 > CurlClientState::$curlVersion['version_number']) {
175184
// DNS cache removals require curl 7.42 or higher
176-
$this->multi->reset();
185+
$multi->reset();
177186
}
178187

179188
foreach ($options['resolve'] as $host => $ip) {
180189
$resolve[] = null === $ip ? "-$host:$port" : "$host:$port:$ip";
181-
$this->multi->dnsCache->hostnames[$host] = $ip;
182-
$this->multi->dnsCache->removals["-$host:$port"] = "-$host:$port";
190+
$multi->dnsCache->hostnames[$host] = $ip;
191+
$multi->dnsCache->removals["-$host:$port"] = "-$host:$port";
183192
}
184193

185194
$curlopts[\CURLOPT_RESOLVE] = $resolve;
@@ -281,16 +290,16 @@ public function request(string $method, string $url, array $options = []): Respo
281290
$curlopts += $options['extra']['curl'];
282291
}
283292

284-
if ($pushedResponse = $this->multi->pushedResponses[$url] ?? null) {
285-
unset($this->multi->pushedResponses[$url]);
293+
if ($pushedResponse = $multi->pushedResponses[$url] ?? null) {
294+
unset($multi->pushedResponses[$url]);
286295

287296
if (self::acceptPushForRequest($method, $options, $pushedResponse)) {
288297
$this->logger && $this->logger->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url));
289298

290299
// Reinitialize the pushed response with request's options
291300
$ch = $pushedResponse->handle;
292301
$pushedResponse = $pushedResponse->response;
293-
$pushedResponse->__construct($this->multi, $url, $options, $this->logger);
302+
$pushedResponse->__construct($multi, $url, $options, $this->logger);
294303
} else {
295304
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s"', $url));
296305
$pushedResponse = null;
@@ -300,7 +309,7 @@ public function request(string $method, string $url, array $options = []): Respo
300309
if (!$pushedResponse) {
301310
$ch = curl_init();
302311
$this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url));
303-
$curlopts += [\CURLOPT_SHARE => $this->multi->share];
312+
$curlopts += [\CURLOPT_SHARE => $multi->share];
304313
}
305314

306315
foreach ($curlopts as $opt => $value) {
@@ -310,7 +319,7 @@ public function request(string $method, string $url, array $options = []): Respo
310319
}
311320
}
312321

313-
return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host), CurlClientState::$curlVersion['version_number']);
322+
return $pushedResponse ?? new CurlResponse($multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host), CurlClientState::$curlVersion['version_number']);
314323
}
315324

316325
/**
@@ -324,9 +333,11 @@ public function stream($responses, ?float $timeout = null): ResponseStreamInterf
324333
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of CurlResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
325334
}
326335

327-
if (\is_resource($this->multi->handle) || $this->multi->handle instanceof \CurlMultiHandle) {
336+
$multi = $this->ensureState();
337+
338+
if (\is_resource($multi->handle) || $multi->handle instanceof \CurlMultiHandle) {
328339
$active = 0;
329-
while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($this->multi->handle, $active)) {
340+
while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($multi->handle, $active)) {
330341
}
331342
}
332343

@@ -335,7 +346,9 @@ public function stream($responses, ?float $timeout = null): ResponseStreamInterf
335346

336347
public function reset()
337348
{
338-
$this->multi->reset();
349+
if (isset($this->multi)) {
350+
$this->multi->reset();
351+
}
339352
}
340353

341354
/**
@@ -439,6 +452,16 @@ private static function createRedirectResolver(array $options, string $host): \C
439452
};
440453
}
441454

455+
private function ensureState(): CurlClientState
456+
{
457+
if (!isset($this->multi)) {
458+
$this->multi = new CurlClientState($this->maxHostConnections, $this->maxPendingPushes);
459+
$this->multi->logger = $this->logger;
460+
}
461+
462+
return $this->multi;
463+
}
464+
442465
private function findConstantName(int $opt): ?string
443466
{
444467
$constants = array_filter(get_defined_constants(), static function ($v, $k) use ($opt) {

‎src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ public function testHandleIsReinitOnReset()
6363
{
6464
$httpClient = $this->getHttpClient(__FUNCTION__);
6565

66-
$r = new \ReflectionProperty($httpClient, 'multi');
66+
$r = new \ReflectionMethod($httpClient, 'ensureState');
6767
$r->setAccessible(true);
68-
$clientState = $r->getValue($httpClient);
68+
$clientState = $r->invoke($httpClient);
6969
$initialShareId = $clientState->share;
7070
$httpClient->reset();
7171
self::assertNotSame($initialShareId, $clientState->share);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.