@@ -215,15 +215,18 @@ public function request(string $method, string $url, array $options = []): Respo
215
215
$ context = stream_context_create ($ context , ['notification ' => $ notification ]);
216
216
217
217
$ resolver = static function ($ multi ) use ($ context , $ options , $ url , &$ info , $ onProgress ) {
218
- [$ host , $ port, $ url [ ' authority ' ]] = self ::dnsResolve ($ url , $ multi , $ info, $ onProgress );
218
+ [$ host , $ port] = self ::parseHostPort ($ url , $ info );
219
219
220
220
if (!isset ($ options ['normalized_headers ' ]['host ' ])) {
221
221
$ options ['headers ' ][] = 'Host: ' .$ host .$ port ;
222
222
}
223
223
224
- stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
225
224
$ proxy = self ::getProxy ($ options ['proxy ' ], $ url , $ options ['no_proxy ' ]);
226
- self ::configureHeadersAndProxy ($ context , $ host , $ options ['headers ' ], $ proxy );
225
+
226
+ if (!self ::configureHeadersAndProxy ($ context , $ host , $ options ['headers ' ], $ proxy , 'https: ' === $ url ['scheme ' ])) {
227
+ $ ip = self ::dnsResolve ($ host , $ multi , $ info , $ onProgress );
228
+ $ url ['authority ' ] = substr_replace ($ url ['authority ' ], $ ip , -\strlen ($ host ) - \strlen ($ port ), \strlen ($ host ));
229
+ }
227
230
228
231
return [self ::createRedirectResolver ($ options , $ host , $ proxy , $ info , $ onProgress ), implode ('' , $ url )];
229
232
};
@@ -269,9 +272,9 @@ private static function getBodyAsString($body): string
269
272
}
270
273
271
274
/**
272
- * Resolves the IP of the host using the local DNS cache if possible .
275
+ * Extracts the host and the port from the URL .
273
276
*/
274
- private static function dnsResolve (array $ url , NativeClientState $ multi , array &$ info, ? \ Closure $ onProgress ): array
277
+ private static function parseHostPort (array $ url , array &$ info ): array
275
278
{
276
279
if ($ port = parse_url ($ url ['authority ' ], \PHP_URL_PORT ) ?: '' ) {
277
280
$ info ['primary_port ' ] = $ port ;
@@ -280,8 +283,14 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
280
283
$ info ['primary_port ' ] = 'http: ' === $ url ['scheme ' ] ? 80 : 443 ;
281
284
}
282
285
283
- $ host = parse_url ($ url ['authority ' ], \PHP_URL_HOST );
286
+ return [parse_url ($ url ['authority ' ], \PHP_URL_HOST ), $ port ];
287
+ }
284
288
289
+ /**
290
+ * Resolves the IP of the host using the local DNS cache if possible.
291
+ */
292
+ private static function dnsResolve ($ host , NativeClientState $ multi , array &$ info , ?\Closure $ onProgress ): string
293
+ {
285
294
if (null === $ ip = $ multi ->dnsCache [$ host ] ?? null ) {
286
295
$ info ['debug ' ] .= "* Hostname was NOT found in DNS cache \n" ;
287
296
$ now = microtime (true );
@@ -304,7 +313,7 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
304
313
$ onProgress ();
305
314
}
306
315
307
- return [ $ host , $ port , substr_replace ( $ url [ ' authority ' ], $ ip , - \strlen ( $ host ) - \strlen ( $ port ), \strlen ( $ host ))] ;
316
+ return $ ip ;
308
317
}
309
318
310
319
/**
@@ -367,24 +376,33 @@ private static function createRedirectResolver(array $options, string $host, ?ar
367
376
}
368
377
}
369
378
370
- [$ host , $ port , $ url ['authority ' ]] = self ::dnsResolve ($ url , $ multi , $ info , $ onProgress );
371
- stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
379
+ [$ host , $ port ] = self ::parseHostPort ($ url , $ info );
372
380
373
381
if (false !== (parse_url ($ location , \PHP_URL_HOST ) ?? false )) {
374
382
// Authorization and Cookie headers MUST NOT follow except for the initial host name
375
383
$ requestHeaders = $ redirectHeaders ['host ' ] === $ host ? $ redirectHeaders ['with_auth ' ] : $ redirectHeaders ['no_auth ' ];
376
384
$ requestHeaders [] = 'Host: ' .$ host .$ port ;
377
- self ::configureHeadersAndProxy ($ context , $ host , $ requestHeaders , $ proxy );
385
+ $ dnsResolve = !self ::configureHeadersAndProxy ($ context , $ host , $ requestHeaders , $ proxy , 'https: ' === $ url ['scheme ' ]);
386
+ } else {
387
+ $ dnsResolve = isset (stream_context_get_options ($ context )['ssl ' ]['peer_name ' ]);
388
+ }
389
+
390
+ if ($ dnsResolve ) {
391
+ $ ip = self ::dnsResolve ($ host , $ multi , $ info , $ onProgress );
392
+ $ url ['authority ' ] = substr_replace ($ url ['authority ' ], $ ip , -\strlen ($ host ) - \strlen ($ port ), \strlen ($ host ));
378
393
}
379
394
380
395
return implode ('' , $ url );
381
396
};
382
397
}
383
398
384
- private static function configureHeadersAndProxy ($ context , string $ host , array $ requestHeaders , ?array $ proxy ): bool
399
+ private static function configureHeadersAndProxy ($ context , string $ host , array $ requestHeaders , ?array $ proxy, bool $ isSsl ): bool
385
400
{
386
401
if (null === $ proxy ) {
387
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
402
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
403
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
404
+
405
+ return false ;
388
406
}
389
407
390
408
// Matching "no_proxy" should follow the behavior of curl
@@ -393,17 +411,24 @@ private static function configureHeadersAndProxy($context, string $host, array $
393
411
$ dotRule = '. ' .ltrim ($ rule , '. ' );
394
412
395
413
if ('* ' === $ rule || $ host === $ rule || substr ($ host , -\strlen ($ dotRule )) === $ dotRule ) {
396
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
414
+ stream_context_set_option ($ context , 'http ' , 'proxy ' , null );
415
+ stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , false );
416
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
417
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , $ host );
418
+
419
+ return false ;
397
420
}
398
421
}
399
422
400
- stream_context_set_option ($ context , 'http ' , 'proxy ' , $ proxy ['url ' ]);
401
- stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , true );
402
-
403
423
if (null !== $ proxy ['auth ' ]) {
404
424
$ requestHeaders [] = 'Proxy-Authorization: ' .$ proxy ['auth ' ];
405
425
}
406
426
407
- return stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
427
+ stream_context_set_option ($ context , 'http ' , 'proxy ' , $ proxy ['url ' ]);
428
+ stream_context_set_option ($ context , 'http ' , 'request_fulluri ' , !$ isSsl );
429
+ stream_context_set_option ($ context , 'http ' , 'header ' , $ requestHeaders );
430
+ stream_context_set_option ($ context , 'ssl ' , 'peer_name ' , null );
431
+
432
+ return true ;
408
433
}
409
434
}
0 commit comments