diff --git a/CHANGELOG.md b/CHANGELOG.md index 2338a708..e516b483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Changelog * If a custom proxy client is configured on the cache manager, the `ProxyClient` class is an alias to that client, to support autowiring. * Attribute configuration now also works on single action controllers with the `__invoke` method. +* New configuration option `proxy_client.*.http.request_factory` and `stream_factory` to support custom PSR-17 HTTP request and stream factories for proxy clients. 3.1.2 ----- @@ -53,6 +54,11 @@ Changelog 2.x === +2.18.0 +------ + +* New configuration option `proxy_client.*.http.request_factory` to support custom HTTP request factories for proxy clients. + 2.17.1 ------ diff --git a/Resources/doc/features/invalidation.rst b/Resources/doc/features/invalidation.rst index d1f9d177..6f3f9eaa 100644 --- a/Resources/doc/features/invalidation.rst +++ b/Resources/doc/features/invalidation.rst @@ -66,7 +66,8 @@ To refresh paths and routes, you can use ``refreshPath($path, $headers)`` and If you want to add a header (such as ``Authorization``) to *all* invalidation requests, you can use a - :ref:`custom HTTP client ` instead. + :ref:`custom HTTP client ` or + :ref:`custom HTTP request factory ` instead. .. _invalidation configuration: diff --git a/Resources/doc/reference/configuration/proxy-client.rst b/Resources/doc/reference/configuration/proxy-client.rst index 2b40f2d5..40a3562b 100644 --- a/Resources/doc/reference/configuration/proxy-client.rst +++ b/Resources/doc/reference/configuration/proxy-client.rst @@ -400,6 +400,23 @@ example to send a basic authentication header with each request, you can configure a service for the ``HttpClient`` and specify that in the ``http_client`` option of any of the cache proxy clients. +.. _custom HTTP request factory: + +Custom HTTP Request Factory and Stream Factory +---------------------------------------------- + +The proxy client uses an implementation of PSR-17 ``Psr\Http\Message\RequestFactoryInterface`` +to create HTTP requests and ``Psr\Http\Message\StreamFactoryInterface`` to +create streams. + +If you need to customize request creation, you can configure your custom +service and specify that in the ``request_factory`` option of any of the cache +proxy clients. + +If you need to customize stream creation, you can configure your custom service +and specify that in the ``stream_factory`` option of any of the cache proxy +clients. + Caching Proxy Configuration --------------------------- diff --git a/composer.json b/composer.json index bb40fd6c..b69ddd0b 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ ], "require": { "php": "^8.1", - "friendsofsymfony/http-cache": "^2.15 || ^3.0", + "friendsofsymfony/http-cache": "^3.0", "symfony/dependency-injection": "^6.4 || ^7.0", "symfony/expression-language": "^6.4 || ^7.0", "symfony/framework-bundle": "^6.4 || ^7.0", @@ -60,7 +60,7 @@ "phpstan/phpstan": "^2", "phpstan/phpstan-symfony": "^2", "phpstan/extension-installer": "^1.4", - "jean-beru/fos-http-cache-cloudfront": "^1.1", + "jean-beru/fos-http-cache-cloudfront": "^1.1.1", "friendsofphp/php-cs-fixer": "^3.54" }, "suggest": { diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 2b7ae1da..72fb70e9 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -624,6 +624,14 @@ private function getHttpDispatcherNode(): ArrayNodeDefinition ->defaultNull() ->info('Httplug async client service name to use for sending the requests.') ->end() + ->scalarNode('request_factory') + ->defaultNull() + ->info('Service name of PSR-17 message factory.') + ->end() + ->scalarNode('stream_factory') + ->defaultNull() + ->info('Service name of PSR-17 stream factory.') + ->end() ->end() ; diff --git a/src/DependencyInjection/FOSHttpCacheExtension.php b/src/DependencyInjection/FOSHttpCacheExtension.php index 68dad8aa..15e1aea3 100644 --- a/src/DependencyInjection/FOSHttpCacheExtension.php +++ b/src/DependencyInjection/FOSHttpCacheExtension.php @@ -427,6 +427,18 @@ private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader, $container->setParameter('fos_http_cache.proxy_client.varnish.options', $options); $loader->load('varnish.xml'); + + $requestFactory = isset($config['http']['request_factory']) + ? new Reference($config['http']['request_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.varnish') + ->replaceArgument(2, $requestFactory); + + $streamFactory = isset($config['http']['stream_factory']) + ? new Reference($config['http']['stream_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.varnish') + ->replaceArgument(3, $streamFactory); } private function loadNginx(ContainerBuilder $container, XmlFileLoader $loader, array $config): void @@ -436,6 +448,18 @@ private function loadNginx(ContainerBuilder $container, XmlFileLoader $loader, a 'purge_location' => $config['purge_location'], ]); $loader->load('nginx.xml'); + + $requestFactory = isset($config['http']['request_factory']) + ? new Reference($config['http']['request_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.nginx') + ->replaceArgument(2, $requestFactory); + + $streamFactory = isset($config['http']['stream_factory']) + ? new Reference($config['http']['stream_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.nginx') + ->replaceArgument(3, $streamFactory); } private function loadSymfony(ContainerBuilder $container, XmlFileLoader $loader, array $config): void @@ -462,6 +486,18 @@ private function loadSymfony(ContainerBuilder $container, XmlFileLoader $loader, $container->setParameter('fos_http_cache.proxy_client.symfony.options', $options); $loader->load('symfony.xml'); + + $requestFactory = isset($config['http']['request_factory']) + ? new Reference($config['http']['request_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.symfony') + ->replaceArgument(2, $requestFactory); + + $streamFactory = isset($config['http']['stream_factory']) + ? new Reference($config['http']['stream_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.symfony') + ->replaceArgument(3, $streamFactory); } private function loadCloudflare(ContainerBuilder $container, XmlFileLoader $loader, array $config): void @@ -475,6 +511,18 @@ private function loadCloudflare(ContainerBuilder $container, XmlFileLoader $load $container->setParameter('fos_http_cache.proxy_client.cloudflare.options', $options); $loader->load('cloudflare.xml'); + + $requestFactory = isset($config['http']['request_factory']) + ? new Reference($config['http']['request_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.cloudflare') + ->replaceArgument(2, $requestFactory); + + $streamFactory = isset($config['http']['stream_factory']) + ? new Reference($config['http']['stream_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.cloudflare') + ->replaceArgument(3, $streamFactory); } private function loadCloudfront(ContainerBuilder $container, XmlFileLoader $loader, array $config): void @@ -511,6 +559,18 @@ private function loadFastly(ContainerBuilder $container, XmlFileLoader $loader, $container->setParameter('fos_http_cache.proxy_client.fastly.options', $options); $loader->load('fastly.xml'); + + $requestFactory = isset($config['http']['request_factory']) + ? new Reference($config['http']['request_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.fastly') + ->replaceArgument(2, $requestFactory); + + $streamFactory = isset($config['http']['stream_factory']) + ? new Reference($config['http']['stream_factory']) + : null; + $container->getDefinition('fos_http_cache.proxy_client.fastly') + ->replaceArgument(3, $streamFactory); } /** diff --git a/src/Resources/config/cloudflare.xml b/src/Resources/config/cloudflare.xml index ae3f2000..5e92d5a6 100644 --- a/src/Resources/config/cloudflare.xml +++ b/src/Resources/config/cloudflare.xml @@ -11,6 +11,8 @@ lazy="true"> %fos_http_cache.proxy_client.cloudflare.options% + + diff --git a/src/Resources/config/fastly.xml b/src/Resources/config/fastly.xml index 8c86127f..41277e2f 100755 --- a/src/Resources/config/fastly.xml +++ b/src/Resources/config/fastly.xml @@ -11,6 +11,8 @@ lazy="true"> %fos_http_cache.proxy_client.fastly.options% + + diff --git a/src/Resources/config/nginx.xml b/src/Resources/config/nginx.xml index 7ec9f6fc..f9421820 100644 --- a/src/Resources/config/nginx.xml +++ b/src/Resources/config/nginx.xml @@ -10,6 +10,8 @@ public="true"> %fos_http_cache.proxy_client.nginx.options% + + diff --git a/src/Resources/config/symfony.xml b/src/Resources/config/symfony.xml index 3e2a1411..fcf2e334 100644 --- a/src/Resources/config/symfony.xml +++ b/src/Resources/config/symfony.xml @@ -10,6 +10,8 @@ public="true"> %fos_http_cache.proxy_client.symfony.options% + + diff --git a/src/Resources/config/varnish.xml b/src/Resources/config/varnish.xml index 520d81f6..57216740 100644 --- a/src/Resources/config/varnish.xml +++ b/src/Resources/config/varnish.xml @@ -10,6 +10,8 @@ public="true"> %fos_http_cache.proxy_client.varnish.options% + + diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 2427d422..3a867380 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -108,6 +108,8 @@ public function testSupportsAllConfigFormats(): void 'servers' => ['22.22.22.22'], 'base_url' => '/test', 'http_client' => 'acme.guzzle.varnish', + 'request_factory' => null, + 'stream_factory' => null, ], ], ], @@ -241,6 +243,8 @@ public function testSupportsNginx(): void 'servers' => ['22.22.22.22'], 'base_url' => '/test', 'http_client' => 'acme.guzzle.nginx', + 'request_factory' => null, + 'stream_factory' => null, ], ], ]; @@ -276,6 +280,8 @@ public function testSupportsSymfony(): void 'servers' => ['22.22.22.22'], 'base_url' => '/test', 'http_client' => 'acme.guzzle.symfony', + 'request_factory' => null, + 'stream_factory' => null, ], 'use_kernel_dispatcher' => false, ], @@ -506,6 +512,8 @@ public function testSplitOptions(): void 'base_url' => null, 'http_client' => null, 'servers' => ['1.1.1.1:80', '2.2.2.2:80'], + 'request_factory' => null, + 'stream_factory' => null, ], 'tags_header' => 'X-Cache-Tags', 'tag_mode' => 'ban', @@ -516,6 +524,8 @@ public function testSplitOptions(): void 'base_url' => null, 'http_client' => null, 'servers' => ['1.1.1.1:81', '2.2.2.2:81'], + 'request_factory' => null, + 'stream_factory' => null, ], ], ]; @@ -757,6 +767,8 @@ public function testUserContextLogoutHandler(string $configFile, $expected, $cac 'servers' => ['localhost'], 'base_url' => null, 'http_client' => null, + 'request_factory' => null, + 'stream_factory' => null, ]; $expectedConfiguration['proxy_client'][$proxyClient]['purge_location'] = false; } @@ -796,6 +808,8 @@ public function testSupportsServersFromJsonEnv(): void 'servers_from_jsonenv' => '%env(json:VARNISH_SERVERS)%', 'base_url' => '/test', 'http_client' => 'acme.guzzle.nginx', + 'request_factory' => null, + 'stream_factory' => null, ], 'tag_mode' => 'ban', 'tags_header' => 'X-Cache-Tags', @@ -829,6 +843,8 @@ public function testConfigureExpressionLanguageService(): void 'servers_from_jsonenv' => '%env(json:VARNISH_SERVERS)%', 'base_url' => '/test', 'http_client' => 'acme.guzzle.nginx', + 'request_factory' => null, + 'stream_factory' => null, ], 'tag_mode' => 'ban', 'tags_header' => 'X-Cache-Tags',