diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 649f87b17c1e..41d2d0a3e013 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -274,7 +274,7 @@ public function request(string $method, string $url, array $options = []): Respo if (file_exists($options['bindto'])) { $curlopts[\CURLOPT_UNIX_SOCKET_PATH] = $options['bindto']; } elseif (!str_starts_with($options['bindto'], 'if!') && preg_match('/^(.*):(\d+)$/', $options['bindto'], $matches)) { - $curlopts[\CURLOPT_INTERFACE] = $matches[1]; + $curlopts[\CURLOPT_INTERFACE] = trim($matches[1], '[]'); $curlopts[\CURLOPT_LOCALPORT] = $matches[2]; } else { $curlopts[\CURLOPT_INTERFACE] = $options['bindto']; diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index 5e4bb64ee27c..42c8be1bd8f2 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -334,7 +334,9 @@ private static function dnsResolve($host, NativeClientState $multi, array &$info $info['debug'] .= "* Hostname was NOT found in DNS cache\n"; $now = microtime(true); - if (!$ip = gethostbynamel($host)) { + if ('[' === $host[0] && ']' === $host[-1] && filter_var(substr($host, 1, -1), \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { + $ip = [$host]; + } elseif (!$ip = gethostbynamel($host)) { throw new TransportException(sprintf('Could not resolve host "%s".', $host)); } diff --git a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php index d8165705ca11..7e9aab212364 100644 --- a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php @@ -37,21 +37,6 @@ protected function getHttpClient(string $testCase): HttpClientInterface return new CurlHttpClient(['verify_peer' => false, 'verify_host' => false], 6, 50); } - public function testBindToPort() - { - $client = $this->getHttpClient(__FUNCTION__); - $response = $client->request('GET', 'http://localhost:8057', ['bindto' => '127.0.0.1:9876']); - $response->getStatusCode(); - - $r = new \ReflectionProperty($response, 'handle'); - $r->setAccessible(true); - - $curlInfo = curl_getinfo($r->getValue($response)); - - self::assertSame('127.0.0.1', $curlInfo['local_ip']); - self::assertSame(9876, $curlInfo['local_port']); - } - public function testTimeoutIsNotAFatalError() { if ('\\' === \DIRECTORY_SEPARATOR) { diff --git a/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php b/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php index fafab198aafe..db4d5519e40e 100644 --- a/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php +++ b/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php @@ -12,20 +12,26 @@ $_POST['content-type'] = $_SERVER['HTTP_CONTENT_TYPE'] ?? '?'; } +$headers = [ + 'SERVER_PROTOCOL', + 'SERVER_NAME', + 'REQUEST_URI', + 'REQUEST_METHOD', + 'PHP_AUTH_USER', + 'PHP_AUTH_PW', + 'REMOTE_ADDR', + 'REMOTE_PORT', +]; + +foreach ($headers as $k) { + if (isset($_SERVER[$k])) { + $vars[$k] = $_SERVER[$k]; + } +} + foreach ($_SERVER as $k => $v) { - switch ($k) { - default: - if (0 !== strpos($k, 'HTTP_')) { - continue 2; - } - // no break - case 'SERVER_NAME': - case 'SERVER_PROTOCOL': - case 'REQUEST_URI': - case 'REQUEST_METHOD': - case 'PHP_AUTH_USER': - case 'PHP_AUTH_PW': - $vars[$k] = $v; + if (0 === strpos($k, 'HTTP_')) { + $vars[$k] = $v; } } diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index 10c6395c6acf..eb10dbedbdba 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -36,6 +36,7 @@ public static function tearDownAfterClass(): void { TestHttpServer::stop(8067); TestHttpServer::stop(8077); + TestHttpServer::stop(8087); } abstract protected function getHttpClient(string $testCase): HttpClientInterface; @@ -1152,4 +1153,30 @@ public function testWithOptions() $response = $client2->request('GET', '/'); $this->assertSame(200, $response->getStatusCode()); } + + public function testBindToPort() + { + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('GET', 'http://localhost:8057', ['bindto' => '127.0.0.1:9876']); + $response->getStatusCode(); + + $vars = $response->toArray(); + + self::assertSame('127.0.0.1', $vars['REMOTE_ADDR']); + self::assertSame('9876', $vars['REMOTE_PORT']); + } + + public function testBindToPortV6() + { + TestHttpServer::start(8087, '[::1]'); + + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('GET', 'http://[::1]:8087', ['bindto' => '[::1]:9876']); + $response->getStatusCode(); + + $vars = $response->toArray(); + + self::assertSame('::1', $vars['REMOTE_ADDR']); + self::assertSame('9876', $vars['REMOTE_PORT']); + } } diff --git a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php index 463b4b75c60a..d8b828c93248 100644 --- a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php +++ b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php @@ -21,7 +21,7 @@ class TestHttpServer /** * @return Process */ - public static function start(int $port = 8057) + public static function start(int $port = 8057, $ip = '127.0.0.1') { if (isset(self::$process[$port])) { self::$process[$port]->stop(); @@ -32,14 +32,14 @@ public static function start(int $port = 8057) } $finder = new PhpExecutableFinder(); - $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', '127.0.0.1:'.$port])); + $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', $ip.':'.$port])); $process->setWorkingDirectory(__DIR__.'/Fixtures/web'); $process->start(); self::$process[$port] = $process; do { usleep(50000); - } while (!@fopen('http://127.0.0.1:'.$port, 'r')); + } while (!@fopen('http://'.$ip.':'.$port, 'r')); return $process; }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: