Skip to content

Commit fb24e7b

Browse files
Improve doc for HttpClient
1 parent d1edcd7 commit fb24e7b

File tree

2 files changed

+119
-99
lines changed

2 files changed

+119
-99
lines changed

components/http_client.rst

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ The HttpClient Component
66
========================
77

88
The HttpClient component is a low-level HTTP client with support for both
9-
PHP stream wrappers and cURL. It also provides utilities to consume APIs.
9+
PHP stream wrappers and cURL. It provides utilities to consume APIs and
10+
supports synchronous and asynchronous operations.
1011

1112
.. versionadded:: 4.3
1213

1314
The HttpClient component was introduced in Symfony 4.3.
1415

16+
.. TODO
17+
.. tell about implementation vs abstraction
18+
.. tell there are more options
19+
.. tell chunked + compression are supported out of the box
20+
1521
Installation
1622
------------
1723

@@ -69,14 +75,15 @@ Enabling HTTP/2 Support
6975
-----------------------
7076

7177
HTTP/2 is only supported when using the cURL-based transport and the libcurl
72-
version is >= 7.36.0. If you meet these requirements, you can enable HTTP/2
73-
explicitly via the ``http_version`` option::
78+
version is >= 7.36.0. If you meet these requirements, HTTP/2 will be used by
79+
default when the request protocol is ``https``. If you need it for ``http``,
80+
you must enable it explicitly via the ``http_version`` option::
7481

7582
$httpClient = HttpClient::create(['http_version' => '2.0']);
7683

77-
If you don't set the HTTP version explicitly, Symfony will use ``'2.0'`` only
78-
when the request protocol is ``https://`` (and the cURL requirements mentioned
79-
earlier are met).
84+
Support for HTTP/2 PUSH works out of the box when libcurl >= 7.61.0 is used with
85+
PHP >= 7.2.17 / 7.3.4: pushed responses are put into a temporary cache and are
86+
used when a subsequent request is triggered for the corresponding URLs.
8087

8188
Making Requests
8289
---------------
@@ -89,14 +96,13 @@ method to perform all kinds of HTTP requests::
8996
$response = $httpClient->request('PUT', 'https://...');
9097
// ...
9198

92-
Responses are always asynchronous, so they are ready as soon as the response
93-
HTTP headers are received, instead of waiting to receive the entire response
94-
contents::
99+
Responses are always asynchronous, so that the call to the method returns
100+
immediately instead of waiting to receive the response::
95101

102+
// code execution continues immediately; it doesn't wait to receive the response
96103
$response = $httpClient->request('GET', 'http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-desktop-amd64.iso');
97104

98-
// code execution continues immediately; it doesn't wait to receive the response
99-
// you can get the value of any HTTP response header
105+
// getting the response headers waits until they arrive
100106
$contentType = $response->getHeaders()['content-type'][0];
101107

102108
// trying to get the response contents will block the execution until
@@ -135,8 +141,8 @@ each request (which overrides any global authentication)::
135141
Query String Parameters
136142
~~~~~~~~~~~~~~~~~~~~~~~
137143

138-
You can either append them manually to the requested URL, or better, add them
139-
as an associative array to the ``query`` option::
144+
You can either append them manually to the requested URL, or define them as an
145+
associative array via the ``query`` option, that will be merged with the URL::
140146

141147
// it makes an HTTP GET request to https://httpbin.org/get?token=...&name=...
142148
$response = $httpClient->request('GET', 'https://httpbin.org/get', [
@@ -155,7 +161,7 @@ requests and the specific headers for each request::
155161

156162
// this header is added to all requests made by this client
157163
$httpClient = HttpClient::create(['headers' => [
158-
'Accept-Encoding' => 'gzip',
164+
'User-Agent' => 'My Fancy App',
159165
]]);
160166

161167
// this header is only included in this request and overrides the value
@@ -170,7 +176,7 @@ Uploading Data
170176
~~~~~~~~~~~~~~
171177

172178
This component provides several methods for uploading data using the ``body``
173-
option. You can use regular strings, closures and resources and they'll be
179+
option. You can use regular strings, closures, iterables and resources and they'll be
174180
processed automatically when making the requests::
175181

176182
$response = $httpClient->request('POST', 'https://...', [
@@ -264,7 +270,7 @@ following methods::
264270
Streaming Responses
265271
~~~~~~~~~~~~~~~~~~~
266272

267-
Call to the ``stream()`` method of the HTTP client to get *chunks* of the
273+
Call the ``stream()`` method of the HTTP client to get *chunks* of the
268274
response sequentially instead of waiting for the entire response::
269275

270276
$url = 'https://releases.ubuntu.com/18.04.1/ubuntu-18.04.1-desktop-amd64.iso';
@@ -286,13 +292,13 @@ response sequentially instead of waiting for the entire response::
286292
// response chunks implement Symfony\Contracts\HttpClient\ChunkInterface
287293
$fileHandler = fopen('/ubuntu.iso', 'w');
288294
foreach ($httpClient->stream($response) as $chunk) {
289-
fwrite($fileHandler, $chunk->getContent(););
295+
fwrite($fileHandler, $chunk->getContent());
290296
}
291297

292298
Handling Exceptions
293299
~~~~~~~~~~~~~~~~~~~
294300

295-
When the HTTP status code of the response is not in the 200-299 range (i.e. 3xx,
301+
When the HTTP status code of the response is in the 300-599 range (i.e. 3xx,
296302
4xx or 5xx) your code is expected to handle it. If you don't do that, the
297303
``getHeaders()`` and ``getContent()`` methods throw an appropriate exception::
298304

@@ -335,19 +341,15 @@ class to autoconfigure the HTTP client based on the requested URL::
335341
use Symfony\Component\HttpClient\ScopingHttpClient;
336342

337343
$client = HttpClient::create();
338-
$httpClient = new ScopingHttpClient($client, [
339-
// the key is a regexp which must match the beginning of the request URL
344+
$client = new ScopingHttpClient($client, [
345+
// the options defined as values apply only to the URLs matching
346+
// the regular expressions defined as keys
340347
'https://api\.github\.com/' => [
341348
'headers' => [
342349
'Accept' => 'application/vnd.github.v3+json',
343350
'Authorization' => 'token '.$githubToken,
344351
],
345352
],
346-
347-
// use a '*' wildcard to apply some options to all requests
348-
'*' => [
349-
// ...
350-
]
351353
]);
352354

353355
If the request URL is relative (because you use the ``base_uri`` option), the
@@ -362,30 +364,25 @@ regular expression applied to relative URLs::
362364
'base_uri' => 'https://api.github.com/',
363365
// ...
364366
],
365-
366-
'*' => [
367-
// ...
368-
]
369367
],
370368
// this is the regexp applied to all relative URLs
371369
'https://api\.github\.com/'
372370
);
373371

374-
PSR-7 and PSR-18 Compatibility
375-
------------------------------
372+
PSR-18 Compatibility
373+
--------------------
376374

377-
This component uses its own interfaces and exception classes different from the
378-
ones defined in `PSR-7`_ (HTTP message interfaces) and `PSR-18`_ (HTTP Client).
379-
However, it includes the :class:`Symfony\\Component\\HttpClient\\Psr18Client`
375+
This component uses and implements abstractions defined by the
376+
``symfony/contracts`` package. It also implements the `PSR-18`_ (HTTP Client)
377+
specifications via the :class:`Symfony\\Component\\HttpClient\\Psr18Client`
380378
class, which is an adapter to turn a Symfony ``HttpClientInterface`` into a
381379
PSR-18 ``ClientInterface``.
382380

383-
Before using it in your application, run the following commands to install the
384-
required dependencies:
381+
To use it, you need the ``psr/http-client`` package and a `PSR-17`_ implementation:
385382

386383
.. code-block:: terminal
387384
388-
# installs the base ClientInterface
385+
# installs the PSR-18 ClientInterface
389386
$ composer require psr/http-client
390387
391388
# installs an efficient implementation of response and stream factories
@@ -437,12 +434,11 @@ If you want to define multiple HTTP clients, use this other expanded configurati
437434
framework:
438435
# ...
439436
http_client:
440-
http_clients:
441-
crawler:
437+
scoped_clients:
438+
crawler.client:
442439
headers: [{ 'X-Powered-By': 'ACME App' }]
443440
http_version: '1.0'
444-
default:
445-
max_host_connections: 10
441+
some_api.client:
446442
max_redirects: 7
447443
448444
Injecting the HTTP Client Into Services
@@ -533,5 +529,5 @@ However, using ``MockResponse`` allows simulating chunked responses and timeouts
533529
$mockResponse = new MockResponse($body());
534530

535531
.. _`cURL PHP extension`: https://php.net/curl
536-
.. _`PSR-7`: https://www.php-fig.org/psr/psr-7/
532+
.. _`PSR-17`: https://www.php-fig.org/psr/psr-17/
537533
.. _`PSR-18`: https://www.php-fig.org/psr/psr-18/

reference/configuration/framework.rst

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -90,30 +90,51 @@ Configuration
9090

9191
* `http_client`_
9292

93-
* `auth_basic`_
94-
* `auth_bearer`_
95-
* `base_uri`_
96-
* `bindto`_
97-
* `buffer`_
98-
* `cafile`_
99-
* `capath`_
100-
* `capture_peer_cert_chain`_
101-
* `ciphers`_
102-
* `headers`_
103-
* `http_version`_
104-
* `local_cert`_
105-
* `local_pk`_
93+
* `default_options`_
94+
95+
* `bindto`_
96+
* `cafile`_
97+
* `capath`_
98+
* `ciphers`_
99+
* `headers`_
100+
* `http_version`_
101+
* `local_cert`_
102+
* `local_pk`_
103+
* `max_redirects`_
104+
* `no_proxy`_
105+
* `passphrase`_
106+
* `peer_fingerprint`_
107+
* `proxy`_
108+
* `resolve`_
109+
* `timeout`_
110+
* `verify_host`_
111+
* `verify_peer`_
112+
106113
* `max_host_connections`_
107-
* `max_redirects`_
108-
* `no_proxy`_
109-
* `passphrase`_
110-
* `peer_fingerprint`_
111-
* `proxy`_
112-
* `query`_
113-
* `resolve`_
114-
* `timeout`_
115-
* `verify_host`_
116-
* `verify_peer`_
114+
* `scoped_clients`_
115+
116+
* `scope`_
117+
* `auth_basic`_
118+
* `auth_bearer`_
119+
* `base_uri`_
120+
* `bindto`_
121+
* `cafile`_
122+
* `capath`_
123+
* `ciphers`_
124+
* `headers`_
125+
* `http_version`_
126+
* `local_cert`_
127+
* `local_pk`_
128+
* `max_redirects`_
129+
* `no_proxy`_
130+
* `passphrase`_
131+
* `peer_fingerprint`_
132+
* `proxy`_
133+
* `query`_
134+
* `resolve`_
135+
* `timeout`_
136+
* `verify_host`_
137+
* `verify_peer`_
117138

118139
* `http_method_override`_
119140
* `ide`_
@@ -662,39 +683,49 @@ when the request starts with this path.
662683
http_client
663684
~~~~~~~~~~~
664685

665-
If there's only one HTTP client defined in the app, you can configure it
666-
directly under the ``framework.http_client`` option:
686+
When the HttpClient component is installed, an HTTP client is available
687+
as a service named ``http_client`` or using the autowiring alias
688+
:class:`Symfony\\Constracts\\HttpClient\\HttpClientInterface`.
689+
690+
This service can be configured using ``framework.http_client.default_options``:
667691

668692
.. code-block:: yaml
669693
670694
# config/packages/framework.yaml
671695
framework:
672696
# ...
673697
http_client:
674-
headers: [{ 'X-Powered-By': 'ACME App' }]
675698
max_host_connections: 10
676-
max_redirects: 7
699+
default_options:
700+
headers: [{ 'X-Powered-By': 'ACME App' }]
701+
max_redirects: 7
677702
678-
If the app defines multiple HTTP clients, you must give them a unique name and
679-
define them under the type of HTTP client you are creating (``http_clients`` for
680-
regular clients and ``api_clients`` for clients that include utilities to
681-
consume APIs):
703+
Multiple pre-configured HTTP client services can be defined, each with its
704+
service name defined as a key under ``scoped_clients``. Scoped clients inherit
705+
the default options defined for the ``http_client`` service. You can override
706+
these options and can define a few others:
682707

683708
.. code-block:: yaml
684709
685710
# config/packages/framework.yaml
686711
framework:
687712
# ...
688713
http_client:
689-
http_clients:
690-
crawler:
691-
# ...
692-
default:
693-
# ...
694-
api_clients:
695-
github:
714+
scoped_clients:
715+
my_api.client:
716+
auth_bearer: secret_bearer_token
696717
# ...
697718
719+
Options defined for scoped clients apply only to URLs that match either their
720+
`base_uri`_ or the `scope`_ option when it is defined. Non-matching URLs always
721+
use default options.
722+
723+
Each scoped client also define a corresponding named autowiring alias.
724+
E.g. if you use
725+
``Symfony\Constracts\HttpClient\HttpClientInterface $myApiClient``
726+
as the type and name of an argument, autowiring will inject the ``my_api.client``
727+
service into your autowired classes.
728+
698729
auth_basic
699730
..........
700731

@@ -743,15 +774,6 @@ bindto
743774
A network interface name, IP address, a host name or a UNIX socket to use as the
744775
outgoing network interface.
745776

746-
buffer
747-
......
748-
749-
**type**: ``boolean``
750-
751-
.. TODO: improve this useless description
752-
753-
Indicates if the response should be buffered or not.
754-
755777
cafile
756778
......
757779

@@ -767,14 +789,6 @@ capath
767789

768790
The path to a directory that contains one or more certificate authority files.
769791

770-
capture_peer_cert_chain
771-
.......................
772-
773-
**type**: ``boolean``
774-
775-
If ``true``, the response includes a ``peer_certificate_chain`` attribute with
776-
the peer certificates (OpenSSL X.509 resources).
777-
778792
ciphers
779793
.......
780794

@@ -887,17 +901,27 @@ resolve
887901

888902
A list of hostnames and their IP addresses to pre-populate the DNS cache used by
889903
the HTTP client in order to avoid a DNS lookup for those hosts. This option is
890-
useful both to improve performance and to make your tests easier.
904+
useful to improve security when IPs are checked before the URL is passed to the
905+
client and to make your tests easier.
891906

892907
The value of this option is an associative array of ``domain => IP address``
893908
(e.g ``['symfony.com' => '46.137.106.254', ...]``).
894909

910+
scope
911+
.....
912+
913+
**type**: ``string``
914+
915+
For scoped clients only: the regular expression that the URL must match before
916+
applying all other non-default options. By default, the scope is derived from
917+
`base_uri`_.
918+
895919
timeout
896920
.......
897921

898922
**type**: ``float`` **default**: depends on your PHP config
899923

900-
Time, in seconds, to wait for a response. If the response takes longer, a
924+
Time, in seconds, to wait for a response. If the response stales for longer, a
901925
:class:`Symfony\\Component\\HttpClient\\Exception\\TransportException` is thrown.
902926
Its default value is the same as the value of PHP's `default_socket_timeout`_
903927
config option.

0 commit comments

Comments
 (0)