123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- <?php
- /*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- use Google\Auth\HttpHandler\HttpHandlerFactory;
- use GuzzleHttp\ClientInterface;
- use GuzzleHttp\Exception\RequestException;
- use GuzzleHttp\Psr7\Response;
- use Psr\Http\Message\RequestInterface;
- use Psr\Http\Message\ResponseInterface;
-
- /**
- * This class implements the RESTful transport of apiServiceRequest()'s
- */
- class Google_Http_REST
- {
- /**
- * Executes a Psr\Http\Message\RequestInterface and (if applicable) automatically retries
- * when errors occur.
- *
- * @param Google_Client $client
- * @param Psr\Http\Message\RequestInterface $req
- * @return array decoded result
- * @throws Google_Service_Exception on server side error (ie: not authenticated,
- * invalid or malformed post body, invalid url)
- */
- public static function execute(
- ClientInterface $client,
- RequestInterface $request,
- $expectedClass = null,
- $config = array(),
- $retryMap = null
- ) {
- $runner = new Google_Task_Runner(
- $config,
- sprintf('%s %s', $request->getMethod(), (string) $request->getUri()),
- array(get_class(), 'doExecute'),
- array($client, $request, $expectedClass)
- );
-
- if (null !== $retryMap) {
- $runner->setRetryMap($retryMap);
- }
-
- return $runner->run();
- }
-
- /**
- * Executes a Psr\Http\Message\RequestInterface
- *
- * @param Google_Client $client
- * @param Psr\Http\Message\RequestInterface $request
- * @return array decoded result
- * @throws Google_Service_Exception on server side error (ie: not authenticated,
- * invalid or malformed post body, invalid url)
- */
- public static function doExecute(ClientInterface $client, RequestInterface $request, $expectedClass = null)
- {
- try {
- $httpHandler = HttpHandlerFactory::build($client);
- $response = $httpHandler($request);
- } catch (RequestException $e) {
- // if Guzzle throws an exception, catch it and handle the response
- if (!$e->hasResponse()) {
- throw $e;
- }
-
- $response = $e->getResponse();
- // specific checking for Guzzle 5: convert to PSR7 response
- if ($response instanceof \GuzzleHttp\Message\ResponseInterface) {
- $response = new Response(
- $response->getStatusCode(),
- $response->getHeaders() ?: [],
- $response->getBody(),
- $response->getProtocolVersion(),
- $response->getReasonPhrase()
- );
- }
- }
-
- return self::decodeHttpResponse($response, $request, $expectedClass);
- }
-
- /**
- * Decode an HTTP Response.
- * @static
- * @throws Google_Service_Exception
- * @param Psr\Http\Message\RequestInterface $response The http response to be decoded.
- * @param Psr\Http\Message\ResponseInterface $response
- * @return mixed|null
- */
- public static function decodeHttpResponse(
- ResponseInterface $response,
- RequestInterface $request = null,
- $expectedClass = null
- ) {
- $code = $response->getStatusCode();
-
- // retry strategy
- if (intVal($code) >= 400) {
- // if we errored out, it should be safe to grab the response body
- $body = (string) $response->getBody();
-
- // Check if we received errors, and add those to the Exception for convenience
- throw new Google_Service_Exception($body, $code, null, self::getResponseErrors($body));
- }
-
- // Ensure we only pull the entire body into memory if the request is not
- // of media type
- $body = self::decodeBody($response, $request);
-
- if ($expectedClass = self::determineExpectedClass($expectedClass, $request)) {
- $json = json_decode($body, true);
-
- return new $expectedClass($json);
- }
-
- return $response;
- }
-
- private static function decodeBody(ResponseInterface $response, RequestInterface $request = null)
- {
- if (self::isAltMedia($request)) {
- // don't decode the body, it's probably a really long string
- return '';
- }
-
- return (string) $response->getBody();
- }
-
- private static function determineExpectedClass($expectedClass, RequestInterface $request = null)
- {
- // "false" is used to explicitly prevent an expected class from being returned
- if (false === $expectedClass) {
- return null;
- }
-
- // if we don't have a request, we just use what's passed in
- if (null === $request) {
- return $expectedClass;
- }
-
- // return what we have in the request header if one was not supplied
- return $expectedClass ?: $request->getHeaderLine('X-Php-Expected-Class');
- }
-
- private static function getResponseErrors($body)
- {
- $json = json_decode($body, true);
-
- if (isset($json['error']['errors'])) {
- return $json['error']['errors'];
- }
-
- return null;
- }
-
- private static function isAltMedia(RequestInterface $request = null)
- {
- if ($request && $qs = $request->getUri()->getQuery()) {
- parse_str($qs, $query);
- if (isset($query['alt']) && $query['alt'] == 'media') {
- return true;
- }
- }
-
- return false;
- }
- }
|