/** * Decode an HTTP Response. * @static * @throws apiServiceException * @param apiHttpRequest $response The http response to be decoded. * @return mixed|null */ static function decodeHttpResponse($response) { $code = $response->getResponseHttpCode(); $body = $response->getResponseBody(); $decoded = null; if ($code != '200' && $code != '201' && $code != '204') { $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 apiServiceException($err, $code); } // 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) { throw new apiServiceException("Invalid json in service response: {$body}"); } } return $decoded; }
/** * Check if an HTTP request can be cached by a private local cache. * * @static * @param apiHttpRequest $resp * @return bool True if the request is cacheable. * False if the request is uncacheable. */ public static function isRequestCacheable(apiHttpRequest $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; }
/** * Check if an HTTP response can be cached by a private local cache. * * @static * @param apiHttpRequest $resp * @return bool True if the response is cacheable. * False if the response is un-cacheable. */ public static function isResponseCacheable(apiHttpRequest $resp) { $method = $resp->getRequestMethod(); if (!in_array($method, self::$CACHEABLE_HTTP_METHODS)) { return false; } $code = $resp->getResponseHttpCode(); if (!in_array($code, self::$CACHEABLE_STATUS_CODES)) { return false; } // The resource is uncacheable if the resource is already expired and // the resource doesn't have an ETag for revalidation. $etag = $resp->getResponseHeader("etag"); if (self::isExpired($resp) && $etag == false) { return false; } // [rfc2616-14.9.2] If [no-store is] sent in a response, a cache MUST NOT // store any part of either this response or the request that elicited it. $cacheControl = $resp->getParsedCacheControl(); if (in_array('no-store', $cacheControl)) { return false; } // Pragma: no-cache is an http request directive, but is occasionally // used as a response header incorrectly. $pragma = $resp->getResponseHeader('pragma'); if ($pragma == 'no-cache' || strpos($pragma, 'no-cache') !== false) { return false; } // [rfc2616-14.44] Vary: * is extremely difficult to cache. "It implies that // a cache cannot determine from the request headers of a subsequent request // whether this response is the appropriate representation." // Given this, we deem responses with the Vary header as uncacheable. $vary = $resp->getResponseHeader('vary'); if ($vary) { return false; } return true; }