vendor/symfony/http-client/Response/TraceableResponse.php line 214

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\HttpClient\Response;
  11. use Symfony\Component\HttpClient\Chunk\ErrorChunk;
  12. use Symfony\Component\HttpClient\Exception\ClientException;
  13. use Symfony\Component\HttpClient\Exception\RedirectionException;
  14. use Symfony\Component\HttpClient\Exception\ServerException;
  15. use Symfony\Component\HttpClient\TraceableHttpClient;
  16. use Symfony\Component\Stopwatch\StopwatchEvent;
  17. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  18. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  19. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  20. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  21. use Symfony\Contracts\HttpClient\HttpClientInterface;
  22. use Symfony\Contracts\HttpClient\ResponseInterface;
  23. /**
  24.  * @author Nicolas Grekas <p@tchwork.com>
  25.  *
  26.  * @internal
  27.  */
  28. class TraceableResponse implements ResponseInterfaceStreamableInterface
  29. {
  30.     private $client;
  31.     private $response;
  32.     private $content;
  33.     private $event;
  34.     public function __construct(HttpClientInterface $clientResponseInterface $response, &$content, ?StopwatchEvent $event null)
  35.     {
  36.         $this->client $client;
  37.         $this->response $response;
  38.         $this->content = &$content;
  39.         $this->event $event;
  40.     }
  41.     public function __sleep(): array
  42.     {
  43.         throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
  44.     }
  45.     public function __wakeup()
  46.     {
  47.         throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
  48.     }
  49.     public function __destruct()
  50.     {
  51.         try {
  52.             if (method_exists($this->response'__destruct')) {
  53.                 $this->response->__destruct();
  54.             }
  55.         } finally {
  56.             if ($this->event && $this->event->isStarted()) {
  57.                 $this->event->stop();
  58.             }
  59.         }
  60.     }
  61.     public function getStatusCode(): int
  62.     {
  63.         try {
  64.             return $this->response->getStatusCode();
  65.         } finally {
  66.             if ($this->event && $this->event->isStarted()) {
  67.                 $this->event->lap();
  68.             }
  69.         }
  70.     }
  71.     public function getHeaders(bool $throw true): array
  72.     {
  73.         try {
  74.             return $this->response->getHeaders($throw);
  75.         } finally {
  76.             if ($this->event && $this->event->isStarted()) {
  77.                 $this->event->lap();
  78.             }
  79.         }
  80.     }
  81.     public function getContent(bool $throw true): string
  82.     {
  83.         try {
  84.             if (false === $this->content) {
  85.                 return $this->response->getContent($throw);
  86.             }
  87.             return $this->content $this->response->getContent(false);
  88.         } finally {
  89.             if ($this->event && $this->event->isStarted()) {
  90.                 $this->event->stop();
  91.             }
  92.             if ($throw) {
  93.                 $this->checkStatusCode($this->response->getStatusCode());
  94.             }
  95.         }
  96.     }
  97.     public function toArray(bool $throw true): array
  98.     {
  99.         try {
  100.             if (false === $this->content) {
  101.                 return $this->response->toArray($throw);
  102.             }
  103.             return $this->content $this->response->toArray(false);
  104.         } finally {
  105.             if ($this->event && $this->event->isStarted()) {
  106.                 $this->event->stop();
  107.             }
  108.             if ($throw) {
  109.                 $this->checkStatusCode($this->response->getStatusCode());
  110.             }
  111.         }
  112.     }
  113.     public function cancel(): void
  114.     {
  115.         $this->response->cancel();
  116.         if ($this->event && $this->event->isStarted()) {
  117.             $this->event->stop();
  118.         }
  119.     }
  120.     public function getInfo(?string $type null)
  121.     {
  122.         return $this->response->getInfo($type);
  123.     }
  124.     /**
  125.      * Casts the response to a PHP stream resource.
  126.      *
  127.      * @return resource
  128.      *
  129.      * @throws TransportExceptionInterface   When a network error occurs
  130.      * @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
  131.      * @throws ClientExceptionInterface      On a 4xx when $throw is true
  132.      * @throws ServerExceptionInterface      On a 5xx when $throw is true
  133.      */
  134.     public function toStream(bool $throw true)
  135.     {
  136.         if ($throw) {
  137.             // Ensure headers arrived
  138.             $this->response->getHeaders(true);
  139.         }
  140.         if ($this->response instanceof StreamableInterface) {
  141.             return $this->response->toStream(false);
  142.         }
  143.         return StreamWrapper::createResource($this->response$this->client);
  144.     }
  145.     /**
  146.      * @internal
  147.      */
  148.     public static function stream(HttpClientInterface $clientiterable $responses, ?float $timeout): \Generator
  149.     {
  150.         $wrappedResponses = [];
  151.         $traceableMap = new \SplObjectStorage();
  152.         foreach ($responses as $r) {
  153.             if (!$r instanceof self) {
  154.                 throw new \TypeError(sprintf('"%s::stream()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.'TraceableHttpClient::class, get_debug_type($r)));
  155.             }
  156.             $traceableMap[$r->response] = $r;
  157.             $wrappedResponses[] = $r->response;
  158.             if ($r->event && !$r->event->isStarted()) {
  159.                 $r->event->start();
  160.             }
  161.         }
  162.         foreach ($client->stream($wrappedResponses$timeout) as $r => $chunk) {
  163.             if ($traceableMap[$r]->event && $traceableMap[$r]->event->isStarted()) {
  164.                 try {
  165.                     if ($chunk->isTimeout() || !$chunk->isLast()) {
  166.                         $traceableMap[$r]->event->lap();
  167.                     } else {
  168.                         $traceableMap[$r]->event->stop();
  169.                     }
  170.                 } catch (TransportExceptionInterface $e) {
  171.                     $traceableMap[$r]->event->stop();
  172.                     if ($chunk instanceof ErrorChunk) {
  173.                         $chunk->didThrow(false);
  174.                     } else {
  175.                         $chunk = new ErrorChunk($chunk->getOffset(), $e);
  176.                     }
  177.                 }
  178.             }
  179.             yield $traceableMap[$r] => $chunk;
  180.         }
  181.     }
  182.     private function checkStatusCode(int $code)
  183.     {
  184.         if (500 <= $code) {
  185.             throw new ServerException($this);
  186.         }
  187.         if (400 <= $code) {
  188.             throw new ClientException($this);
  189.         }
  190.         if (300 <= $code) {
  191.             throw new RedirectionException($this);
  192.         }
  193.     }
  194. }