Skip to content

Commit 34005d9

Browse files
[FrameworkBundle] Simplify wiring of scoped clients
1 parent fc2a438 commit 34005d9

File tree

2 files changed

+52
-47
lines changed

2 files changed

+52
-47
lines changed

DependencyInjection/FrameworkExtension.php

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,47 +2880,52 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder
28802880
$retryOptions = $scopeConfig['retry_failed'] ?? ['enabled' => false];
28812881
unset($scopeConfig['retry_failed']);
28822882

2883-
$transport = $name.'.transport';
2884-
$container->register($transport, HttpClientInterface::class)
2883+
// This "transport" service is decorated in the following order:
2884+
// 1. ThrottlingHttpClient (30) -> throttles requests
2885+
// 2. UriTemplateHttpClient (25) -> expands URI templates
2886+
// 3. ScopingHttpClient (20) -> resolves relative URLs and applies scope configuration
2887+
// 4. CachingHttpClient (15) -> caches responses
2888+
// 5. RetryableHttpClient (10) -> retries requests
2889+
// 6. TraceableHttpClient (5) -> traces requests
2890+
$container->register($name, HttpClientInterface::class)
28852891
->setFactory('current')
28862892
->setArguments([[new Reference('http_client.transport')]])
2893+
->addTag('http_client.client')
28872894
;
28882895

2896+
$scopingDefinition = $container->register($name.'.scoping', ScopingHttpClient::class)
2897+
->setDecoratedService($name, null, 20)
2898+
->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']);
2899+
28892900
if (null === $scope) {
28902901
$baseUri = $scopeConfig['base_uri'];
28912902
unset($scopeConfig['base_uri']);
28922903

2893-
$container->register($name, ScopingHttpClient::class)
2904+
$scopingDefinition
28942905
->setFactory([ScopingHttpClient::class, 'forBaseUri'])
2895-
->setArguments([new Reference($transport), $baseUri, $scopeConfig])
2896-
->addTag('http_client.client')
2897-
->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore'])
2898-
;
2906+
->setArguments([new Reference('.inner'), $baseUri, $scopeConfig]);
28992907
} else {
2900-
$container->register($name, ScopingHttpClient::class)
2901-
->setArguments([new Reference($transport), [$scope => $scopeConfig], $scope])
2902-
->addTag('http_client.client')
2903-
->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore'])
2904-
;
2908+
$scopingDefinition
2909+
->setArguments([new Reference('.inner'), [$scope => $scopeConfig], $scope]);
29052910
}
29062911

29072912
if ($this->readConfigEnabled('http_client.scoped_clients.'.$name.'.caching', $container, $cachingOptions)) {
2908-
$this->registerCachingHttpClient($cachingOptions, $scopeConfig, $transport, $container);
2913+
$this->registerCachingHttpClient($cachingOptions, $scopeConfig, $name, $container);
29092914
}
29102915

29112916
if (null !== $rateLimiter) {
2912-
$this->registerThrottlingHttpClient($rateLimiter, $transport, $container);
2917+
$this->registerThrottlingHttpClient($rateLimiter, $name, $container);
29132918
}
29142919

29152920
if ($this->readConfigEnabled('http_client.scoped_clients.'.$name.'.retry_failed', $container, $retryOptions)) {
2916-
$this->registerRetryableHttpClient($retryOptions, $transport, $container);
2921+
$this->registerRetryableHttpClient($retryOptions, $name, $container);
29172922
}
29182923

29192924
$container
29202925
->register($name.'.uri_template', UriTemplateHttpClient::class)
2921-
->setDecoratedService($name, null, 7) // After TraceableHttpClient (5) and on top of ScopingHttpClient
2926+
->setDecoratedService($name, null, 25)
29222927
->setArguments([
2923-
new Reference($name.'.uri_template.inner'),
2928+
new Reference('.inner'),
29242929
new Reference('http_client.uri_template_expander', ContainerInterface::NULL_ON_INVALID_REFERENCE),
29252930
$defaultUriTemplateVars,
29262931
]);
@@ -2944,7 +2949,7 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder
29442949

29452950
if ($responseFactoryId = $config['mock_response_factory'] ?? null) {
29462951
$container->register('http_client.mock_client', MockHttpClient::class)
2947-
->setDecoratedService('http_client.transport', null, -10) // lower priority than TraceableHttpClient (5)
2952+
->setDecoratedService('http_client.transport', null, -10)
29482953
->setArguments([new Reference($responseFactoryId)]);
29492954
}
29502955
}
@@ -2957,9 +2962,9 @@ private function registerCachingHttpClient(array $options, array $defaultOptions
29572962

29582963
$container
29592964
->register($name.'.caching', CachingHttpClient::class)
2960-
->setDecoratedService($name, null, 13) // between RetryableHttpClient (10) and ThrottlingHttpClient (15)
2965+
->setDecoratedService($name, null, 15)
29612966
->setArguments([
2962-
new Reference($name.'.caching.inner'),
2967+
new Reference('.inner'),
29632968
new Reference($options['cache_pool']),
29642969
$defaultOptions,
29652970
$options['shared'],
@@ -2982,8 +2987,8 @@ private function registerThrottlingHttpClient(string $rateLimiter, string $name,
29822987

29832988
$container
29842989
->register($name.'.throttling', ThrottlingHttpClient::class)
2985-
->setDecoratedService($name, null, 15) // higher priority than RetryableHttpClient (10)
2986-
->setArguments([new Reference($name.'.throttling.inner'), new Reference($name.'.throttling.limiter')]);
2990+
->setDecoratedService($name, null, 30)
2991+
->setArguments([new Reference('.inner'), new Reference($name.'.throttling.limiter')]);
29872992
}
29882993

29892994
private function registerRetryableHttpClient(array $options, string $name, ContainerBuilder $container): void
@@ -3014,8 +3019,8 @@ private function registerRetryableHttpClient(array $options, string $name, Conta
30143019

30153020
$container
30163021
->register($name.'.retryable', RetryableHttpClient::class)
3017-
->setDecoratedService($name, null, 10) // higher priority than TraceableHttpClient (5)
3018-
->setArguments([new Reference($name.'.retryable.inner'), $retryStrategy, $options['max_retries'], new Reference('logger')])
3022+
->setDecoratedService($name, null, 10)
3023+
->setArguments([new Reference('.inner'), $retryStrategy, $options['max_retries'], new Reference('logger')])
30193024
->addTag('monolog.logger', ['channel' => 'http_client']);
30203025
}
30213026

Tests/DependencyInjection/FrameworkExtensionTestCase.php

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
use Symfony\Component\HttpClient\Exception\ChunkCacheItemNotFoundException;
5959
use Symfony\Component\HttpClient\MockHttpClient;
6060
use Symfony\Component\HttpClient\RetryableHttpClient;
61-
use Symfony\Component\HttpClient\ScopingHttpClient;
6261
use Symfony\Component\HttpClient\ThrottlingHttpClient;
6362
use Symfony\Component\HttpFoundation\IpUtils;
6463
use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass;
@@ -107,6 +106,7 @@
107106
use Symfony\Component\Workflow\WorkflowEvents;
108107
use Symfony\Contracts\Cache\CacheInterface;
109108
use Symfony\Contracts\Cache\TagAwareCacheInterface;
109+
use Symfony\Contracts\HttpClient\HttpClientInterface;
110110

111111
abstract class FrameworkExtensionTestCase extends TestCase
112112
{
@@ -2239,16 +2239,16 @@ public function testHttpClientDefaultOptions()
22392239

22402240
$this->assertTrue($container->hasDefinition('foo'), 'should have the "foo" service.');
22412241
$definition = $container->getDefinition('foo');
2242-
$this->assertSame(ScopingHttpClient::class, $definition->getClass());
2243-
$this->assertTrue($definition->hasTag('kernel.reset'));
2242+
$this->assertSame(HttpClientInterface::class, $definition->getClass());
2243+
$this->assertTrue($definition->hasTag('http_client.client'));
22442244
}
22452245

22462246
public function testScopedHttpClientWithoutQueryOption()
22472247
{
22482248
$container = $this->createContainerFromFile('http_client_scoped_without_query_option');
22492249

22502250
$this->assertTrue($container->hasDefinition('foo'), 'should have the "foo" service.');
2251-
$this->assertSame(ScopingHttpClient::class, $container->getDefinition('foo')->getClass());
2251+
$this->assertSame(HttpClientInterface::class, $container->getDefinition('foo')->getClass());
22522252
}
22532253

22542254
public function testHttpClientOverrideDefaultOptions()
@@ -2258,7 +2258,7 @@ public function testHttpClientOverrideDefaultOptions()
22582258
$this->assertSame(['foo' => 'bar'], $container->getDefinition('http_client.transport')->getArgument(0)['headers']);
22592259
$this->assertSame(['foo' => 'bar'], $container->getDefinition('http_client.transport')->getArgument(0)['extra']);
22602260
$this->assertSame(4, $container->getDefinition('http_client.transport')->getArgument(1));
2261-
$this->assertSame('http://example.com', $container->getDefinition('foo')->getArgument(1));
2261+
$this->assertSame('http://example.com', $container->getDefinition('foo.scoping')->getArgument(1));
22622262

22632263
$expected = [
22642264
'headers' => [
@@ -2270,7 +2270,7 @@ public function testHttpClientOverrideDefaultOptions()
22702270
'query' => [],
22712271
'resolve' => [],
22722272
];
2273-
$this->assertEquals($expected, $container->getDefinition('foo')->getArgument(2));
2273+
$this->assertEquals($expected, $container->getDefinition('foo.scoping')->getArgument(2));
22742274
}
22752275

22762276
public function testCachingHttpClient()
@@ -2287,26 +2287,26 @@ public function testCachingHttpClient()
22872287
$this->assertSame('http_client', $definition->getDecoratedService()[0]);
22882288
$this->assertCount(5, $arguments = $definition->getArguments());
22892289
$this->assertInstanceOf(Reference::class, $arguments[0]);
2290-
$this->assertSame('http_client.caching.inner', (string) $arguments[0]);
2290+
$this->assertSame('.inner', (string) $arguments[0]);
22912291
$this->assertInstanceOf(Reference::class, $arguments[1]);
22922292
$this->assertSame('foo', (string) $arguments[1]);
22932293
$this->assertArrayHasKey('headers', $arguments[2]);
22942294
$this->assertSame(['X-powered' => 'PHP'], $arguments[2]['headers']);
22952295
$this->assertFalse($arguments[3]);
22962296
$this->assertSame(2, $arguments[4]);
22972297

2298-
$this->assertTrue($container->hasDefinition('bar.transport.caching'));
2299-
$definition = $container->getDefinition('bar.transport.caching');
2298+
$this->assertTrue($container->hasDefinition('bar.caching'));
2299+
$definition = $container->getDefinition('bar.caching');
23002300
$this->assertSame(CachingHttpClient::class, $definition->getClass());
23012301
$arguments = $definition->getArguments();
23022302
$this->assertInstanceOf(Reference::class, $arguments[0]);
2303-
$this->assertSame('bar.transport.caching.inner', (string) $arguments[0]);
2303+
$this->assertSame('.inner', (string) $arguments[0]);
23042304
$this->assertInstanceOf(Reference::class, $arguments[1]);
23052305
$this->assertSame('baz', (string) $arguments[1]);
2306-
$scopedClient = $container->getDefinition('bar');
2306+
$scopedClient = $container->getDefinition('bar.scoping');
23072307

2308-
$this->assertSame('bar.transport', (string) $scopedClient->getArgument(0));
2309-
$this->assertNull($scopedClient->getDecoratedService());
2308+
$this->assertSame('.inner', (string) $scopedClient->getArgument(0));
2309+
$this->assertSame('bar', $scopedClient->getDecoratedService()[0]);
23102310
}
23112311

23122312
public function testHttpClientRetry()
@@ -2320,8 +2320,8 @@ public function testHttpClientRetry()
23202320
$this->assertSame(0.3, $container->getDefinition('http_client.retry_strategy')->getArgument(4));
23212321
$this->assertSame(2, $container->getDefinition('http_client.retryable')->getArgument(2));
23222322

2323-
$this->assertSame(RetryableHttpClient::class, $container->getDefinition('foo.transport.retryable')->getClass());
2324-
$this->assertSame(4, $container->getDefinition('foo.transport.retry_strategy')->getArgument(2));
2323+
$this->assertSame(RetryableHttpClient::class, $container->getDefinition('foo.retryable')->getClass());
2324+
$this->assertSame(4, $container->getDefinition('foo.retry_strategy')->getArgument(2));
23252325
}
23262326

23272327
public function testHttpClientWithQueryParameterKey()
@@ -2331,12 +2331,12 @@ public function testHttpClientWithQueryParameterKey()
23312331
$expected = [
23322332
'key' => 'foo',
23332333
];
2334-
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(2)['query']);
2334+
$this->assertSame($expected, $container->getDefinition('foo.scoping')->getArgument(2)['query']);
23352335

23362336
$expected = [
23372337
'host' => '127.0.0.1',
23382338
];
2339-
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(2)['resolve']);
2339+
$this->assertSame($expected, $container->getDefinition('foo.scoping')->getArgument(2)['resolve']);
23402340
}
23412341

23422342
public function testHttpClientFullDefaultOptions()
@@ -2382,19 +2382,19 @@ public function testHttpClientRateLimiter()
23822382
$this->assertSame('http_client', $definition->getDecoratedService()[0]);
23832383
$this->assertCount(2, $arguments = $definition->getArguments());
23842384
$this->assertInstanceOf(Reference::class, $arguments[0]);
2385-
$this->assertSame('http_client.throttling.inner', (string) $arguments[0]);
2385+
$this->assertSame('.inner', (string) $arguments[0]);
23862386
$this->assertInstanceOf(Reference::class, $arguments[1]);
23872387
$this->assertSame('http_client.throttling.limiter', (string) $arguments[1]);
23882388

2389-
$this->assertTrue($container->hasDefinition('foo.transport.throttling'));
2390-
$definition = $container->getDefinition('foo.transport.throttling');
2389+
$this->assertTrue($container->hasDefinition('foo.throttling'));
2390+
$definition = $container->getDefinition('foo.throttling');
23912391
$this->assertSame(ThrottlingHttpClient::class, $definition->getClass());
2392-
$this->assertSame('foo.transport', $definition->getDecoratedService()[0]);
2392+
$this->assertSame('foo', $definition->getDecoratedService()[0]);
23932393
$this->assertCount(2, $arguments = $definition->getArguments());
23942394
$this->assertInstanceOf(Reference::class, $arguments[0]);
2395-
$this->assertSame('foo.transport.throttling.inner', (string) $arguments[0]);
2395+
$this->assertSame('.inner', (string) $arguments[0]);
23962396
$this->assertInstanceOf(Reference::class, $arguments[1]);
2397-
$this->assertSame('foo.transport.throttling.limiter', (string) $arguments[1]);
2397+
$this->assertSame('foo.throttling.limiter', (string) $arguments[1]);
23982398
}
23992399

24002400
public static function provideMailer(): iterable

0 commit comments

Comments
 (0)