Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3b643b8

Browse filesBrowse files
[HttpClient] Resolve hostnames in NoPrivateNetworkHttpClient
1 parent ebcaeea commit 3b643b8
Copy full SHA for 3b643b8
Expand file treeCollapse file tree

10 files changed

+78
-15
lines changed

‎HttpOptions.php

Copy file name to clipboardExpand all lines: HttpOptions.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ public function buffer(bool $buffer)
148148
}
149149

150150
/**
151+
* @param callable(int, int, array, \Closure|null=):void $callback
152+
*
151153
* @return $this
152154
*/
153155
public function setOnProgress(callable $callback)

‎NativeHttpClient.php

Copy file name to clipboardExpand all lines: NativeHttpClient.php
+10-2Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,15 @@ public function request(string $method, string $url, array $options = []): Respo
138138
// Memoize the last progress to ease calling the callback periodically when no network transfer happens
139139
$lastProgress = [0, 0];
140140
$maxDuration = 0 < $options['max_duration'] ? $options['max_duration'] : \INF;
141-
$onProgress = static function (...$progress) use ($onProgress, &$lastProgress, &$info, $maxDuration) {
141+
$multi = $this->multi;
142+
$resolve = static function (string $host, ?string $ip = null) use ($multi): ?string {
143+
if (null !== $ip) {
144+
$multi->dnsCache[$host] = $ip;
145+
}
146+
147+
return $multi->dnsCache[$host] ?? null;
148+
};
149+
$onProgress = static function (...$progress) use ($onProgress, &$lastProgress, &$info, $maxDuration, $resolve) {
142150
if ($info['total_time'] >= $maxDuration) {
143151
throw new TransportException(sprintf('Max duration was reached for "%s".', implode('', $info['url'])));
144152
}
@@ -154,7 +162,7 @@ public function request(string $method, string $url, array $options = []): Respo
154162
$lastProgress = $progress ?: $lastProgress;
155163
}
156164

157-
$onProgress($lastProgress[0], $lastProgress[1], $progressInfo);
165+
$onProgress($lastProgress[0], $lastProgress[1], $progressInfo, $resolve);
158166
};
159167
} elseif (0 < $options['max_duration']) {
160168
$maxDuration = $options['max_duration'];

‎NoPrivateNetworkHttpClient.php

Copy file name to clipboardExpand all lines: NoPrivateNetworkHttpClient.php
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,24 @@ public function request(string $method, string $url, array $options = []): Respo
8080
$lastUrl = '';
8181
$lastPrimaryIp = '';
8282

83-
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastUrl, &$lastPrimaryIp): void {
83+
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use ($onProgress, $subnets, &$lastUrl, &$lastPrimaryIp): void {
8484
if ($info['url'] !== $lastUrl) {
8585
$host = trim(parse_url($info['url'], PHP_URL_HOST) ?: '', '[]');
86+
$resolve ??= static fn () => null;
87+
88+
if (($ip = $host)
89+
&& !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)
90+
&& !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)
91+
&& !$ip = $resolve($host)
92+
) {
93+
if ($ip = @(dns_get_record($host, \DNS_A)[0]['ip'] ?? null)) {
94+
$resolve($host, $ip);
95+
} elseif ($ip = @(dns_get_record($host, \DNS_AAAA)[0]['ipv6'] ?? null)) {
96+
$resolve($host, '['.$ip.']');
97+
}
98+
}
8699

87-
if ($host && IpUtils::checkIp($host, $subnets ?? self::PRIVATE_SUBNETS)) {
100+
if ($ip && IpUtils::checkIp($ip, $subnets ?? self::PRIVATE_SUBNETS)) {
88101
throw new TransportException(sprintf('Host "%s" is blocked for "%s".', $host, $info['url']));
89102
}
90103

‎Response/AmpResponse.php

Copy file name to clipboardExpand all lines: Response/AmpResponse.php
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,17 @@ public function __construct(AmpClientState $multi, Request $request, array $opti
8989
$info['max_duration'] = $options['max_duration'];
9090
$info['debug'] = '';
9191

92+
$resolve = static function (string $host, ?string $ip = null) use ($multi): ?string {
93+
if (null !== $ip) {
94+
$multi->dnsCache[$host] = $ip;
95+
}
96+
97+
return $multi->dnsCache[$host] ?? null;
98+
};
9299
$onProgress = $options['on_progress'] ?? static function () {};
93-
$onProgress = $this->onProgress = static function () use (&$info, $onProgress) {
100+
$onProgress = $this->onProgress = static function () use (&$info, $onProgress, $resolve) {
94101
$info['total_time'] = microtime(true) - $info['start_time'];
95-
$onProgress((int) $info['size_download'], ((int) (1 + $info['download_content_length']) ?: 1) - 1, (array) $info);
102+
$onProgress((int) $info['size_download'], ((int) (1 + $info['download_content_length']) ?: 1) - 1, (array) $info, $resolve);
96103
};
97104

98105
$pauseDeferred = new Deferred();

‎Response/AsyncContext.php

Copy file name to clipboardExpand all lines: Response/AsyncContext.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ public function replaceRequest(string $method, string $url, array $options = [])
156156
$this->info['previous_info'][] = $info = $this->response->getInfo();
157157
if (null !== $onProgress = $options['on_progress'] ?? null) {
158158
$thisInfo = &$this->info;
159-
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
160-
$onProgress($dlNow, $dlSize, $thisInfo + $info);
159+
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$thisInfo, $onProgress) {
160+
$onProgress($dlNow, $dlSize, $thisInfo + $info, $resolve);
161161
};
162162
}
163163
if (0 < ($info['max_duration'] ?? 0) && 0 < ($info['total_time'] ?? 0)) {

‎Response/AsyncResponse.php

Copy file name to clipboardExpand all lines: Response/AsyncResponse.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public function __construct(HttpClientInterface $client, string $method, string
5151

5252
if (null !== $onProgress = $options['on_progress'] ?? null) {
5353
$thisInfo = &$this->info;
54-
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
55-
$onProgress($dlNow, $dlSize, $thisInfo + $info);
54+
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$thisInfo, $onProgress) {
55+
$onProgress($dlNow, $dlSize, $thisInfo + $info, $resolve);
5656
};
5757
}
5858
$this->response = $client->request($method, $url, ['buffer' => false] + $options);

‎Response/CurlResponse.php

Copy file name to clipboardExpand all lines: Response/CurlResponse.php
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,20 @@ public function __construct(CurlClientState $multi, $ch, ?array $options = null,
115115
curl_pause($ch, \CURLPAUSE_CONT);
116116

117117
if ($onProgress = $options['on_progress']) {
118+
$resolve = static function (string $host, ?string $ip = null) use ($multi): ?string {
119+
if (null !== $ip) {
120+
$multi->dnsCache->hostnames[$host] = $ip;
121+
}
122+
123+
return $multi->dnsCache->hostnames[$host] ?? null;
124+
};
118125
$url = isset($info['url']) ? ['url' => $info['url']] : [];
119126
curl_setopt($ch, \CURLOPT_NOPROGRESS, false);
120-
curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION, static function ($ch, $dlSize, $dlNow) use ($onProgress, &$info, $url, $multi, $debugBuffer) {
127+
curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION, static function ($ch, $dlSize, $dlNow) use ($onProgress, &$info, $url, $multi, $debugBuffer, $resolve) {
121128
try {
122129
rewind($debugBuffer);
123130
$debug = ['debug' => stream_get_contents($debugBuffer)];
124-
$onProgress($dlNow, $dlSize, $url + curl_getinfo($ch) + $info + $debug);
131+
$onProgress($dlNow, $dlSize, $url + curl_getinfo($ch) + $info + $debug, $resolve);
125132
} catch (\Throwable $e) {
126133
$multi->handlesActivity[(int) $ch][] = null;
127134
$multi->handlesActivity[(int) $ch][] = $e;

‎Tests/HttpClientTestCase.php

Copy file name to clipboardExpand all lines: Tests/HttpClientTestCase.php
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
1717
use Symfony\Component\HttpClient\Exception\TransportException;
1818
use Symfony\Component\HttpClient\Internal\ClientState;
19+
use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;
1920
use Symfony\Component\HttpClient\Response\StreamWrapper;
2021
use Symfony\Component\Process\Exception\ProcessFailedException;
2122
use Symfony\Component\Process\Process;
@@ -466,4 +467,26 @@ public function testMisspelledScheme()
466467

467468
$httpClient->request('GET', 'http:/localhost:8057/');
468469
}
470+
471+
public function testNoPrivateNetwork()
472+
{
473+
$client = $this->getHttpClient(__FUNCTION__);
474+
$client = new NoPrivateNetworkHttpClient($client);
475+
476+
$this->expectException(TransportException::class);
477+
$this->expectExceptionMessage('Host "localhost" is blocked');
478+
479+
$client->request('GET', 'http://localhost:8888');
480+
}
481+
482+
public function testNoPrivateNetworkWithResolve()
483+
{
484+
$client = $this->getHttpClient(__FUNCTION__);
485+
$client = new NoPrivateNetworkHttpClient($client);
486+
487+
$this->expectException(TransportException::class);
488+
$this->expectExceptionMessage('Host "symfony.com" is blocked');
489+
490+
$client->request('GET', 'http://symfony.com', ['resolve' => ['symfony.com' => '127.0.0.1']]);
491+
}
469492
}

‎Tests/MockHttpClientTest.php

Copy file name to clipboardExpand all lines: Tests/MockHttpClientTest.php
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,17 @@ protected function getHttpClient(string $testCase): HttpClientInterface
304304

305305
switch ($testCase) {
306306
default:
307-
return new MockHttpClient(function (string $method, string $url, array $options) use ($client) {
307+
return new MockHttpClient(function (string $method, string $url, array $options) use ($client, $testCase) {
308308
try {
309309
// force the request to be completed so that we don't test side effects of the transport
310310
$response = $client->request($method, $url, ['buffer' => false] + $options);
311311
$content = $response->getContent(false);
312312

313313
return new MockResponse($content, $response->getInfo());
314314
} catch (\Throwable $e) {
315+
if (str_starts_with($testCase, 'testNoPrivateNetwork')) {
316+
throw $e;
317+
}
315318
$this->fail($e->getMessage());
316319
}
317320
});

‎TraceableHttpClient.php

Copy file name to clipboardExpand all lines: TraceableHttpClient.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ public function request(string $method, string $url, array $options = []): Respo
5858
$content = false;
5959
}
6060

61-
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use (&$traceInfo, $onProgress) {
61+
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$traceInfo, $onProgress) {
6262
$traceInfo = $info;
6363

6464
if (null !== $onProgress) {
65-
$onProgress($dlNow, $dlSize, $info);
65+
$onProgress($dlNow, $dlSize, $info, $resolve);
6666
}
6767
};
6868

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.