/** * Decode an HTTP Response. * @static * @throws Google_ServiceException * @param Google_HttpRequest $response The http response to be decoded. * @return mixed|null */ public static function decodeHttpResponse($response) { $code = $response->getResponseHttpCode(); $body = $response->getResponseBody(); $decoded = null; if (intVal($code) >= 300) { $decoded = json_decode($body, true); $err = 'Error calling ' . $response->getRequestMethod() . ' ' . $response->getUrl(); if ($decoded != null && isset($decoded['error']['message']) && isset($decoded['error']['code'])) { // if we're getting a json encoded error definition, use that instead of the raw response // body for improved readability $err .= ": ({$decoded['error']['code']}) {$decoded['error']['message']}"; } else { $err .= ": ({$code}) {$body}"; } throw new Google_ServiceException($err, $code, null, $decoded['error']['errors']); } // Only attempt to decode the response, if the response code wasn't (204) 'no content' if ($code != '204') { $decoded = json_decode($body, true); if ($decoded === null || $decoded === "") { throw new Google_ServiceException("Invalid json in service response: {$body}"); } } return $decoded; }
/** * Check if an HTTP request can be cached by a private local cache. * * @static * @param Google_HttpRequest $resp * @return bool True if the request is cacheable. * False if the request is uncacheable. */ public static function isRequestCacheable(Google_HttpRequest $resp) { $method = $resp->getRequestMethod(); if (!in_array($method, self::$CACHEABLE_HTTP_METHODS)) { return false; } // Don't cache authorized requests/responses. // [rfc2616-14.8] When a shared cache receives a request containing an // Authorization field, it MUST NOT return the corresponding response // as a reply to any other request... if ($resp->getRequestHeader("authorization")) { return false; } return true; }
/** * Send the request via our curl object. * * @param curl $curl prepared curl object. * @param Google_HttpRequest $request The request. * @return string result of the request. */ private function do_request($curl, $request) { $url = $request->getUrl(); $method = $request->getRequestMethod(); switch (strtoupper($method)) { case 'POST': $ret = $curl->post($url, $request->getPostBody()); break; case 'GET': $ret = $curl->get($url); break; case 'HEAD': $ret = $curl->head($url); break; case 'PUT': $ret = $curl->put($url); break; default: throw new coding_exception('Unknown request type: ' . $method); break; } return $ret; }
/** * Send an API request to Google. * * This method overwrite the parent one so that the Google SDK will use our class * curl to proceed with the requests. This allows us to have control over the * proxy parameters and other stuffs. * * Note that the caching support of the Google SDK has been removed from this function. * * @param Google_HttpRequest $request the http request to be executed * @return Google_HttpRequest http request with the response http code, response * headers and response body filled in * @throws Google_IOException on curl or IO error */ public function makeRequest(Google_HttpRequest $request) { if (array_key_exists($request->getRequestMethod(), self::$ENTITY_HTTP_METHODS)) { $request = $this->processEntityRequest($request); } $curl = new curl(); $curl->setopt($this->curlParams); $curl->setopt(array('CURLOPT_URL' => $request->getUrl())); $requestHeaders = $request->getRequestHeaders(); if ($requestHeaders && is_array($requestHeaders)) { $parsed = array(); foreach ($requestHeaders as $k => $v) { $parsed[] = "{$k}: {$v}"; } $curl->setHeader($parsed); } $curl->setopt(array('CURLOPT_CUSTOMREQUEST' => $request->getRequestMethod(), 'CURLOPT_USERAGENT' => $request->getUserAgent())); $respdata = $this->do_request($curl, $request); // Retry if certificates are missing. if ($curl->get_errno() == CURLE_SSL_CACERT) { error_log('SSL certificate problem, verify that the CA cert is OK.' . ' Retrying with the CA cert bundle from google-api-php-client.'); $curl->setopt(array('CURLOPT_CAINFO' => dirname(__FILE__) . '/io/cacerts.pem')); $respdata = $this->do_request($curl, $request); } $infos = $curl->get_info(); $respheadersize = $infos['header_size']; $resphttpcode = (int) $infos['http_code']; $curlerrornum = $curl->get_errno(); $curlerror = $curl->error; if ($curlerrornum != CURLE_OK) { throw new Google_IOException("HTTP Error: ({$resphttpcode}) {$curlerror}"); } // Parse out the raw response into usable bits. list($responseHeaders, $responseBody) = self::parseHttpResponse($respdata, $respheadersize); // Fill in the apiHttpRequest with the response values. $request->setResponseHttpCode($resphttpcode); $request->setResponseHeaders($responseHeaders); $request->setResponseBody($responseBody); return $request; }