vendor/symfony/http-client/Response/CommonResponseTrait.php line 44

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\Exception\ClientException;
  12. use Symfony\Component\HttpClient\Exception\JsonException;
  13. use Symfony\Component\HttpClient\Exception\RedirectionException;
  14. use Symfony\Component\HttpClient\Exception\ServerException;
  15. use Symfony\Component\HttpClient\Exception\TransportException;
  16. /**
  17.  * Implements common logic for response classes.
  18.  *
  19.  * @author Nicolas Grekas <p@tchwork.com>
  20.  *
  21.  * @internal
  22.  */
  23. trait CommonResponseTrait
  24. {
  25.     /**
  26.      * @var callable|null A callback that tells whether we're waiting for response headers
  27.      */
  28.     private $initializer;
  29.     private $shouldBuffer;
  30.     private $content;
  31.     private $offset 0;
  32.     private $jsonData;
  33.     /**
  34.      * {@inheritdoc}
  35.      */
  36.     public function getContent(bool $throw true): string
  37.     {
  38.         if ($this->initializer) {
  39.             self::initialize($this);
  40.         }
  41.         if ($throw) {
  42.             $this->checkStatusCode();
  43.         }
  44.         if (null === $this->content) {
  45.             $content null;
  46.             foreach (self::stream([$this]) as $chunk) {
  47.                 if (!$chunk->isLast()) {
  48.                     $content .= $chunk->getContent();
  49.                 }
  50.             }
  51.             if (null !== $content) {
  52.                 return $content;
  53.             }
  54.             if (null === $this->content) {
  55.                 throw new TransportException('Cannot get the content of the response twice: buffering is disabled.');
  56.             }
  57.         } else {
  58.             foreach (self::stream([$this]) as $chunk) {
  59.                 // Chunks are buffered in $this->content already
  60.             }
  61.         }
  62.         rewind($this->content);
  63.         return stream_get_contents($this->content);
  64.     }
  65.     /**
  66.      * {@inheritdoc}
  67.      */
  68.     public function toArray(bool $throw true): array
  69.     {
  70.         if ('' === $content $this->getContent($throw)) {
  71.             throw new JsonException('Response body is empty.');
  72.         }
  73.         if (null !== $this->jsonData) {
  74.             return $this->jsonData;
  75.         }
  76.         try {
  77.             $content json_decode($contenttrue512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR 0));
  78.         } catch (\JsonException $e) {
  79.             throw new JsonException($e->getMessage().sprintf(' for "%s".'$this->getInfo('url')), $e->getCode());
  80.         }
  81.         if (\PHP_VERSION_ID 70300 && \JSON_ERROR_NONE !== json_last_error()) {
  82.             throw new JsonException(json_last_error_msg().sprintf(' for "%s".'$this->getInfo('url')), json_last_error());
  83.         }
  84.         if (!\is_array($content)) {
  85.             throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned for "%s".'get_debug_type($content), $this->getInfo('url')));
  86.         }
  87.         if (null !== $this->content) {
  88.             // Option "buffer" is true
  89.             return $this->jsonData $content;
  90.         }
  91.         return $content;
  92.     }
  93.     /**
  94.      * {@inheritdoc}
  95.      */
  96.     public function toStream(bool $throw true)
  97.     {
  98.         if ($throw) {
  99.             // Ensure headers arrived
  100.             $this->getHeaders($throw);
  101.         }
  102.         $stream StreamWrapper::createResource($this);
  103.         stream_get_meta_data($stream)['wrapper_data']
  104.             ->bindHandles($this->handle$this->content);
  105.         return $stream;
  106.     }
  107.     public function __sleep(): array
  108.     {
  109.         throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
  110.     }
  111.     public function __wakeup()
  112.     {
  113.         throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
  114.     }
  115.     /**
  116.      * Closes the response and all its network handles.
  117.      */
  118.     abstract protected function close(): void;
  119.     private static function initialize(self $response): void
  120.     {
  121.         if (null !== $response->getInfo('error')) {
  122.             throw new TransportException($response->getInfo('error'));
  123.         }
  124.         try {
  125.             if (($response->initializer)($response, -0.0)) {
  126.                 foreach (self::stream([$response], -0.0) as $chunk) {
  127.                     if ($chunk->isFirst()) {
  128.                         break;
  129.                     }
  130.                 }
  131.             }
  132.         } catch (\Throwable $e) {
  133.             // Persist timeouts thrown during initialization
  134.             $response->info['error'] = $e->getMessage();
  135.             $response->close();
  136.             throw $e;
  137.         }
  138.         $response->initializer null;
  139.     }
  140.     private function checkStatusCode()
  141.     {
  142.         $code $this->getInfo('http_code');
  143.         if (500 <= $code) {
  144.             throw new ServerException($this);
  145.         }
  146.         if (400 <= $code) {
  147.             throw new ClientException($this);
  148.         }
  149.         if (300 <= $code) {
  150.             throw new RedirectionException($this);
  151.         }
  152.     }
  153. }