Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
1 <?php 2 /* 3 * Copyright 2012 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 if (!class_exists('Google_Client')) { 19 require_once dirname(__FILE__) . '/../autoload.php'; 20 } 21 22 /** 23 * Implement the caching directives specified in rfc2616. This 24 * implementation is guided by the guidance offered in rfc2616-sec13. 25 */ 26 #[AllowDynamicProperties] 27 class Google_Http_CacheParser 28 { 29 public static $CACHEABLE_HTTP_METHODS = array('GET', 'HEAD'); 30 public static $CACHEABLE_STATUS_CODES = array('200', '203', '300', '301'); 31 32 /** 33 * Check if an HTTP request can be cached by a private local cache. 34 * 35 * @static 36 * @param Google_Http_Request $resp 37 * @return bool True if the request is cacheable. 38 * False if the request is uncacheable. 39 */ 40 public static function isRequestCacheable(Google_Http_Request $resp) 41 { 42 $method = $resp->getRequestMethod(); 43 if (! in_array($method, self::$CACHEABLE_HTTP_METHODS)) { 44 return false; 45 } 46 47 // Don't cache authorized requests/responses. 48 // [rfc2616-14.8] When a shared cache receives a request containing an 49 // Authorization field, it MUST NOT return the corresponding response 50 // as a reply to any other request... 51 if ($resp->getRequestHeader("authorization")) { 52 return false; 53 } 54 55 return true; 56 } 57 58 /** 59 * Check if an HTTP response can be cached by a private local cache. 60 * 61 * @static 62 * @param Google_Http_Request $resp 63 * @return bool True if the response is cacheable. 64 * False if the response is un-cacheable. 65 */ 66 public static function isResponseCacheable(Google_Http_Request $resp) 67 { 68 // First, check if the HTTP request was cacheable before inspecting the 69 // HTTP response. 70 if (false == self::isRequestCacheable($resp)) { 71 return false; 72 } 73 74 $code = $resp->getResponseHttpCode(); 75 if (! in_array($code, self::$CACHEABLE_STATUS_CODES)) { 76 return false; 77 } 78 79 // The resource is uncacheable if the resource is already expired and 80 // the resource doesn't have an ETag for revalidation. 81 $etag = $resp->getResponseHeader("etag"); 82 if (self::isExpired($resp) && $etag == false) { 83 return false; 84 } 85 86 // [rfc2616-14.9.2] If [no-store is] sent in a response, a cache MUST NOT 87 // store any part of either this response or the request that elicited it. 88 $cacheControl = $resp->getParsedCacheControl(); 89 if (isset($cacheControl['no-store'])) { 90 return false; 91 } 92 93 // Pragma: no-cache is an http request directive, but is occasionally 94 // used as a response header incorrectly. 95 $pragma = $resp->getResponseHeader('pragma'); 96 if ($pragma == 'no-cache' || strpos($pragma, 'no-cache') !== false) { 97 return false; 98 } 99 100 // [rfc2616-14.44] Vary: * is extremely difficult to cache. "It implies that 101 // a cache cannot determine from the request headers of a subsequent request 102 // whether this response is the appropriate representation." 103 // Given this, we deem responses with the Vary header as uncacheable. 104 $vary = $resp->getResponseHeader('vary'); 105 if ($vary) { 106 return false; 107 } 108 109 return true; 110 } 111 112 /** 113 * @static 114 * @param Google_Http_Request $resp 115 * @return bool True if the HTTP response is considered to be expired. 116 * False if it is considered to be fresh. 117 */ 118 public static function isExpired(Google_Http_Request $resp) 119 { 120 // HTTP/1.1 clients and caches MUST treat other invalid date formats, 121 // especially including the value “0”, as in the past. 122 $parsedExpires = false; 123 $responseHeaders = $resp->getResponseHeaders(); 124 125 if (isset($responseHeaders['expires'])) { 126 $rawExpires = $responseHeaders['expires']; 127 // Check for a malformed expires header first. 128 if (empty($rawExpires) || (is_numeric($rawExpires) && $rawExpires <= 0)) { 129 return true; 130 } 131 132 // See if we can parse the expires header. 133 $parsedExpires = strtotime($rawExpires); 134 if (false == $parsedExpires || $parsedExpires <= 0) { 135 return true; 136 } 137 } 138 139 // Calculate the freshness of an http response. 140 $freshnessLifetime = false; 141 $cacheControl = $resp->getParsedCacheControl(); 142 if (isset($cacheControl['max-age'])) { 143 $freshnessLifetime = $cacheControl['max-age']; 144 } 145 146 $rawDate = $resp->getResponseHeader('date'); 147 $parsedDate = strtotime($rawDate); 148 149 if (empty($rawDate) || false == $parsedDate) { 150 // We can't default this to now, as that means future cache reads 151 // will always pass with the logic below, so we will require a 152 // date be injected if not supplied. 153 throw new Google_Exception("All cacheable requests must have creation dates."); 154 } 155 156 if (false == $freshnessLifetime && isset($responseHeaders['expires'])) { 157 $freshnessLifetime = $parsedExpires - $parsedDate; 158 } 159 160 if (false == $freshnessLifetime) { 161 return true; 162 } 163 164 // Calculate the age of an http response. 165 $age = max(0, time() - $parsedDate); 166 if (isset($responseHeaders['age'])) { 167 $age = max($age, strtotime($responseHeaders['age'])); 168 } 169 170 return $freshnessLifetime <= $age; 171 } 172 173 /** 174 * Determine if a cache entry should be revalidated with by the origin. 175 * 176 * @param Google_Http_Request $response 177 * @return bool True if the entry is expired, else return false. 178 */ 179 public static function mustRevalidate(Google_Http_Request $response) 180 { 181 // [13.3] When a cache has a stale entry that it would like to use as a 182 // response to a client's request, it first has to check with the origin 183 // server to see if its cached entry is still usable. 184 return self::isExpired($response); 185 } 186 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body