From 3b4a05b2258164ad8fb2b77aec50760f7201b0f4 Mon Sep 17 00:00:00 2001 From: Lctrs Date: Tue, 14 Oct 2025 16:21:42 +0200 Subject: [PATCH] [HttpClient] Document `CachingHttpClient` compatible with RFC 9111 --- http_client.rst | 116 ++++++++++++++++++++++---- reference/configuration/framework.rst | 71 ++++++++++++++++ 2 files changed, 172 insertions(+), 15 deletions(-) diff --git a/http_client.rst b/http_client.rst index a1c8f09bc1d..19e14298185 100644 --- a/http_client.rst +++ b/http_client.rst @@ -740,6 +740,8 @@ making a request. Use the ``max_redirects`` setting to configure this behavior 'max_redirects' => 0, ]); +.. _http-client-retry-failed-requests: + Retry Failed Requests ~~~~~~~~~~~~~~~~~~~~~ @@ -1490,25 +1492,108 @@ Caching Requests and Responses ------------------------------ This component provides a :class:`Symfony\\Component\\HttpClient\\CachingHttpClient` -decorator that allows caching responses and serving them from the local storage -for next requests. The implementation leverages the -:class:`Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache` class under the hood -so that the :doc:`HttpKernel component ` needs to be -installed in your application:: +decorator that allows caching responses and serving them from the cache storage +for next requests as described in `RFC 9111`_. - use Symfony\Component\HttpClient\CachingHttpClient; - use Symfony\Component\HttpClient\HttpClient; - use Symfony\Component\HttpKernel\HttpCache\Store; +The implementation leverages a +:class:`tag aware cache ` under the hood +so the :doc:`Cache component ` needs to be +installed in your application. - $store = new Store('/path/to/cache/storage/'); - $client = HttpClient::create(); - $client = new CachingHttpClient($client, $store); +.. tip:: + + The implementation is asynchronous, so the response must be consumed + (e.g., via getContent() or streaming) for caching to occur. + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/framework.yaml + framework: + http_client: + scoped_clients: + example.client: + base_uri: 'https://example.com' + caching: + cache_pool: example_cache_pool + + cache: + pools: + example_cache_pool: + adapter: cache.adapter.redis_tag_aware + tags: true + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/framework.php + use Symfony\Config\FrameworkConfig; + + return static function (FrameworkConfig $framework): void { + $framework->httpClient()->scopedClient('example.client') + ->baseUri('https://example.com') + ->caching() + ->cachePool('example_cache_pool') + // ... + ; + + $framework->cache() + ->pool('example_cache_pool') + ->adapter('cache.adapter.redis_tag_aware') + ->tags(true) + ; + }; + + .. code-block:: php-standalone + + use Symfony\Component\Cache\Adapter\FilesystemTagAwareAdapter; + use Symfony\Component\HttpClient\CachingHttpClient; + use Symfony\Component\HttpClient\HttpClient; + + $cache = new FilesystemTagAwareAdapter(); + + $client = HttpClient::createForBaseUri('https://example.com'); + $cachingClient = new CachingHttpClient($client, $cache); + +.. tip:: + + It is also highly recommended to configure a :ref:`retry strategy ` + to gracefully handle cache inconsistency. - // this won't hit the network if the resource is already in the cache - $response = $client->request('GET', 'https://example.com/cacheable-resource'); +.. versionadded:: 7.4 -:class:`Symfony\\Component\\HttpClient\\CachingHttpClient` accepts a third argument -to set the options of the :class:`Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache`. + Compliance with `RFC 9111`_ and leveraging the + :doc:`Cache component ` was introduced in Symfony 7.4. + Prior to this, it used ``HttpCache`` from the HttpKernel component. Limit the Number of Requests ---------------------------- @@ -2494,5 +2579,6 @@ body:: .. _`idempotent method`: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods .. _`SSRF`: https://portswigger.net/web-security/ssrf .. _`RFC 6570`: https://www.rfc-editor.org/rfc/rfc6570 +.. _`RFC 9111`: https://www.rfc-editor.org/rfc/rfc9111 .. _`HAR`: https://w3c.github.io/web-performance/specs/HAR/Overview.html .. _`the Cookie HTTP request header`: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index a71ab711ad7..dd6ee6784f0 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -1661,6 +1661,77 @@ If this option is a boolean value, the response is buffered when the value is returned value is ``true`` (the closure receives as argument an array with the response headers). +caching +....... + +**type**: ``array`` + +This option configures the behavior of the HTTP client caching, including which +types of requests to cache and how many times. The behavior is +defined with the following options: + +* :ref:`cache_pool ` +* :ref:`shared ` +* :ref:`max_ttl ` + +.. code-block:: yaml + + # config/packages/framework.yaml + framework: + # ... + http_client: + # ... + default_options: + caching: + cache_pool: cache.app + shared: true + max_ttl: 86400 + + scoped_clients: + my_api.client: + # ... + caching: + cache_pool: my_taggable_pool + +.. versionadded:: 7.4 + + The ``caching`` option was introduced in Symfony 7.4. + +.. _reference-http-client-caching-cache-pool: + +cache_pool +"""""""""" + +**type**: ``string`` + +The service ID of the cache pool used to store the cached responses. The service +must implement the :class:`Symfony\\Contracts\\Cache\\TagAwareCacheInterface`. + +By default, it uses an instance of :class:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter` +wrapping the ``cache.app`` pool. + +.. _reference-http-client-caching-shared: + +shared +""""""" + +**type**: ``boolean`` **default**: ``true`` + +Whether the cache is shared or private. If ``true``, the cache +is `shared `_ +(default), if ``false``, the cache is +`private `_. + +.. _reference-http-client-caching-max-ttl: + +max_ttl +""""""""" + +**type**: ``integer`` **default**: ``null`` + +The maximum time-to-live (in seconds) for cached responses. Server-provided TTLs +are capped to this value if set. + cafile ......