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

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, &$contentStopwatchEvent $event null)
  35.     {
  36.         $this->client $client;
  37.         $this->response $response;
  38.         $this->content = &$content;
  39.         $this->event $event;
  40.     }
  41.     /**
  42.      * @return array
  43.      */
  44.     public function __sleep()
  45.     {
  46.         throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
  47.     }
  48.     public function __wakeup()
  49.     {
  50.         throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
  51.     }
  52.     public function __destruct()
  53.     {
  54.         try {
  55.             $this->response->__destruct();
  56.         } finally {
  57.             if ($this->event && $this->event->isStarted()) {
  58.                 $this->event->stop();
  59.             }
  60.         }
  61.     }
  62.     public function getStatusCode(): int
  63.     {
  64.         try {
  65.             return $this->response->getStatusCode();
  66.         } finally {
  67.             if ($this->event && $this->event->isStarted()) {
  68.                 $this->event->lap();
  69.             }
  70.         }
  71.     }
  72.     public function getHeaders(bool $throw true): array
  73.     {
  74.         try {
  75.             return $this->response->getHeaders($throw);
  76.         } finally {
  77.             if ($this->event && $this->event->isStarted()) {
  78.                 $this->event->lap();
  79.             }
  80.         }
  81.     }
  82.     public function getContent(bool $throw true): string
  83.     {
  84.         try {
  85.             if (false === $this->content) {
  86.                 return $this->response->getContent($throw);
  87.             }
  88.             return $this->content $this->response->getContent(false);
  89.         } finally {
  90.             if ($this->event && $this->event->isStarted()) {
  91.                 $this->event->stop();
  92.             }
  93.             if ($throw) {
  94.                 $this->checkStatusCode($this->response->getStatusCode());
  95.             }
  96.         }
  97.     }
  98.     public function toArray(bool $throw true): array
  99.     {
  100.         try {
  101.             if (false === $this->content) {
  102.                 return $this->response->toArray($throw);
  103.             }
  104.             return $this->content $this->response->toArray(false);
  105.         } finally {
  106.             if ($this->event && $this->event->isStarted()) {
  107.                 $this->event->stop();
  108.             }
  109.             if ($throw) {
  110.                 $this->checkStatusCode($this->response->getStatusCode());
  111.             }
  112.         }
  113.     }
  114.     public function cancel(): void
  115.     {
  116.         $this->response->cancel();
  117.         if ($this->event && $this->event->isStarted()) {
  118.             $this->event->stop();
  119.         }
  120.     }
  121.     public function getInfo(string $type null)
  122.     {
  123.         return $this->response->getInfo($type);
  124.     }
  125.     /**
  126.      * Casts the response to a PHP stream resource.
  127.      *
  128.      * @return resource
  129.      *
  130.      * @throws TransportExceptionInterface   When a network error occurs
  131.      * @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
  132.      * @throws ClientExceptionInterface      On a 4xx when $throw is true
  133.      * @throws ServerExceptionInterface      On a 5xx when $throw is true
  134.      */
  135.     public function toStream(bool $throw true)
  136.     {
  137.         if ($throw) {
  138.             // Ensure headers arrived
  139.             $this->response->getHeaders(true);
  140.         }
  141.         if ($this->response instanceof StreamableInterface) {
  142.             return $this->response->toStream(false);
  143.         }
  144.         return StreamWrapper::createResource($this->response$this->client);
  145.     }
  146.     /**
  147.      * @internal
  148.      */
  149.     public static function stream(HttpClientInterface $clientiterable $responses, ?float $timeout): \Generator
  150.     {
  151.         $wrappedResponses = [];
  152.         $traceableMap = new \SplObjectStorage();
  153.         foreach ($responses as $r) {
  154.             if (!$r instanceof self) {
  155.                 throw new \TypeError(sprintf('"%s::stream()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.'TraceableHttpClient::class, get_debug_type($r)));
  156.             }
  157.             $traceableMap[$r->response] = $r;
  158.             $wrappedResponses[] = $r->response;
  159.             if ($r->event && !$r->event->isStarted()) {
  160.                 $r->event->start();
  161.             }
  162.         }
  163.         foreach ($client->stream($wrappedResponses$timeout) as $r => $chunk) {
  164.             if ($traceableMap[$r]->event && $traceableMap[$r]->event->isStarted()) {
  165.                 try {
  166.                     if ($chunk->isTimeout() || !$chunk->isLast()) {
  167.                         $traceableMap[$r]->event->lap();
  168.                     } else {
  169.                         $traceableMap[$r]->event->stop();
  170.                     }
  171.                 } catch (TransportExceptionInterface $e) {
  172.                     $traceableMap[$r]->event->stop();
  173.                     if ($chunk instanceof ErrorChunk) {
  174.                         $chunk->didThrow(false);
  175.                     } else {
  176.                         $chunk = new ErrorChunk($chunk->getOffset(), $e);
  177.                     }
  178.                 }
  179.             }
  180.             yield $traceableMap[$r] => $chunk;
  181.         }
  182.     }
  183.     private function checkStatusCode(int $code)
  184.     {
  185.         if (500 <= $code) {
  186.             throw new ServerException($this);
  187.         }
  188.         if (400 <= $code) {
  189.             throw new ClientException($this);
  190.         }
  191.         if (300 <= $code) {
  192.             throw new RedirectionException($this);
  193.         }
  194.     }
  195. }