@@ -609,14 +609,57 @@ regular expression applied to relative URLs::
609609 'https://api\.github\.com/'
610610 );
611611
612- PSR-18 Compatibility
613- --------------------
612+ Interoperability
613+ ----------------
614+
615+ The component is interoperable with 3 different abstractions for HTTP clients:
616+ `Symfony Contracts `_, `PSR-18 `_ and `HTTPlug `_ v1 and v2. If your app uses
617+ libraries that need any of them, the component is compatible with them.
618+ They also benefit from autowiring aliases when the
619+ :ref: `framework bundle <framework-bundle-configuration >` is used.
620+
621+ If you are writing or maintaining a library that makes HTTP requests, you can
622+ decouple it from any specific HTTP client implementations by coding against
623+ either Symfony Contracts (recommended) or PSR-18 (which superseded HTTPlug).
624+
625+ Symfony Contracts
626+ ~~~~~~~~~~~~~~~~~
627+
628+ The interfaces found in the ``symfony/http-client-contracts `` package define
629+ the primary abstractions implemented by the component. Its entry point is the
630+ :class: `Symfony\\ Contracts\\ HttpClient\\ HttpClientInterface `. That's the
631+ interface you need to code against when a client is needed::
614632
615- This component uses and implements abstractions defined by the
616- ``symfony/http-client-contracts ``. It also implements the `PSR-18 `_ (HTTP Client)
617- specifications via the :class: `Symfony\\ Component\\ HttpClient\\ Psr18Client `
618- class, which is an adapter to turn a Symfony ``HttpClientInterface `` into a
619- PSR-18 ``ClientInterface ``.
633+ use Symfony\Contracts\HttpClient\HttpClientInterface;
634+
635+ class MyApiLayer
636+ {
637+ private $client;
638+
639+ public function __construct(HttpClientInterface $client)
640+ {
641+ $this->client = $client
642+ }
643+
644+ // [...]
645+ }
646+
647+ All request options mentionned above (e.g. timeout management) are also defined
648+ in the wordings of the interface, so that any compliant implementations (like this
649+ component) is guaranteed to provide them. That's a major difference with the
650+ PSR-18 abstraction, which provides none related to the transport itself.
651+
652+ Another major feature covered by the Symfony Contracts is async/multiplexing,
653+ as described in the previous sections.
654+
655+ PSR-18 and PSR-17
656+ ~~~~~~~~~~~~~~~~~
657+
658+ This component implements the `PSR-18 `_ (HTTP Client) specifications via the
659+ :class: `Symfony\\ Component\\ HttpClient\\ Psr18Client ` class, which is an adapter
660+ to turn a Symfony ``HttpClientInterface `` into a PSR-18 ``ClientInterface ``.
661+ This class also implements the relevant methods of `PSR-17 `_ to ease creating
662+ request objects.
620663
621664To use it, you need the ``psr/http-client `` package and a `PSR-17 `_ implementation:
622665
@@ -631,18 +674,73 @@ To use it, you need the ``psr/http-client`` package and a `PSR-17`_ implementati
631674
632675 Now you can make HTTP requests with the PSR-18 client as follows::
633676
634- use Nyholm\Psr7\Factory\Psr17Factory;
635677 use Symfony\Component\HttpClient\Psr18Client;
636678
637- $psr17Factory = new Psr17Factory();
638- $psr18Client = new Psr18Client();
679+ $client = new Psr18Client();
639680
640681 $url = 'https://symfony.com/versions.json';
641- $request = $psr17Factory ->createRequest('GET', $url);
642- $response = $psr18Client ->sendRequest($request);
682+ $request = $client ->createRequest('GET', $url);
683+ $response = $client ->sendRequest($request);
643684
644685 $content = json_decode($response->getBody()->getContents(), true);
645686
687+ .. versionadded :: 4.4
688+
689+ The PSR-17 factory methods have been added to ``Psr18Client `` in Symfony 4.4.
690+
691+ HTTPlug
692+ ~~~~~~~
693+
694+ .. versionadded :: 4.4
695+
696+ Support for HTTPlug was added in Symfony 4.4.
697+
698+ The `HTTPlug `_ specification pre-dates and is superseded by PSR-18. As such, you
699+ should not use it in newly written code. Yet, many libraries still require v1 or
700+ v2 of it. The component is interoperable with them thanks to the ``HttplugClient ``
701+ adapter class that it provides. Similarly to ``Psr18Client `` implementing
702+ relevant parts of PSR-17, ``HttplugClient `` also implements the factory methods
703+ defined in the related ``php-http/message-factory `` package.
704+
705+ Internally, the implementation relies on the ``Psr18Client ``, so that the
706+ ``psr/http-client `` package is needed to use this class::
707+
708+ .. code-block :: terminal
709+
710+ # Let's suppose php-http/httplug is already required by the lib you want to use
711+
712+ # installs the PSR-18 ClientInterface
713+ $ composer require psr/http-client
714+
715+ # installs an efficient implementation of response and stream factories
716+ # with autowiring aliases provided by Symfony Flex
717+ $ composer require nyholm/psr7
718+
719+ Let's say you want to instantiate a class with the following constructor,
720+ that requires HTTPlug dependencies::
721+
722+ use Http\Client\HttpClient;
723+ use Http\Message\RequestFactory;
724+ use Http\Message\StreamFactory;
725+
726+ class SomeSdk
727+ {
728+ public function __construct(
729+ HttpClient $httpClient,
730+ RequestFactory $requestFactory,
731+ StreamFactory $streamFactory
732+ )
733+ // [...]
734+ }
735+
736+ Because ``HttplugClient `` implements the 3 interfaces, you can use it this way::
737+
738+ use Symfony\Component\HttpClient\HttplugClient;
739+
740+ $httpClient = new HttplugClient();
741+
742+ $apiClient = new SomeSdk($httpClient, $httpClient, $httpClient);
743+
646744Symfony Framework Integration
647745-----------------------------
648746
@@ -765,3 +863,5 @@ However, using ``MockResponse`` allows simulating chunked responses and timeouts
765863.. _`cURL PHP extension` : https://php.net/curl
766864.. _`PSR-17` : https://www.php-fig.org/psr/psr-17/
767865.. _`PSR-18` : https://www.php-fig.org/psr/psr-18/
866+ .. _`HTTPlug` : https://github.com/php-http/httplug/#readme
867+ .. _`Symfony Contracts` : https://github.com/symfony/contracts
0 commit comments