vendor/google/apiclient/src/Http/REST.php line 80

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright 2010 Google Inc.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. namespace Google\Http;
  18. use Google\Auth\HttpHandler\HttpHandlerFactory;
  19. use Google\Service\Exception as GoogleServiceException;
  20. use Google\Task\Runner;
  21. use GuzzleHttp\ClientInterface;
  22. use GuzzleHttp\Exception\RequestException;
  23. use GuzzleHttp\Psr7\Response;
  24. use Psr\Http\Message\RequestInterface;
  25. use Psr\Http\Message\ResponseInterface;
  26. /**
  27.  * This class implements the RESTful transport of apiServiceRequest()'s
  28.  */
  29. class REST
  30. {
  31.     /**
  32.      * Executes a Psr\Http\Message\RequestInterface and (if applicable) automatically retries
  33.      * when errors occur.
  34.      *
  35.      * @template T
  36.      * @param ClientInterface $client
  37.      * @param RequestInterface $request
  38.      * @param class-string<T>|false|null $expectedClass
  39.      * @param array $config
  40.      * @param array $retryMap
  41.      * @return mixed|T|null
  42.      * @throws \Google\Service\Exception on server side error (ie: not authenticated,
  43.      *  invalid or malformed post body, invalid url)
  44.      */
  45.     public static function execute(
  46.         ClientInterface $client,
  47.         RequestInterface $request,
  48.         $expectedClass null,
  49.         $config = [],
  50.         $retryMap null
  51.     ) {
  52.         $runner = new Runner(
  53.             $config,
  54.             sprintf('%s %s'$request->getMethod(), (string) $request->getUri()),
  55.             [self::class, 'doExecute'],
  56.             [$client$request$expectedClass]
  57.         );
  58.         if (null !== $retryMap) {
  59.             $runner->setRetryMap($retryMap);
  60.         }
  61.         return $runner->run();
  62.     }
  63.     /**
  64.      * Executes a Psr\Http\Message\RequestInterface
  65.      *
  66.      * @template T
  67.      * @param ClientInterface $client
  68.      * @param RequestInterface $request
  69.      * @param class-string<T>|false|null $expectedClass
  70.      * @return mixed|T|null
  71.      * @throws \Google\Service\Exception on server side error (ie: not authenticated,
  72.      *  invalid or malformed post body, invalid url)
  73.      */
  74.     public static function doExecute(ClientInterface $clientRequestInterface $request$expectedClass null)
  75.     {
  76.         try {
  77.             $httpHandler HttpHandlerFactory::build($client);
  78.             $response $httpHandler($request);
  79.         } catch (RequestException $e) {
  80.             // if Guzzle throws an exception, catch it and handle the response
  81.             if (!$e->hasResponse()) {
  82.                 throw $e;
  83.             }
  84.             $response $e->getResponse();
  85.             // specific checking for Guzzle 5: convert to PSR7 response
  86.             if (
  87.                 interface_exists('\GuzzleHttp\Message\ResponseInterface')
  88.                 && $response instanceof \GuzzleHttp\Message\ResponseInterface
  89.             ) {
  90.                 $response = new Response(
  91.                     $response->getStatusCode(),
  92.                     $response->getHeaders() ?: [],
  93.                     $response->getBody(),
  94.                     $response->getProtocolVersion(),
  95.                     $response->getReasonPhrase()
  96.                 );
  97.             }
  98.         }
  99.         return self::decodeHttpResponse($response$request$expectedClass);
  100.     }
  101.     /**
  102.      * Decode an HTTP Response.
  103.      * @static
  104.      *
  105.      * @template T
  106.      * @param RequestInterface $response The http response to be decoded.
  107.      * @param ResponseInterface $response
  108.      * @param class-string<T>|false|null $expectedClass
  109.      * @return mixed|T|null
  110.      * @throws \Google\Service\Exception
  111.      */
  112.     public static function decodeHttpResponse(
  113.         ResponseInterface $response,
  114.         ?RequestInterface $request null,
  115.         $expectedClass null
  116.     ) {
  117.         $code $response->getStatusCode();
  118.         // retry strategy
  119.         if (intVal($code) >= 400) {
  120.             // if we errored out, it should be safe to grab the response body
  121.             $body = (string) $response->getBody();
  122.             // Check if we received errors, and add those to the Exception for convenience
  123.             throw new GoogleServiceException($body$codenullself::getResponseErrors($body));
  124.         }
  125.         // Ensure we only pull the entire body into memory if the request is not
  126.         // of media type
  127.         $body self::decodeBody($response$request);
  128.         if ($expectedClass self::determineExpectedClass($expectedClass$request)) {
  129.             $json json_decode($bodytrue);
  130.             return new $expectedClass($json);
  131.         }
  132.         return $response;
  133.     }
  134.     private static function decodeBody(ResponseInterface $response, ?RequestInterface $request null)
  135.     {
  136.         if (self::isAltMedia($request)) {
  137.             // don't decode the body, it's probably a really long string
  138.             return '';
  139.         }
  140.         return (string) $response->getBody();
  141.     }
  142.     private static function determineExpectedClass($expectedClass, ?RequestInterface $request null)
  143.     {
  144.         // "false" is used to explicitly prevent an expected class from being returned
  145.         if (false === $expectedClass) {
  146.             return null;
  147.         }
  148.         // if we don't have a request, we just use what's passed in
  149.         if (null === $request) {
  150.             return $expectedClass;
  151.         }
  152.         // return what we have in the request header if one was not supplied
  153.         return $expectedClass ?: $request->getHeaderLine('X-Php-Expected-Class');
  154.     }
  155.     private static function getResponseErrors($body)
  156.     {
  157.         $json json_decode($bodytrue);
  158.         if (isset($json['error']['errors'])) {
  159.             return $json['error']['errors'];
  160.         }
  161.         return null;
  162.     }
  163.     private static function isAltMedia(?RequestInterface $request null)
  164.     {
  165.         if ($request && $qs $request->getUri()->getQuery()) {
  166.             parse_str($qs$query);
  167.             if (isset($query['alt']) && $query['alt'] == 'media') {
  168.                 return true;
  169.             }
  170.         }
  171.         return false;
  172.     }
  173. }