@@ -171,7 +171,7 @@ public function request(string $method, string $url, array $options = []): Respo
171
171
172
172
$ this ->logger && $ this ->logger ->info (sprintf ('Request: "%s %s" ' , $ method , implode ('' , $ url )));
173
173
174
- [$ host , $ port, $ url [ ' authority ' ]] = self ::dnsResolve ($ url , $ this -> multi , $ info, $ onProgress );
174
+ [$ host , $ port] = self ::parseHostPort ($ url , $ info );
175
175
176
176
if (!isset ($ options ['normalized_headers ' ]['host ' ])) {
177
177
$ options ['headers ' ][] = 'Host: ' .$ host .$ port ;
@@ -198,7 +198,6 @@ public function request(string $method, string $url, array $options = []): Respo
198
198
'follow_location ' => false , // We follow redirects ourselves - the native logic is too limited
199
199
],
200
200
'ssl ' => array_filter ([
201
- 'peer_name ' => $ host ,
202
201
'verify_peer ' => $ options ['verify_peer ' ],
203
202
'verify_peer_name ' => $ options ['verify_host ' ],
204
203
'cafile ' => $ options ['cafile ' ],
@@ -222,7 +221,11 @@ public function request(string $method, string $url, array $options = []): Respo
222
221
$ proxy = self ::getProxy ($ options ['proxy ' ], $ url , $ options ['no_proxy ' ]);
223
222
$ resolveRedirect = self ::createRedirectResolver ($ options , $ host , $ proxy , $ info , $ onProgress );
224
223
$ context = stream_context_create ($ context , ['notification ' => $ notification ]);
225
- self ::configureHeadersAndProxy ($ context , $ host , $ options ['headers ' ], $ proxy );
224
+
225
+ if (!self ::configureHeadersAndProxy ($ context , $ host , $ options ['headers ' ], $ proxy , 'https: ' === $ url ['scheme ' ])) {
226
+ $ ip = self ::dnsResolve ($ host , $ this ->multi , $ info , $ onProgress );
227
+ $ url ['authority ' ] = substr_replace ($ url ['authority ' ], $ ip , -\strlen ($ host ) - \strlen ($ port ), \strlen ($ host ));
228
+ }
226
229
227
230
return new NativeResponse ($ this ->multi , $ context , implode ('' , $ url ), $ options , $ info , $ resolveRedirect , $ onProgress , $ this ->logger );
228
231
}
@@ -265,9 +268,9 @@ private static function getBodyAsString($body): string
265
268
}
266
269
267
270
/**
268
- * Resolves the IP of the host using the local DNS cache if possible .
271
+ * Extracts the host and the port from the URL .
269
272
*/
270
- private static function dnsResolve (array $ url , NativeClientState $ multi , array &$ info, ? \ Closure $ onProgress ): array
273
+ private static function parseHostPort (array $ url , array &$ info ): array
271
274
{
272
275
if ($ port = parse_url ($ url ['authority ' ], \PHP_URL_PORT ) ?: '' ) {
273
276
$ info ['primary_port ' ] = $ port ;
@@ -276,8 +279,14 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
276
279
$ info ['primary_port ' ] = 'http: ' === $ url ['scheme ' ] ? 80 : 443 ;
277
280
}
278
281
279
- $ host = parse_url ($ url ['authority ' ], \PHP_URL_HOST );
282
+ return [parse_url ($ url ['authority ' ], \PHP_URL_HOST ), $ port ];
283
+ }
280
284
285
+ /**
286
+ * Resolves the IP of the host using the local DNS cache if possible.
287
+ */
288
+ private static function dnsResolve ($ host , NativeClientState $ multi , array &$ info , ?\Closure $ onProgress ): string
289
+ {
281
290
if (null === $ ip = $ multi ->dnsCache [$ host ] ?? null ) {
282
291
$ info ['debug ' ] .= "* Hostname was NOT found in DNS cache \n" ;
283
292
$ now = microtime (true );
@@ -300,7 +309,7 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
300
309
$ onProgress ();
301
310
}
302
311
303
- return [ $ host , $ port , substr_replace ( $ url [ ' authority ' ], $ ip , - \strlen ( $ host ) - \strlen ( $ port ), \strlen ( $ host ))] ;
312
+ return $ ip ;
304
313
}
305
314
306
315
/**
@@ -363,24 +372,33 @@ private static function createRedirectResolver(array $options, string $host, ?ar
363
372
}
364
373
}
365
374
366
- [$ host , $ port , $ url ['authority ' ]] = self ::dnsResolve ($ url , $ multi , $ info , $ onProgress );
367
- stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
375
+ [$ host , $ port ] = self ::parseHostPort ($ url , $ info );
368
376
369
377
if (false !== (parse_url ($ location , \PHP_URL_HOST ) ?? false )) {
370
378
// Authorization and Cookie headers MUST NOT follow except for the initial host name
371
379
$ requestHeaders = $ redirectHeaders ['host ' ] === $ host ? $ redirectHeaders ['with_auth ' ] : $ redirectHeaders ['no_auth ' ];
372
380
$ requestHeaders [] = 'Host: ' .$ host .$ port ;
373
- self ::configureHeadersAndProxy ($ context , $ host , $ requestHeaders , $ proxy );
381
+ $ dnsResolve = !self ::configureHeadersAndProxy ($ context , $ host , $ requestHeaders , $ proxy , 'https: ' === $ url ['scheme ' ]);
382
+ } else {
383
+ $ dnsResolve = isset (stream_context_get_options ($ context )['ssl ' ]['peer_name ' ]);
384
+ }
385
+
386
+ if ($ dnsResolve ) {
387
+ $ ip = self ::dnsResolve ($ host , $ multi , $ info , $ onProgress );
388
+ $ url ['authority ' ] = substr_replace ($ url ['authority ' ], $ ip , -\strlen ($ host ) - \strlen ($ port ), \strlen ($ host ));
374
389
}
375
390
376
391
return implode ('' , $ url );
377
392
};
378
393
}
379
394
380
- private static function configureHeadersAndProxy ($ context , string $ host , array $ requestHeaders , ?array $ proxy ): bool
395
+ private static function configureHeadersAndProxy ($ context , string $ host , array $ requestHeaders , ?array $ proxy, bool $ isSsl ): bool
381
396
{
382
397
if (null === $ proxy ) {
383
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
398
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
399
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
400
+
401
+ return false ;
384
402
}
385
403
386
404
// Matching "no_proxy" should follow the behavior of curl
@@ -389,17 +407,24 @@ private static function configureHeadersAndProxy($context, string $host, array $
389
407
$ dotRule = '. ' .ltrim ($ rule , '. ' );
390
408
391
409
if ('* ' === $ rule || $ host === $ rule || substr ($ host , -\strlen ($ dotRule )) === $ dotRule ) {
392
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
410
+ stream_context_set_option ($ context , 'http ' , 'proxy ' , null );
411
+ stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , false );
412
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
413
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
414
+
415
+ return false ;
393
416
}
394
417
}
395
418
396
- stream_context_set_option ($ context , 'http ' , 'proxy ' , $ proxy ['url ' ]);
397
- stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , true );
398
-
399
419
if (null !== $ proxy ['auth ' ]) {
400
420
$ requestHeaders [] = 'Proxy-Authorization: ' .$ proxy ['auth ' ];
401
421
}
402
422
403
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
423
+ stream_context_set_option ($ context , 'http ' , 'proxy ' , $ proxy ['url ' ]);
424
+ stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , !$ isSsl );
425
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
426
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , null );
427
+
428
+ return true ;
404
429
}
405
430
}
0 commit comments