@@ -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
199199form 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
210237Cookies
@@ -257,6 +284,9 @@ following methods::
257284    // gets the response body as a string 
258285    $content = $response->getContent(); 
259286
287+     // cancels the request/response 
288+     $response->cancel(); 
289+ 
260290    // returns info coming from the transport layer, such as "response_headers", 
261291    // "redirect_count", "start_time", "redirect_url", etc. 
262292    $httpInfo = $response->getInfo(); 
@@ -303,6 +333,29 @@ response sequentially instead of waiting for the entire response::
303333        fwrite($fileHandler, $chunk->getContent()); 
304334    } 
305335
336+ Canceling Responses
337+ ~~~~~~~~~~~~~~~~~~~ 
338+ 
339+ To abort a request (e.g. because it didn't answer in due time, or you want to
340+ fetch only the first bytes of the response, etc.), you can either:
341+ 
342+ * use the ``cancel() `` method of ``ResponseInterface ``::
343+ 
344+       $response->cancel() 
345+ 
346+ * throw an exception from a progress callback::
347+ 
348+       $response = $client->request('GET', 'https://..;', [ 
349+         'on_progress' => function (int $dlNow, int $dlSize, array $info): void { 
350+             // ... 
351+ 
352+             throw new \MyException(); 
353+         }, 
354+       ]); 
355+ 
356+   The exception will be wrapped in a ``TransportExceptionInterface`` and will 
357+   abort the request. 
358+ 
306359Handling Exceptions
307360~~~~~~~~~~~~~~~~~~~ 
308361
@@ -529,7 +582,7 @@ PSR-18 Compatibility
529582-------------------- 
530583
531584This component uses and implements abstractions defined by the
532- ``symfony/contracts `` package . It also implements the `PSR-18 `_ (HTTP Client)
585+ ``symfony/http-client- contracts ``. It also implements the `PSR-18 `_ (HTTP Client)
533586specifications via the :class: `Symfony\\ Component\\ HttpClient\\ Psr18Client `
534587class, which is an adapter to turn a Symfony ``HttpClientInterface `` into a
535588PSR-18 ``ClientInterface ``.
0 commit comments