@@ -50,6 +50,9 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
50
50
*/
51
51
private $ logger ;
52
52
53
+ private $ maxHostConnections ;
54
+ private $ maxPendingPushes ;
55
+
53
56
/**
54
57
* An internal object to share state between the client and its responses.
55
58
*
@@ -70,18 +73,22 @@ public function __construct(array $defaultOptions = [], int $maxHostConnections
70
73
throw new \LogicException ('You cannot use the "Symfony\Component\HttpClient\CurlHttpClient" as the "curl" extension is not installed. ' );
71
74
}
72
75
76
+ $ this ->maxHostConnections = $ maxHostConnections ;
77
+ $ this ->maxPendingPushes = $ maxPendingPushes ;
78
+
73
79
$ this ->defaultOptions ['buffer ' ] = $ this ->defaultOptions ['buffer ' ] ?? \Closure::fromCallable ([__CLASS__ , 'shouldBuffer ' ]);
74
80
75
81
if ($ defaultOptions ) {
76
82
[, $ this ->defaultOptions ] = self ::prepareRequest (null , null , $ defaultOptions , $ this ->defaultOptions );
77
83
}
78
-
79
- $ this ->multi = new CurlClientState ($ maxHostConnections , $ maxPendingPushes );
80
84
}
81
85
82
86
public function setLogger (LoggerInterface $ logger ): void
83
87
{
84
- $ this ->logger = $ this ->multi ->logger = $ logger ;
88
+ $ this ->logger = $ logger ;
89
+ if (isset ($ this ->multi )) {
90
+ $ this ->multi ->logger = $ logger ;
91
+ }
85
92
}
86
93
87
94
/**
@@ -91,6 +98,8 @@ public function setLogger(LoggerInterface $logger): void
91
98
*/
92
99
public function request (string $ method , string $ url , array $ options = []): ResponseInterface
93
100
{
101
+ $ multi = $ this ->ensureState ();
102
+
94
103
[$ url , $ options ] = self ::prepareRequest ($ method , $ url , $ options , $ this ->defaultOptions );
95
104
$ scheme = $ url ['scheme ' ];
96
105
$ authority = $ url ['authority ' ];
@@ -161,25 +170,25 @@ public function request(string $method, string $url, array $options = []): Respo
161
170
}
162
171
163
172
// 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 ]];
166
175
}
167
176
168
- if ($ options ['resolve ' ] || $ this -> multi ->dnsCache ->evictions ) {
177
+ if ($ options ['resolve ' ] || $ multi ->dnsCache ->evictions ) {
169
178
// 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 = [];
172
181
$ port = parse_url ($ authority , \PHP_URL_PORT ) ?: ('http: ' === $ scheme ? 80 : 443 );
173
182
174
183
if ($ resolve && 0x072A00 > CurlClientState::$ curlVersion ['version_number ' ]) {
175
184
// DNS cache removals require curl 7.42 or higher
176
- $ this -> multi ->reset ();
185
+ $ multi ->reset ();
177
186
}
178
187
179
188
foreach ($ options ['resolve ' ] as $ host => $ ip ) {
180
189
$ 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 " ;
183
192
}
184
193
185
194
$ curlopts [\CURLOPT_RESOLVE ] = $ resolve ;
@@ -281,16 +290,16 @@ public function request(string $method, string $url, array $options = []): Respo
281
290
$ curlopts += $ options ['extra ' ]['curl ' ];
282
291
}
283
292
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 ]);
286
295
287
296
if (self ::acceptPushForRequest ($ method , $ options , $ pushedResponse )) {
288
297
$ this ->logger && $ this ->logger ->debug (sprintf ('Accepting pushed response: "%s %s" ' , $ method , $ url ));
289
298
290
299
// Reinitialize the pushed response with request's options
291
300
$ ch = $ pushedResponse ->handle ;
292
301
$ pushedResponse = $ pushedResponse ->response ;
293
- $ pushedResponse ->__construct ($ this -> multi , $ url , $ options , $ this ->logger );
302
+ $ pushedResponse ->__construct ($ multi , $ url , $ options , $ this ->logger );
294
303
} else {
295
304
$ this ->logger && $ this ->logger ->debug (sprintf ('Rejecting pushed response: "%s" ' , $ url ));
296
305
$ pushedResponse = null ;
@@ -300,7 +309,7 @@ public function request(string $method, string $url, array $options = []): Respo
300
309
if (!$ pushedResponse ) {
301
310
$ ch = curl_init ();
302
311
$ this ->logger && $ this ->logger ->info (sprintf ('Request: "%s %s" ' , $ method , $ url ));
303
- $ curlopt
F438
s += [\CURLOPT_SHARE => $ this -> multi ->share ];
312
+ $ curlopts += [\CURLOPT_SHARE => $ multi ->share ];
304
313
}
305
314
306
315
foreach ($ curlopts as $ opt => $ value ) {
@@ -310,7 +319,7 @@ public function request(string $method, string $url, array $options = []): Respo
310
319
}
311
320
}
312
321
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 ' ]);
314
323
}
315
324
316
325
/**
@@ -324,9 +333,11 @@ public function stream($responses, ?float $timeout = null): ResponseStreamInterf
324
333
throw new \TypeError (sprintf ('"%s()" expects parameter 1 to be an iterable of CurlResponse objects, "%s" given. ' , __METHOD__ , get_debug_type ($ responses )));
325
334
}
326
335
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) {
328
339
$ 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 )) {
330
341
}
331
342
}
332
343
@@ -335,7 +346,9 @@ public function stream($responses, ?float $timeout = null): ResponseStreamInterf
335
346
336
347
public function reset ()
337
348
{
338
- $ this ->multi ->reset ();
349
+ if (isset ($ this ->multi )) {
350
+ $ this ->multi ->reset ();
351
+ }
339
352
}
340
353
341
354
/**
@@ -439,6 +452,16 @@ private static function createRedirectResolver(array $options, string $host): \C
439
452
};
440
453
}
441
454
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
+
442
465
private function findConstantName (int $ opt ): ?string
443
466
{
444
467
$ constants = array_filter (get_defined_constants (), static function ($ v , $ k ) use ($ opt ) {
0 commit comments