Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
103 - 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
 
18
use Google\Auth\HttpHandler\HttpHandlerFactory;
19
use GuzzleHttp\ClientInterface;
20
use GuzzleHttp\Exception\RequestException;
21
use GuzzleHttp\Psr7\Response;
22
use Psr\Http\Message\RequestInterface;
23
use Psr\Http\Message\ResponseInterface;
24
 
25
/**
26
 * This class implements the RESTful transport of apiServiceRequest()'s
27
 */
28
class Google_Http_REST
29
{
30
  /**
31
   * Executes a Psr\Http\Message\RequestInterface and (if applicable) automatically retries
32
   * when errors occur.
33
   *
34
   * @param Google_Client $client
35
   * @param Psr\Http\Message\RequestInterface $req
36
   * @return array decoded result
37
   * @throws Google_Service_Exception on server side error (ie: not authenticated,
38
   *  invalid or malformed post body, invalid url)
39
   */
40
  public static function execute(
41
      ClientInterface $client,
42
      RequestInterface $request,
43
      $expectedClass = null,
44
      $config = array(),
45
      $retryMap = null
46
  ) {
47
    $runner = new Google_Task_Runner(
48
        $config,
49
        sprintf('%s %s', $request->getMethod(), (string) $request->getUri()),
50
        array(get_class(), 'doExecute'),
51
        array($client, $request, $expectedClass)
52
    );
53
 
54
    if (null !== $retryMap) {
55
      $runner->setRetryMap($retryMap);
56
    }
57
 
58
    return $runner->run();
59
  }
60
 
61
  /**
62
   * Executes a Psr\Http\Message\RequestInterface
63
   *
64
   * @param Google_Client $client
65
   * @param Psr\Http\Message\RequestInterface $request
66
   * @return array decoded result
67
   * @throws Google_Service_Exception on server side error (ie: not authenticated,
68
   *  invalid or malformed post body, invalid url)
69
   */
70
  public static function doExecute(ClientInterface $client, RequestInterface $request, $expectedClass = null)
71
  {
72
    try {
73
      $httpHandler = HttpHandlerFactory::build($client);
74
      $response = $httpHandler($request);
75
    } catch (RequestException $e) {
76
      // if Guzzle throws an exception, catch it and handle the response
77
      if (!$e->hasResponse()) {
78
        throw $e;
79
      }
80
 
81
      $response = $e->getResponse();
82
      // specific checking for Guzzle 5: convert to PSR7 response
83
      if ($response instanceof \GuzzleHttp\Message\ResponseInterface) {
84
        $response = new Response(
85
            $response->getStatusCode(),
86
            $response->getHeaders() ?: [],
87
            $response->getBody(),
88
            $response->getProtocolVersion(),
89
            $response->getReasonPhrase()
90
        );
91
      }
92
    }
93
 
94
    return self::decodeHttpResponse($response, $request, $expectedClass);
95
  }
96
 
97
  /**
98
   * Decode an HTTP Response.
99
   * @static
100
   * @throws Google_Service_Exception
101
   * @param Psr\Http\Message\RequestInterface $response The http response to be decoded.
102
   * @param Psr\Http\Message\ResponseInterface $response
103
   * @return mixed|null
104
   */
105
  public static function decodeHttpResponse(
106
      ResponseInterface $response,
107
      RequestInterface $request = null,
108
      $expectedClass = null
109
  ) {
110
    $code = $response->getStatusCode();
111
 
112
    // retry strategy
113
    if (intVal($code) >= 400) {
114
      // if we errored out, it should be safe to grab the response body
115
      $body = (string) $response->getBody();
116
 
117
      // Check if we received errors, and add those to the Exception for convenience
118
      throw new Google_Service_Exception($body, $code, null, self::getResponseErrors($body));
119
    }
120
 
121
    // Ensure we only pull the entire body into memory if the request is not
122
    // of media type
123
    $body = self::decodeBody($response, $request);
124
 
125
    if ($expectedClass = self::determineExpectedClass($expectedClass, $request)) {
126
      $json = json_decode($body, true);
127
 
128
      return new $expectedClass($json);
129
    }
130
 
131
    return $response;
132
  }
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
 
141
    return (string) $response->getBody();
142
  }
143
 
144
  private static function determineExpectedClass($expectedClass, RequestInterface $request = null)
145
  {
146
    // "false" is used to explicitly prevent an expected class from being returned
147
    if (false === $expectedClass) {
148
      return null;
149
    }
150
 
151
    // if we don't have a request, we just use what's passed in
152
    if (null === $request) {
153
      return $expectedClass;
154
    }
155
 
156
    // return what we have in the request header if one was not supplied
157
    return $expectedClass ?: $request->getHeaderLine('X-Php-Expected-Class');
158
  }
159
 
160
  private static function getResponseErrors($body)
161
  {
162
    $json = json_decode($body, true);
163
 
164
    if (isset($json['error']['errors'])) {
165
      return $json['error']['errors'];
166
    }
167
 
168
    return null;
169
  }
170
 
171
  private static function isAltMedia(RequestInterface $request = null)
172
  {
173
    if ($request && $qs = $request->getUri()->getQuery()) {
174
      parse_str($qs, $query);
175
      if (isset($query['alt']) && $query['alt'] == 'media') {
176
        return true;
177
      }
178
    }
179
 
180
    return false;
181
  }
182
}