Skip to content

Commit 689f71b

Browse files
committed
Merge branch '4.3' into 4.4
* 4.3: [HttpClient] doc how to cancel a request + upload files
2 parents 23b59fa + 2215509 commit 689f71b

File tree

2 files changed

+96
-13
lines changed

2 files changed

+96
-13
lines changed

components/http_client.rst

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ processed automatically when making the requests::
186186
'body' => ['parameter1' => 'value1', '...'],
187187

188188
// using a closure to generate the uploaded data
189-
'body' => function () {
189+
'body' => function (int $size): string {
190190
// ...
191191
},
192192

@@ -199,12 +199,39 @@ When uploading data with the ``POST`` method, if you don't define the
199199
form data and adds the required
200200
``'Content-Type: application/x-www-form-urlencoded'`` header for you.
201201

202-
When uploading JSON payloads, use the ``json`` option instead of ``body``. The
203-
given content will be JSON-encoded automatically and the request will add the
204-
``Content-Type: application/json`` automatically too::
202+
When the ``body`` option is set as a closure, it will be called several times until
203+
it returns the empty string, which signals the end of the body. Each time, the
204+
closure should return a string smaller than the amount requested as argument.
205205

206-
$response = $httpClient->request('POST', 'https://...', [
207-
'json' => ['param1' => 'value1', '...'],
206+
A generator or any ``Traversable`` can also be used instead of a closure.
207+
208+
.. tip::
209+
210+
When uploading JSON payloads, use the ``json`` option instead of ``body``. The
211+
given content will be JSON-encoded automatically and the request will add the
212+
``Content-Type: application/json`` automatically too::
213+
214+
$response = $httpClient->request('POST', 'https://...', [
215+
'json' => ['param1' => 'value1', '...'],
216+
]);
217+
218+
$decodedPayload = $response->toArray();
219+
220+
To submit a form with file uploads, it is your responsibility to encode the body
221+
according to the ``multipart/form-data`` content-type. The
222+
:doc:`Symfony Mime </components/mime>` component makes it a few lines of code::
223+
224+
use Symfony\Component\Mime\Part\DataPart;
225+
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
226+
227+
$formFields = [
228+
'regular_field' => 'some value',
229+
'file_field' => DataPart::fromPath('/path/to/uploaded/file'),
230+
];
231+
$formData = new FormDataPart($formFields);
232+
$client->request('POST', 'https://...', [
233+
'headers' => $formData->getPreparedHeaders()->toArray(),
234+
'body' => $formData->bodyToIterable(),
208235
]);
209236

210237
Cookies
@@ -232,12 +259,47 @@ making a request. Use the ``max_redirects`` setting to configure this behavior
232259
'max_redirects' => 0,
233260
]);
234261

262+
HTTP Proxies
263+
~~~~~~~~~~~~
264+
265+
By default, this component honors the standard environment variables that your
266+
Operating System defines to direct the HTTP traffic through your local proxy.
267+
This means there is usually nothing to configure to have the client work with
268+
proxies, provided these env vars are properly configured.
269+
270+
You can still set or override these settings using the ``proxy`` and ``no_proxy``
271+
options:
272+
273+
* ``proxy`` should be set to the ``http://...`` URL of the proxy to get through
274+
275+
* ``no_proxy`` disables the proxy for a comma-separated list of hosts that do not
276+
require it to get reached.
277+
278+
Progress Callback
279+
~~~~~~~~~~~~~~~~~
280+
281+
By providing a callable to the ``on_progress`` option, one can track
282+
uploads/downloads as they complete. This callback is guaranteed to be called on
283+
DNS resolution, on arrival of headers and on completion; additionally it is
284+
called when new data is uploaded or downloaded and at least once per second::
285+
286+
$response = $httpClient->request('GET', 'https://...', [
287+
'on_progress' => function (int $dlNow, int $dlSize, array $info): void {
288+
// $dlNow is the number of bytes downloaded so far
289+
// $dlSize is the total size to be downloaded or -1 if it is unknown
290+
// $info is what $response->getInfo() would return at this very time
291+
},
292+
];
293+
294+
Any exceptions thrown from the callback will be wrapped in an instance of
295+
``TransportExceptionInterface`` and will abort the request.
296+
235297
Advanced Options
236298
~~~~~~~~~~~~~~~~
237299

238300
The :class:`Symfony\\Contracts\\HttpClient\\HttpClientInterface` defines all the
239301
options you might need to take full control of the way the request is performed,
240-
including progress monitoring, DNS pre-resolution, timeout, SSL parameters, etc.
302+
including DNS pre-resolution, SSL parameters, public key pinning, etc.
241303

242304
Processing Responses
243305
--------------------
@@ -257,6 +319,9 @@ following methods::
257319
// gets the response body as a string
258320
$content = $response->getContent();
259321

322+
// cancels the request/response
323+
$response->cancel();
324+
260325
// returns info coming from the transport layer, such as "response_headers",
261326
// "redirect_count", "start_time", "redirect_url", etc.
262327
$httpInfo = $response->getInfo();
@@ -285,10 +350,6 @@ response sequentially instead of waiting for the entire response::
285350
$response = $httpClient->request('GET', $url, [
286351
// optional: if you don't want to buffer the response in memory
287352
'buffer' => false,
288-
// optional: to display details about the response progress
289-
'on_progress' => function (int $dlNow, int $dlSize, array $info): void {
290-
// ...
291-
},
292353
]);
293354

294355
// Responses are lazy: this code is executed as soon as headers are received
@@ -303,6 +364,28 @@ response sequentially instead of waiting for the entire response::
303364
fwrite($fileHandler, $chunk->getContent());
304365
}
305366

367+
Canceling Responses
368+
~~~~~~~~~~~~~~~~~~~
369+
370+
To abort a request (e.g. because it didn't complete in due time, or you want to
371+
fetch only the first bytes of the response, etc.), you can either use the
372+
``cancel()`` method of ``ResponseInterface``::
373+
374+
$response->cancel()
375+
376+
Or throw an exception from a progress callback::
377+
378+
$response = $client->request('GET', 'https://...', [
379+
'on_progress' => function (int $dlNow, int $dlSize, array $info): void {
380+
// ...
381+
382+
throw new \MyException();
383+
},
384+
]);
385+
386+
The exception will be wrapped in an instance of ``TransportExceptionInterface``
387+
and will abort the request.
388+
306389
Handling Exceptions
307390
~~~~~~~~~~~~~~~~~~~
308391

@@ -546,7 +629,7 @@ PSR-18 Compatibility
546629
--------------------
547630

548631
This component uses and implements abstractions defined by the
549-
``symfony/contracts`` package. It also implements the `PSR-18`_ (HTTP Client)
632+
``symfony/http-client-contracts``. It also implements the `PSR-18`_ (HTTP Client)
550633
specifications via the :class:`Symfony\\Component\\HttpClient\\Psr18Client`
551634
class, which is an adapter to turn a Symfony ``HttpClientInterface`` into a
552635
PSR-18 ``ClientInterface``.

reference/configuration/framework.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ This service can be configured using ``framework.http_client.default_options``:
699699
http_client:
700700
max_host_connections: 10
701701
default_options:
702-
headers: [{ 'X-Powered-By': 'ACME App' }]
702+
headers: { 'X-Powered-By': 'ACME App' }
703703
max_redirects: 7
704704
705705
.. _reference-http-client-scoped-clients:

0 commit comments

Comments
 (0)