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