Skip to content

Commit 18725f0

Browse files
Merge branch '5.4' into 6.4
* 5.4: [HttpClient] Fix streaming and redirecting with NoPrivateNetworkHttpClient Bump Symfony version to 5.4.49 Update VERSION for 5.4.48 Update CONTRIBUTORS for 5.4.48 Update CHANGELOG for 5.4.48
2 parents 60a1136 + d77d8e2 commit 18725f0

7 files changed

+81
-43
lines changed

NoPrivateNetworkHttpClient.php

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use Symfony\Contracts\HttpClient\ChunkInterface;
2121
use Symfony\Contracts\HttpClient\HttpClientInterface;
2222
use Symfony\Contracts\HttpClient\ResponseInterface;
23-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
2423
use Symfony\Contracts\Service\ResetInterface;
2524

2625
/**
@@ -81,32 +80,34 @@ public function request(string $method, string $url, array $options = []): Respo
8180
$ip = self::dnsResolve($dnsCache, $host, $this->ipFlags, $options);
8281
self::ipCheck($ip, $this->subnets, $this->ipFlags, $host, $url);
8382

84-
if (0 < $maxRedirects = $options['max_redirects']) {
85-
$options['max_redirects'] = 0;
86-
$redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = $options['headers'];
87-
88-
if (isset($options['normalized_headers']['host']) || isset($options['normalized_headers']['authorization']) || isset($options['normalized_headers']['cookie'])) {
89-
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], static function ($h) {
90-
return 0 !== stripos($h, 'Host:') && 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
91-
});
92-
}
93-
}
94-
9583
$onProgress = $options['on_progress'] ?? null;
9684
$subnets = $this->subnets;
9785
$ipFlags = $this->ipFlags;
9886

9987
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, $ipFlags): void {
10088
static $lastPrimaryIp = '';
10189

102-
if (($info['primary_ip'] ?? '') !== $lastPrimaryIp) {
90+
if (!\in_array($info['primary_ip'] ?? '', ['', $lastPrimaryIp], true)) {
10391
self::ipCheck($info['primary_ip'], $subnets, $ipFlags, null, $info['url']);
10492
$lastPrimaryIp = $info['primary_ip'];
10593
}
10694

10795
null !== $onProgress && $onProgress($dlNow, $dlSize, $info);
10896
};
10997

98+
if (0 >= $maxRedirects = $options['max_redirects']) {
99+
return new AsyncResponse($this->client, $method, $url, $options);
100+
}
101+
102+
$options['max_redirects'] = 0;
103+
$redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = $options['headers'];
104+
105+
if (isset($options['normalized_headers']['host']) || isset($options['normalized_headers']['authorization']) || isset($options['normalized_headers']['cookie'])) {
106+
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], static function ($h) {
107+
return 0 !== stripos($h, 'Host:') && 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
108+
});
109+
}
110+
110111
return new AsyncResponse($this->client, $method, $url, $options, static function (ChunkInterface $chunk, AsyncContext $context) use (&$method, &$options, $maxRedirects, &$redirectHeaders, $subnets, $ipFlags, $dnsCache): \Generator {
111112
if (null !== $chunk->getError() || $chunk->isTimeout() || !$chunk->isFirst()) {
112113
yield $chunk;
@@ -158,11 +159,6 @@ public function request(string $method, string $url, array $options = []): Respo
158159
});
159160
}
160161

161-
public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface
162-
{
163-
return $this->client->stream($responses, $timeout);
164-
}
165-
166162
public function setLogger(LoggerInterface $logger): void
167163
{
168164
if ($this->client instanceof LoggerAwareInterface) {

Tests/DataCollector/HttpClientDataCollectorTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ public static function setUpBeforeClass(): void
2424
TestHttpServer::start();
2525
}
2626

27-
public static function tearDownAfterClass(): void
28-
{
29-
TestHttpServer::stop();
30-
}
31-
3227
public function testItCollectsRequestCount()
3328
{
3429
$httpClient1 = $this->httpClientThatHasTracedRequests([

Tests/HttpClientTestCase.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,73 @@ public function testNoPrivateNetworkWithResolveAndRedirect()
518518
$client->request('GET', 'http://localhost:8057/302?location=https://symfony.com/');
519519
}
520520

521+
public function testNoPrivateNetwork304()
522+
{
523+
$client = $this->getHttpClient(__FUNCTION__);
524+
$client = new NoPrivateNetworkHttpClient($client, '104.26.14.6/32');
525+
$response = $client->request('GET', 'http://localhost:8057/304', [
526+
'headers' => ['If-Match' => '"abc"'],
527+
'buffer' => false,
528+
]);
529+
530+
$this->assertSame(304, $response->getStatusCode());
531+
$this->assertSame('', $response->getContent(false));
532+
}
533+
534+
public function testNoPrivateNetwork302()
535+
{
536+
$client = $this->getHttpClient(__FUNCTION__);
537+
$client = new NoPrivateNetworkHttpClient($client, '104.26.14.6/32');
538+
$response = $client->request('GET', 'http://localhost:8057/302/relative');
539+
540+
$body = $response->toArray();
541+
542+
$this->assertSame('/', $body['REQUEST_URI']);
543+
$this->assertNull($response->getInfo('redirect_url'));
544+
545+
$response = $client->request('GET', 'http://localhost:8057/302/relative', [
546+
'max_redirects' => 0,
547+
]);
548+
549+
$this->assertSame(302, $response->getStatusCode());
550+
$this->assertSame('http://localhost:8057/', $response->getInfo('redirect_url'));
551+
}
552+
553+
public function testNoPrivateNetworkStream()
554+
{
555+
$client = $this->getHttpClient(__FUNCTION__);
556+
557+
$response = $client->request('GET', 'http://localhost:8057');
558+
$client = new NoPrivateNetworkHttpClient($client, '104.26.14.6/32');
559+
560+
$response = $client->request('GET', 'http://localhost:8057');
561+
$chunks = $client->stream($response);
562+
$result = [];
563+
564+
foreach ($chunks as $r => $chunk) {
565+
if ($chunk->isTimeout()) {
566+
$result[] = 't';
567+
} elseif ($chunk->isLast()) {
568+
$result[] = 'l';
569+
} elseif ($chunk->isFirst()) {
570+
$result[] = 'f';
571+
}
572+
}
573+
574+
$this->assertSame($response, $r);
575+
$this->assertSame(['f', 'l'], $result);
576+
577+
$chunk = null;
578+
$i = 0;
579+
580+
foreach ($client->stream($response) as $chunk) {
581+
++$i;
582+
}
583+
584+
$this->assertSame(1, $i);
585+
$this->assertTrue($chunk->isLast());
586+
}
587+
521588
public function testNoRedirectWithInvalidLocation()
522589
{
523590
$client = $this->getHttpClient(__FUNCTION__);

Tests/HttplugClientTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ public static function setUpBeforeClass(): void
3232
TestHttpServer::start();
3333
}
3434

35-
public static function tearDownAfterClass(): void
36-
{
37-
TestHttpServer::stop();
38-
}
39-
4035
/**
4136
* @requires function ob_gzhandler
4237
*/

Tests/Psr18ClientTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ public static function setUpBeforeClass(): void
2828
TestHttpServer::start();
2929
}
3030

31-
public static function tearDownAfterClass(): void
32-
{
33-
TestHttpServer::stop();
34-
}
35-
3631
/**
3732
* @requires function ob_gzhandler
3833
*/

Tests/RetryableHttpClientTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@
2727

2828
class RetryableHttpClientTest extends TestCase
2929
{
30-
public static function tearDownAfterClass(): void
31-
{
32-
TestHttpServer::stop();
33-
}
34-
3530
public function testRetryOnError()
3631
{
3732
$client = new RetryableHttpClient(

Tests/TraceableHttpClientTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ public static function setUpBeforeClass(): void
2929
TestHttpServer::start();
3030
}
3131

32-
public static function tearDownAfterClass(): void
33-
{
34-
TestHttpServer::stop();
35-
}
36-
3732
public function testItTracesRequest()
3833
{
3934
$httpClient = $this->createMock(HttpClientInterface::class);

0 commit comments

Comments
 (0)