@@ -1498,7 +1498,8 @@ This allows using them where native PHP streams are needed::
1498
1498
Extensibility
1499
1499
-------------
1500
1500
1501
- In order to extend the behavior of a base HTTP client, decoration is the way to go::
1501
+ If you want to extend the behavior of a base HTTP client, you can use
1502
+ :doc: `service decoration </service_container/service_decoration >`::
1502
1503
1503
1504
class MyExtendedHttpClient implements HttpClientInterface
1504
1505
{
@@ -1511,11 +1512,11 @@ In order to extend the behavior of a base HTTP client, decoration is the way to
1511
1512
1512
1513
public function request(string $method, string $url, array $options = []): ResponseInterface
1513
1514
{
1514
- // do what you want here with $method, $url and/or $options
1515
+ // process and/or change the $method, $url and/or $options as needed
1516
+ $response = $this->decoratedClient->request($method, $url, $options);
1515
1517
1516
- $response = $this->decoratedClient->request();
1517
-
1518
- //!\ calling any method on $response here would break async, see below for a better way
1518
+ // if you call here any method on $response, the HTTP request
1519
+ // won't be async; see below for a better way
1519
1520
1520
1521
return $response;
1521
1522
}
@@ -1526,13 +1527,13 @@ In order to extend the behavior of a base HTTP client, decoration is the way to
1526
1527
}
1527
1528
}
1528
1529
1529
- A decorator like this one is suited for use cases where processing the
1530
- requests' arguments is enough.
1530
+ A decorator like this one is useful in cases where processing the requests'
1531
+ arguments is enough. By decorating the ``on_progress `` option, you can
1532
+ even implement basic monitoring of the response. However, since calling
1533
+ responses' methods forces synchronous operations, doing so inside ``request() ``
1534
+ will break async.
1531
1535
1532
- By decorating the ``on_progress `` option, one can
1533
- even implement basic monitoring of the response. But since calling responses'
1534
- methods forces synchronous operations, doing so in ``request() `` breaks async.
1535
- The solution then is to also decorate the response object itself.
1536
+ The solution is to also decorate the response object itself.
1536
1537
:class: `Symfony\\ Component\\ HttpClient\\ TraceableHttpClient ` and
1537
1538
:class: `Symfony\\ Component\\ HttpClient\\ Response\\ TraceableResponse ` are good
1538
1539
examples as a starting point.
@@ -1551,10 +1552,9 @@ processing the stream of chunks as they come back from the network::
1551
1552
1552
1553
public function request(string $method, string $url, array $options = []): ResponseInterface
1553
1554
{
1554
- // do what you want here with $method, $url and/or $options
1555
+ // process and/or change the $method, $url and/or $options as needed
1555
1556
1556
1557
$passthru = function (ChunkInterface $chunk, AsyncContext $context) {
1557
-
1558
1558
// do what you want with chunks, e.g. split them
1559
1559
// in smaller chunks, group them, skip some, etc.
1560
1560
@@ -1571,19 +1571,19 @@ it shall return an
1571
1571
:class: `Symfony\\ Component\\ HttpClient\\ Response\\ AsyncResponse `.
1572
1572
1573
1573
The custom processing of chunks should happen in ``$passthru ``: this generator
1574
- is where you need to write your logic. It will be called for each chunk yielded by
1575
- the underlying client. A ``$passthru `` that does nothing would just ``yield $chunk; ``.
1576
- Of course, you could also yield a modified chunk, split the chunk into many
1574
+ is where you need to write your logic. It will be called for each chunk yielded
1575
+ by the underlying client. A ``$passthru `` that does nothing would just ``yield
1576
+ $chunk; ``. You could also yield a modified chunk, split the chunk into many
1577
1577
ones by yielding several times, or even skip a chunk altogether by issuing a
1578
1578
``return; `` instead of yielding.
1579
1579
1580
1580
In order to control the stream, the chunk passthru receives an
1581
1581
:class: `Symfony\\ Component\\ HttpClient\\ Response\\ AsyncContext ` as second
1582
1582
argument. This context object has methods to read the current state of the
1583
- response. It also allows altering the response stream with methods to create new
1584
- chunks of content, pause the stream, cancel the stream, change the info of the
1585
- response, replace the current request by another one or change the chunk passthru
1586
- itself.
1583
+ response. It also allows altering the response stream with methods to create
1584
+ new chunks of content, pause the stream, cancel the stream, change the info of
1585
+ the response, replace the current request by another one or change the chunk
1586
+ passthru itself.
1587
1587
1588
1588
Checking the test cases implemented in
1589
1589
:class: `Symfony\\ Component\\ HttpClient\\ Response\\ Tests\\ AsyncDecoratorTraitTest `
@@ -1594,10 +1594,10 @@ Here are the use cases that it simulates:
1594
1594
* send a preflight request, e.g. for authentication needs;
1595
1595
* issue subrequests and include their content in the main response's body.
1596
1596
1597
- The logic in :class: `Symfony\\ Component\\ HttpClient\\ Response\\ AsyncResponse ` has
1598
- many safety checks that will throw a ``LogicException `` if the chunk passthru
1599
- doesn't behave correctly; e.g. if a chunk is yielded after an ``isLast() `` one,
1600
- or if a content chunk is yielded before an ``isFirst() `` one, etc.
1597
+ The logic in :class: `Symfony\\ Component\\ HttpClient\\ Response\\ AsyncResponse `
1598
+ has many safety checks that will throw a ``LogicException `` if the chunk
1599
+ passthru doesn't behave correctly; e.g. if a chunk is yielded after an ``isLast() ``
1600
+ one, or if a content chunk is yielded before an ``isFirst() `` one, etc.
1601
1601
1602
1602
Testing HTTP Clients and Responses
1603
1603
----------------------------------
0 commit comments