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 bce6124

Browse filesBrowse files
feature #30674 [FrameworkBundle] change the way http clients are configured by leveraging ScopingHttpClient (nicolas-grekas)
This PR was merged into the 4.3-dev branch. Discussion ---------- [FrameworkBundle] change the way http clients are configured by leveraging ScopingHttpClient | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This PR allows configuring scoped HTTP clients ("scoped_clients" replaces the previous "clients" options): ```yaml framework: http_client: max_host_connections: 4 default_options: # ... scoped_clients: github_client: base_uri: https://api.github.com headers: Authorization: token abc123 # ... ``` The base URI is turned into a scoping regular expression so that the token will be sent only when the `github_client` service is requesting the corresponding URLs. When the base URI is too restrictive, the `scope` option can be used explicitly to define the regexp that URLs must match before any other options are applied. ~All defined scopes are passed to a new `scoping_http_client` service, that can be used to hit endpoints with authentication pre-configured for several hosts. Its named autowiring alias is `HttpClientInterface $scopingClient` (this cannot be done with `http_client` as we want safe defaults, e.g. credentials should not be used implicitly when writing webhooks/crawlers.)~ Commits ------- f1a26b9 [FrameworkBundle] change the way http clients are configured by leveraging ScopingHttpClient
2 parents 8f3d80f + f1a26b9 commit bce6124
Copy full SHA for bce6124

17 files changed

+306
-219
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+216-127Lines changed: 216 additions & 127 deletions
Large diffs are not rendered by default.

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+11-31Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
use Symfony\Component\Form\FormTypeGuesserInterface;
6262
use Symfony\Component\Form\FormTypeInterface;
6363
use Symfony\Component\HttpClient\HttpClient;
64-
use Symfony\Component\HttpClient\HttpClientTrait;
6564
use Symfony\Component\HttpClient\Psr18Client;
65+
use Symfony\Component\HttpClient\ScopingHttpClient;
6666
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
6767
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
6868
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
@@ -117,7 +117,6 @@
117117
use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand;
118118
use Symfony\Component\Yaml\Yaml;
119119
use Symfony\Contracts\Cache\CacheInterface;
120-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
121120
use Symfony\Contracts\HttpClient\HttpClientInterface;
122121
use Symfony\Contracts\Service\ResetInterface;
123122
use Symfony\Contracts\Service\ServiceSubscriberInterface;
@@ -1803,42 +1802,23 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder
18031802

18041803
$loader->load('http_client.xml');
18051804

1806-
$merger = new class() {
1807-
use HttpClientTrait;
1808-
1809-
public function merge(array $options, array $defaultOptions)
1810-
{
1811-
try {
1812-
[, $mergedOptions] = $this->prepareRequest(null, null, $options, $defaultOptions);
1813-
1814-
foreach ($mergedOptions as $k => $v) {
1815-
if (!isset($options[$k]) && !isset($defaultOptions[$k])) {
1816-
// Remove options added by prepareRequest()
1817-
unset($mergedOptions[$k]);
1818-
}
1819-
}
1820-
1821-
return $mergedOptions;
1822-
} catch (TransportExceptionInterface $e) {
1823-
throw new InvalidArgumentException($e->getMessage(), 0, $e);
1824-
}
1825-
}
1826-
};
1827-
1828-
$defaultOptions = $merger->merge($config['default_options'] ?? [], []);
1829-
$container->getDefinition('http_client')->setArguments([$defaultOptions, $config['max_host_connections'] ?? 6]);
1805+
$container->getDefinition('http_client')->setArguments([$config['default_options'] ?? [], $config['max_host_connections'] ?? 6]);
18301806

18311807
if (!$hasPsr18 = interface_exists(ClientInterface::class)) {
18321808
$container->removeDefinition('psr18.http_client');
18331809
$container->removeAlias(ClientInterface::class);
18341810
}
18351811

1836-
foreach ($config['clients'] as $name => $clientConfig) {
1837-
$options = $merger->merge($clientConfig['default_options'] ?? [], $defaultOptions);
1812+
foreach ($config['scoped_clients'] as $name => $scopeConfig) {
1813+
if ('http_client' === $name) {
1814+
throw new InvalidArgumentException(sprintf('Invalid scope name: "%s" is reserved.', $name));
1815+
}
1816+
1817+
$scope = $scopeConfig['scope'];
1818+
unset($scopeConfig['scope']);
18381819

1839-
$container->register($name, HttpClientInterface::class)
1840-
->setFactory([HttpClient::class, 'create'])
1841-
->setArguments([$options, $clientConfig['max_host_connections'] ?? $config['max_host_connections'] ?? 6]);
1820+
$container->register($name, ScopingHttpClient::class)
1821+
->setArguments([new Reference('http_client'), [$scope => $scopeConfig], $scope]);
18421822

18431823
$container->registerAliasForArgument($name, HttpClientInterface::class);
18441824

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+30-13Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -458,30 +458,55 @@
458458

459459
<xsd:complexType name="http_client">
460460
<xsd:sequence>
461-
<xsd:element name="default-options" type="http_client_options" minOccurs="0" />
462-
<xsd:element name="client" type="http_client_client" minOccurs="0" maxOccurs="unbounded" />
461+
<xsd:element name="default-options" type="http_client_default_options" minOccurs="0" />
462+
<xsd:element name="scoped-client" type="http_client_scope_options" minOccurs="0" maxOccurs="unbounded" />
463463
</xsd:sequence>
464464
<xsd:attribute name="enabled" type="xsd:boolean" />
465465
<xsd:attribute name="max-host-connections" type="xsd:integer" />
466466
</xsd:complexType>
467467

468-
<xsd:complexType name="http_client_options" mixed="true">
468+
<xsd:complexType name="http_client_default_options" mixed="true">
469469
<xsd:choice maxOccurs="unbounded">
470-
<xsd:element name="query" type="http_query" minOccurs="0" maxOccurs="unbounded" />
471470
<xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" />
472471
<xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" />
473472
<xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
474473
</xsd:choice>
474+
<xsd:attribute name="max-redirects" type="xsd:integer" />
475+
<xsd:attribute name="http-version" type="xsd:string" />
475476
<xsd:attribute name="proxy" type="xsd:string" />
477+
<xsd:attribute name="no-proxy" type="xsd:string" />
476478
<xsd:attribute name="timeout" type="xsd:float" />
477479
<xsd:attribute name="bindto" type="xsd:string" />
478480
<xsd:attribute name="verify-peer" type="xsd:boolean" />
481+
<xsd:attribute name="verify-host" type="xsd:boolean" />
482+
<xsd:attribute name="cafile" type="xsd:string" />
483+
<xsd:attribute name="capath" type="xsd:string" />
484+
<xsd:attribute name="local-cert" type="xsd:string" />
485+
<xsd:attribute name="local-pk" type="xsd:string" />
486+
<xsd:attribute name="passphrase" type="xsd:string" />
487+
<xsd:attribute name="ciphers" type="xsd:string" />
488+
489+
</xsd:complexType>
490+
491+
<xsd:complexType name="http_client_scope_options" mixed="true">
492+
<xsd:choice maxOccurs="unbounded">
493+
<xsd:element name="query" type="http_query" minOccurs="0" maxOccurs="unbounded" />
494+
<xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" />
495+
<xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" />
496+
<xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
497+
</xsd:choice>
498+
<xsd:attribute name="name" type="xsd:string" />
499+
<xsd:attribute name="scope" type="xsd:string" />
500+
<xsd:attribute name="base-uri" type="xsd:string" />
479501
<xsd:attribute name="auth-basic" type="xsd:string" />
480502
<xsd:attribute name="auth-bearer" type="xsd:string" />
481503
<xsd:attribute name="max-redirects" type="xsd:integer" />
482504
<xsd:attribute name="http-version" type="xsd:string" />
483-
<xsd:attribute name="base-uri" type="xsd:string" />
505+
<xsd:attribute name="proxy" type="xsd:string" />
484506
<xsd:attribute name="no-proxy" type="xsd:string" />
507+
<xsd:attribute name="timeout" type="xsd:float" />
508+
<xsd:attribute name="bindto" type="xsd:string" />
509+
<xsd:attribute name="verify-peer" type="xsd:boolean" />
485510
<xsd:attribute name="verify-host" type="xsd:boolean" />
486511
<xsd:attribute name="cafile" type="xsd:string" />
487512
<xsd:attribute name="capath" type="xsd:string" />
@@ -491,14 +516,6 @@
491516
<xsd:attribute name="ciphers" type="xsd:string" />
492517
</xsd:complexType>
493518

494-
<xsd:complexType name="http_client_client">
495-
<xsd:sequence>
496-
<xsd:element name="default-options" type="http_client_options" minOccurs="0" />
497-
</xsd:sequence>
498-
<xsd:attribute name="name" type="xsd:string" />
499-
<xsd:attribute name="max-host-connections" type="xsd:integer" />
500-
</xsd:complexType>
501-
502519
<xsd:complexType name="fingerprint">
503520
<xsd:choice maxOccurs="unbounded">
504521
<xsd:element name="pin-sha256" type="xsd:string" minOccurs="0" />

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
336336
'disallow_search_engine_index' => true,
337337
'http_client' => [
338338
'enabled' => !class_exists(FullStack::class) && class_exists(HttpClient::class),
339-
'clients' => [],
339+
'scoped_clients' => [],
340340
],
341341
'mailer' => [
342342
'dsn' => 'smtp://null',

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
'http_client' => [
55
'max_host_connections' => 4,
66
'default_options' => null,
7-
'clients' => [
7+
'scoped_clients' => [
88
'foo' => [
9-
'default_options' => null,
9+
'base_uri' => 'http://example.com',
1010
],
1111
],
1212
],

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
$container->loadFromExtension('framework', [
44
'http_client' => [
55
'default_options' => [
6-
'auth_basic' => 'foo:bar',
7-
'query' => ['foo' => 'bar', 'bar' => 'baz'],
86
'headers' => ['X-powered' => 'PHP'],
97
'max_redirects' => 2,
108
'http_version' => '2.0',
11-
'base_uri' => 'http://example.com',
129
'resolve' => ['localhost' => '127.0.0.1'],
1310
'proxy' => 'proxy.org',
1411
'timeout' => 3.5,

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php
+3-5Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
'default_options' => [
77
'headers' => ['foo' => 'bar'],
88
],
9-
'clients' => [
9+
'scoped_clients' => [
1010
'foo' => [
11-
'max_host_connections' => 5,
12-
'default_options' => [
13-
'headers' => ['bar' => 'baz'],
14-
],
11+
'base_uri' => 'http://example.com',
12+
'headers' => ['bar' => 'baz'],
1513
],
1614
],
1715
],

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
<framework:config>
99
<framework:http-client max-host-connections="4">
1010
<framework:default-options />
11-
<framework:client name="foo">
12-
<framework:default-options />
13-
</framework:client>
11+
<framework:scoped-client
12+
name="foo"
13+
base-uri="http://example.com"
14+
/>
1415
</framework:http-client>
1516
</framework:config>
1617
</container>

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_full_default_options.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_full_default_options.xml
-4Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@
1212
bindto="127.0.0.1"
1313
timeout="3.5"
1414
verify-peer="true"
15-
auth-basic="foo:bar"
1615
max-redirects="2"
1716
http-version="2.0"
18-
base-uri="http://example.com"
1917
verify-host="true"
2018
cafile="/etc/ssl/cafile"
2119
capath="/etc/ssl"
@@ -24,8 +22,6 @@
2422
passphrase="password123456"
2523
ciphers="RC4-SHA:TLS13-AES-128-GCM-SHA256"
2624
>
27-
<framework:query key="foo">bar</framework:query>
28-
<framework:query key="bar">baz</framework:query>
2925
<framework:header name="X-powered">PHP</framework:header>
3026
<framework:resolve host="localhost">127.0.0.1</framework:resolve>
3127
<framework:peer-fingerprint>

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml
+3-5Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
<framework:default-options>
1111
<framework:header name="foo">bar</framework:header>
1212
</framework:default-options>
13-
<framework:client name="foo" max-host-connections="5">
14-
<framework:default-options>
15-
<framework:header name="bar">baz</framework:header>
16-
</framework:default-options>
17-
</framework:client>
13+
<framework:scoped-client name="foo" base-uri="http://example.com">
14+
<framework:header name="bar">baz</framework:header>
15+
</framework:scoped-client>
1816
</framework:http-client>
1917
</framework:config>
2018
</container>

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ framework:
22
http_client:
33
max_host_connections: 4
44
default_options: ~
5-
clients:
5+
scoped_clients:
66
foo:
7-
default_options: ~
7+
base_uri: http://example.com

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
framework:
22
http_client:
33
default_options:
4-
auth_basic: foo:bar
5-
query: {'foo': 'bar', 'bar': 'baz'}
64
headers:
75
X-powered: PHP
86
max_redirects: 2
97
http_version: 2.0
10-
base_uri: 'http://example.com'
118
resolve: {'localhost': '127.0.0.1'}
129
proxy: proxy.org
1310
timeout: 3.5

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ framework:
33
max_host_connections: 4
44
default_options:
55
headers: {'foo': 'bar'}
6-
clients:
6+
scoped_clients:
77
foo:
8-
max_host_connections: 5
9-
default_options:
10-
headers: {'bar': 'baz'}
8+
base_uri: http://example.com
9+
headers: {'bar': 'baz'}

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+17-11Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
3636
use Symfony\Component\DependencyInjection\Reference;
3737
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
38+
use Symfony\Component\HttpClient\ScopingHttpClient;
3839
use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass;
3940
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
4041
use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
@@ -53,7 +54,6 @@
5354
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
5455
use Symfony\Component\Validator\Validation;
5556
use Symfony\Component\Workflow;
56-
use Symfony\Contracts\HttpClient\HttpClientInterface;
5757

5858
abstract class FrameworkExtensionTest extends TestCase
5959
{
@@ -1406,25 +1406,34 @@ public function testHttpClientDefaultOptions()
14061406
$this->assertTrue($container->hasDefinition('http_client'), '->registerHttpClientConfiguration() loads http_client.xml');
14071407

14081408
$defaultOptions = [
1409-
'query' => [],
14101409
'headers' => [],
14111410
'resolve' => [],
14121411
];
14131412
$this->assertSame([$defaultOptions, 4], $container->getDefinition('http_client')->getArguments());
14141413

14151414
$this->assertTrue($container->hasDefinition('foo'), 'should have the "foo" service.');
1416-
$this->assertSame(HttpClientInterface::class, $container->getDefinition('foo')->getClass());
1417-
$this->assertSame([$defaultOptions, 4], $container->getDefinition('foo')->getArguments());
1415+
$this->assertSame(ScopingHttpClient::class, $container->getDefinition('foo')->getClass());
14181416
}
14191417

14201418
public function testHttpClientOverrideDefaultOptions()
14211419
{
14221420
$container = $this->createContainerFromFile('http_client_override_default_options');
14231421

1424-
$this->assertSame(['foo' => ['bar']], $container->getDefinition('http_client')->getArgument(0)['headers']);
1422+
$this->assertSame(['foo' => 'bar'], $container->getDefinition('http_client')->getArgument(0)['headers']);
14251423
$this->assertSame(4, $container->getDefinition('http_client')->getArgument(1));
1426-
$this->assertSame(['bar' => ['baz'], 'foo' => ['bar']], $container->getDefinition('foo')->getArgument(0)['headers']);
1427-
$this->assertSame(5, $container->getDefinition('foo')->getArgument(1));
1424+
1425+
$expected = [
1426+
'http\://example\.com/' => [
1427+
'base_uri' => 'http://example.com',
1428+
'headers' => [
1429+
'bar' => 'baz',
1430+
],
1431+
'query' => [],
1432+
'resolve' => [],
1433+
],
1434+
];
1435+
1436+
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(1));
14281437
}
14291438

14301439
public function testHttpClientFullDefaultOptions()
@@ -1433,12 +1442,9 @@ public function testHttpClientFullDefaultOptions()
14331442

14341443
$defaultOptions = $container->getDefinition('http_client')->getArgument(0);
14351444

1436-
$this->assertSame('foo:bar', $defaultOptions['auth_basic']);
1437-
$this->assertSame(['foo' => 'bar', 'bar' => 'baz'], $defaultOptions['query']);
1438-
$this->assertSame(['x-powered' => ['PHP']], $defaultOptions['headers']);
1445+
$this->assertSame(['X-powered' => 'PHP'], $defaultOptions['headers']);
14391446
$this->assertSame(2, $defaultOptions['max_redirects']);
14401447
$this->assertSame(2.0, (float) $defaultOptions['http_version']);
1441-
$this->assertSame('http://example.com', $defaultOptions['base_uri']);
14421448
$this->assertSame(['localhost' => '127.0.0.1'], $defaultOptions['resolve']);
14431449
$this->assertSame('proxy.org', $defaultOptions['proxy']);
14441450
$this->assertSame(3.5, $defaultOptions['timeout']);

‎src/Symfony/Component/HttpClient/Response/MockResponse.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/Response/MockResponse.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ private static function readResponse(self $response, array $options, ResponseInt
240240
$info = $mock->getInfo() ?: [];
241241
$response->info['http_code'] = ($info['http_code'] ?? 0) ?: $mock->getStatusCode(false) ?: 200;
242242
$response->addResponseHeaders($info['response_headers'] ?? [], $response->info, $response->headers);
243-
$dlSize = (int) ($response->headers['content-length'][0] ?? 0);
243+
$dlSize = isset($response->headers['content-encoding']) ? 0 : (int) ($response->headers['content-length'][0] ?? 0);
244244

245245
$response->info = [
246246
'start_time' => $response->info['start_time'],
@@ -282,7 +282,7 @@ private static function readResponse(self $response, array $options, ResponseInt
282282
// "notify" completion
283283
$onProgress($offset, $dlSize, $response->info);
284284

285-
if (isset($response->headers['content-length']) && $offset !== $dlSize) {
285+
if ($dlSize && $offset !== $dlSize) {
286286
throw new TransportException(sprintf('Transfer closed with %s bytes remaining to read.', $dlSize - $offset));
287287
}
288288
}

‎src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ public function set($key, $values, $replace = true)
122122
parent::set($key, $values, $replace);
123123

124124
// ensure the cache-control header has sensible defaults
125-
if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true)) {
126-
$computed = $this->computeCacheControlValue();
125+
if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) {
127126
$this->headers['cache-control'] = [$computed];
128127
$this->headerNames['cache-control'] = 'Cache-Control';
129128
$this->computedCacheControl = $this->parseCacheControl($computed);

0 commit comments

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