From 44a7a583ac1cb9c436f1b976384d10c93aafa0f3 Mon Sep 17 00:00:00 2001 From: Dmitrii Baranov Date: Mon, 2 Dec 2024 15:23:10 +0200 Subject: [PATCH] [HttpClient] Add IPv6 support to NativeHttpClient --- src/Symfony/Component/HttpClient/CHANGELOG.md | 5 ++++ .../Component/HttpClient/NativeHttpClient.php | 23 +++++++++++++++---- .../HttpClient/Tests/NativeHttpClientTest.php | 23 +++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CHANGELOG.md b/src/Symfony/Component/HttpClient/CHANGELOG.md index 5c70b9b3d4f6e..154f183a801ee 100644 --- a/src/Symfony/Component/HttpClient/CHANGELOG.md +++ b/src/Symfony/Component/HttpClient/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.3 +--- + + * Add IPv6 support to `NativeHttpClient` + 7.2 --- diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index da01191d4a016..941d37542c3ad 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -332,25 +332,38 @@ private static function dnsResolve(string $host, NativeClientState $multi, array { $flag = '' !== $host && '[' === $host[0] && ']' === $host[-1] && str_contains($host, ':') ? \FILTER_FLAG_IPV6 : \FILTER_FLAG_IPV4; $ip = \FILTER_FLAG_IPV6 === $flag ? substr($host, 1, -1) : $host; + $now = microtime(true); if (filter_var($ip, \FILTER_VALIDATE_IP, $flag)) { // The host is already an IP address } elseif (null === $ip = $multi->dnsCache[$host] ?? null) { $info['debug'] .= "* Hostname was NOT found in DNS cache\n"; - $now = microtime(true); - if (!$ip = gethostbynamel($host)) { + if ($ip = gethostbynamel($host)) { + $ip = $ip[0]; + } elseif (!\defined('STREAM_PF_INET6')) { + throw new TransportException(\sprintf('Could not resolve host "%s".', $host)); + } elseif ($ip = dns_get_record($host, \DNS_AAAA)) { + $ip = $ip[0]['ipv6']; + } elseif (\extension_loaded('sockets')) { + if (!$addrInfo = socket_addrinfo_lookup($host, 0, ['ai_socktype' => \SOCK_STREAM, 'ai_family' => \AF_INET6])) { + throw new TransportException(\sprintf('Could not resolve host "%s".', $host)); + } + + $ip = socket_addrinfo_explain($addrInfo[0])['ai_addr']['sin6_addr']; + } elseif ('localhost' === $host || 'localhost.' === $host) { + $ip = '::1'; + } else { throw new TransportException(\sprintf('Could not resolve host "%s".', $host)); } - $multi->dnsCache[$host] = $ip = $ip[0]; + $multi->dnsCache[$host] = $ip; $info['debug'] .= "* Added {$host}:0:{$ip} to DNS cache\n"; - $host = $ip; } else { $info['debug'] .= "* Hostname was found in DNS cache\n"; - $host = str_contains($ip, ':') ? "[$ip]" : $ip; } + $host = str_contains($ip, ':') ? "[$ip]" : $ip; $info['namelookup_time'] = microtime(true) - ($info['start_time'] ?: $now); $info['primary_ip'] = $ip; diff --git a/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php index 35ab614b482a5..90402d26af84b 100644 --- a/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php @@ -11,8 +11,10 @@ namespace Symfony\Component\HttpClient\Tests; +use Symfony\Bridge\PhpUnit\DnsMock; use Symfony\Component\HttpClient\NativeHttpClient; use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\Test\TestHttpServer; /** * @group dns-sensitive @@ -48,4 +50,25 @@ public function testHttp2PushVulcainWithUnusedResponse() { $this->markTestSkipped('NativeHttpClient doesn\'t support HTTP/2.'); } + + public function testIPv6Resolve() + { + TestHttpServer::start(-8087); + + DnsMock::withMockedHosts([ + 'symfony.com' => [ + [ + 'type' => 'AAAA', + 'ipv6' => '::1', + ], + ], + ]); + + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('GET', 'http://symfony.com:8087/'); + + $this->assertSame(200, $response->getStatusCode()); + + DnsMock::withMockedHosts([]); + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy