8000 [HttpClient] Fix option "bindto" with IPv6 addresses · symfony/symfony@e19f0c6 · GitHub
[go: up one dir, main page]

Skip to content

Commit e19f0c6

Browse files
[HttpClient] Fix option "bindto" with IPv6 addresses
1 parent 69ff299 commit e19f0c6

File tree

6 files changed

+53
-33
lines changed

6 files changed

+53
-33
lines changed

src/Symfony/Component/HttpClient/CurlHttpClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public function request(string $method, string $url, array $options = []): Respo
274274
if (file_exists($options['bindto'])) {
275275
$curlopts[\CURLOPT_UNIX_SOCKET_PATH] = $options['bindto'];
276276
} elseif (!str_starts_with($options['bindto'], 'if!') && preg_match('/^(.*):(\d+)$/', $options['bindto'], $matches)) {
277-
$curlopts[\CURLOPT_INTERFACE] = $matches[1];
277+
$curlopts[\CURLOPT_INTERFACE] = trim($matches[1], '[]');
278278
$curlopts[\CURLOPT_LOCALPORT] = $matches[2];
279279
} else {
280280
$curlopts[\CURLOPT_INTERFACE] = $options['bindto'];

src/Symfony/Component/HttpClient/NativeHttpClient.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,9 @@ private static function dnsResolve($host, NativeClientState $multi, array &$info
334334
$info['debug'] .= "* Hostname was NOT found in DNS cache\n";
335335
$now = microtime(true);
336336

337-
if (!$ip = gethostbynamel($host)) {
337+
if ('[' === $host[0] && ']' === $host[-1] && filter_var(substr($host, 1, -1), \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
338+
$ip = [$host];
339+
} elseif (!$ip = gethostbynamel($host)) {
338340
throw new TransportException(sprintf('Could not resolve host "%s".', $host));
339341
}
340342

src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,6 @@ protected function getHttpClient(string $testCase): HttpClientInterface
3737
return new CurlHttpClient(['verify_peer' => false, 'verify_host' => false], 6, 50);
3838
}
3939

40-
public function testBindToPort()
41-
{
42-
$client = $this->getHttpClient(__FUNCTION__);
43-
$response = $client->request('GET', 'http://localhost:8057', ['bindto' => '127.0.0.1:9876']);
44-
$response->getStatusCode();
45-
46-
$r = new \ReflectionProperty($response, 'handle');
47-
$r->setAccessible(true);
48-
49-
$curlInfo = curl_getinfo($r->getValue($response));
50-
51-
self::assertSame('127.0.0.1', $curlInfo['local_ip']);
52-
self::assertSame(9876, $curlInfo['local_port']);
53-
}
54-
5540
public function testTimeoutIsNotAFatalError()
5641
{
5742
if ('\\' === \DIRECTORY_SEPARATOR) {

src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,26 @@
1212
$_POST['content-type'] = $_SERVER['HTTP_CONTENT_TYPE'] ?? '?';
1313
}
1414

15+
$headers = [
16+
'SERVER_PROTOCOL',
17+
'SERVER_NAME',
18+
'REQUEST_URI',
19+
'REQUEST_METHOD',
20+
'PHP_AUTH_USER',
21+
'PHP_AUTH_PW',
22+
'REMOTE_ADDR',
23+
'REMOTE_PORT',
24+
];
25+
26+
foreach ($headers as $k) {
27+
if (isset($_SERVER[$k])) {
28+
$vars[$k] = $_SERVER[$k];
29+
}
30+
}
31+
1532
foreach ($_SERVER as $k => $v) {
16-
switch ($k) {
17-
default:
18-
if (0 !== strpos($k, 'HTTP_')) {
19-
continue 2;
20-
}
21-
// no break
22-
case 'SERVER_NAME':
23-
case 'SERVER_PROTOCOL':
24-
case 'REQUEST_URI':
25-
case 'REQUEST_METHOD':
26-
case 'PHP_AUTH_USER':
27-
case 'PHP_AUTH_PW':
28-
$vars[$k] = $v;
33+
if (0 === strpos($k, 'HTTP_')) {
34+
$vars[$k] = $v;
2935
}
3036
}
3137

src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static function tearDownAfterClass(): void
3636
{
3737
TestHttpServer::stop(8067);
3838
TestHttpServer::stop(8077);
39+
TestHttpServer::stop(8087);
3940
}
4041

4142
abstract protected function getHttpClient(string $testCase): HttpClientInterface;
@@ -1152,4 +1153,30 @@ public function testWithOptions()
11521153
$response = $client2->request('GET', '/');
11531154
$this->assertSame(200, $response->getStatusCode());
11541155
}
1156+
1157+
public function testBindToPort()
1158+
{
1159+
$client = $this->getHttpClient(__FUNCTION__);
1160+
$response = $client->request('GET', 'http://localhost:8057', ['bindto' => '127.0.0.1:9876']);
1161+
$response->getStatusCode();
1162+
1163+
$vars = $response->toArray();
1164+
1165+
self::assertSame('127.0.0.1', $vars['REMOTE_ADDR']);
1166+
self::assertSame('9876', $vars['REMOTE_PORT']);
1167+
}
1168+
1169+
public function testBindToPortV6()
1170+
{
1171+
TestHttpServer::start(8087, '[::1]');
1172+
1173+
$client = $this->getHttpClient(__FUNCTION__);
1174+
$response = $client->request('GET', 'http://[::1]:8087', ['bindto' => '[::1]:9876']);
1175+
$response->getStatusCode();
1176+
1177+
$vars = $response->toArray();
1178+
1179+
self::assertSame('::1', $vars['REMOTE_ADDR']);
1180+
self::assertSame('9876', $vars['REMOTE_PORT']);
1181+
}
11551182
}

src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TestHttpServer
2121
/**
2222
* @return Process
2323
*/
24-
public static function start(int $port = 8057)
24+
public static function start(int $port = 8057, $ip = '127.0.0.1')
2525
{
2626
if (isset(self::$process[$port])) {
2727
self::$process[$port]->stop();
@@ -32,14 +32,14 @@ public static function start(int $port = 8057)
3232
}
3333

3434
$finder = new PhpExecutableFinder();
35-
$process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', '127.0.0.1:'.$port]));
35+
$process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', $ip.':'.$port]));
3636
$process->setWorkingDirectory(__DIR__.'/Fixtures/web');
3737
$process->start();
3838
self::$process[$port] = $process;
3939

4040
do {
4141
usleep(50000);
42-
} while (!@fopen('http://127.0.0.1:'.$port, 'r'));
42+
} while (!@fopen('http://'.$ip.':'.$port, 'r'));
4343

4444
return $process;
4545
}

0 commit comments

Comments
 (0)
0