Open Journal Systems  3.3.0
DefaultRevalidation.php
1 <?php
2 
3 namespace Guzzle\Plugin\Cache;
4 
8 
13 {
15  protected $storage;
16 
18  protected $canCache;
19 
25  {
26  $this->storage = $cache;
27  $this->canCache = $canCache ?: new DefaultCanCacheStrategy();
28  }
29 
30  public function revalidate(RequestInterface $request, Response $response)
31  {
32  try {
33  $revalidate = $this->createRevalidationRequest($request, $response);
34  $validateResponse = $revalidate->send();
35  if ($validateResponse->getStatusCode() == 200) {
36  return $this->handle200Response($request, $validateResponse);
37  } elseif ($validateResponse->getStatusCode() == 304) {
38  return $this->handle304Response($request, $validateResponse, $response);
39  }
40  } catch (BadResponseException $e) {
41  $this->handleBadResponse($e);
42  }
43 
44  // Other exceptions encountered in the revalidation request are ignored
45  // in hopes that sending a request to the origin server will fix it
46  return false;
47  }
48 
49  public function shouldRevalidate(RequestInterface $request, Response $response)
50  {
51  if ($request->getMethod() != RequestInterface::GET) {
52  return false;
53  }
54 
55  $reqCache = $request->getHeader('Cache-Control');
56  $resCache = $response->getHeader('Cache-Control');
57 
58  $revalidate = $request->getHeader('Pragma') == 'no-cache' ||
59  ($reqCache && ($reqCache->hasDirective('no-cache') || $reqCache->hasDirective('must-revalidate'))) ||
60  ($resCache && ($resCache->hasDirective('no-cache') || $resCache->hasDirective('must-revalidate')));
61 
62  // Use the strong ETag validator if available and the response contains no Cache-Control directive
63  if (!$revalidate && !$resCache && $response->hasHeader('ETag')) {
64  $revalidate = true;
65  }
66 
67  return $revalidate;
68  }
69 
77  protected function handleBadResponse(BadResponseException $e)
78  {
79  // 404 errors mean the resource no longer exists, so remove from
80  // cache, and prevent an additional request by throwing the exception
81  if ($e->getResponse()->getStatusCode() == 404) {
82  $this->storage->delete($e->getRequest());
83  throw $e;
84  }
85  }
86 
95  protected function createRevalidationRequest(RequestInterface $request, Response $response)
96  {
97  $revalidate = clone $request;
98  $revalidate->removeHeader('Pragma')->removeHeader('Cache-Control');
99 
100  if ($response->getLastModified()) {
101  $revalidate->setHeader('If-Modified-Since', $response->getLastModified());
102  }
103 
104  if ($response->getEtag()) {
105  $revalidate->setHeader('If-None-Match', $response->getEtag());
106  }
107 
108  // Remove any cache plugins that might be on the request to prevent infinite recursive revalidations
109  $dispatcher = $revalidate->getEventDispatcher();
110  foreach ($dispatcher->getListeners() as $eventName => $listeners) {
111  foreach ($listeners as $listener) {
112  if (is_array($listener) && $listener[0] instanceof CachePlugin) {
113  $dispatcher->removeListener($eventName, $listener);
114  }
115  }
116  }
117 
118  return $revalidate;
119  }
120 
129  protected function handle200Response(RequestInterface $request, Response $validateResponse)
130  {
131  $request->setResponse($validateResponse);
132  if ($this->canCache->canCacheResponse($validateResponse)) {
133  $this->storage->cache($request, $validateResponse);
134  }
135 
136  return false;
137  }
138 
148  protected function handle304Response(RequestInterface $request, Response $validateResponse, Response $response)
149  {
150  static $replaceHeaders = array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified');
151 
152  // Make sure that this response has the same ETag
153  if ($validateResponse->getEtag() != $response->getEtag()) {
154  return false;
155  }
156 
157  // Replace cached headers with any of these headers from the
158  // origin server that might be more up to date
159  $modified = false;
160  foreach ($replaceHeaders as $name) {
161  if ($validateResponse->hasHeader($name)) {
162  $modified = true;
163  $response->setHeader($name, $validateResponse->getHeader($name));
164  }
165  }
166 
167  // Store the updated response in cache
168  if ($modified && $this->canCache->canCacheResponse($response)) {
169  $this->storage->cache($request, $response);
170  }
171 
172  return true;
173  }
174 }
Guzzle\Plugin\Cache\DefaultRevalidation\shouldRevalidate
shouldRevalidate(RequestInterface $request, Response $response)
Definition: DefaultRevalidation.php:55
Guzzle\Http\Message\RequestInterface
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Message/RequestInterface.php:16
Guzzle\Http\Message\RequestInterface\setResponse
setResponse(Response $response, $queued=false)
Guzzle\Http\Message\AbstractMessage\hasHeader
hasHeader($header)
Definition: AbstractMessage.php:133
Guzzle\Plugin\Cache\DefaultRevalidation\$storage
$storage
Definition: DefaultRevalidation.php:18
Guzzle\Plugin\Cache\DefaultRevalidation\revalidate
revalidate(RequestInterface $request, Response $response)
Definition: DefaultRevalidation.php:36
Guzzle\Http\Message\AbstractMessage\getHeader
getHeader($header)
Definition: AbstractMessage.php:95
Guzzle\Plugin\Cache
Definition: CacheKeyProviderInterface.php:3
Guzzle\Plugin\Cache\RevalidationInterface
Definition: RevalidationInterface.php:11
Guzzle\Plugin\Cache\DefaultCanCacheStrategy
Definition: DefaultCanCacheStrategy.php:11
Guzzle\Http\Message\Response
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Message/Response.php:17
Guzzle\Http\Message\MessageInterface\removeHeader
removeHeader($header)
Guzzle\Http\Message\RequestInterface\GET
const GET
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Message/RequestInterface.php:23
Guzzle\Plugin\Cache\DefaultRevalidation\createRevalidationRequest
createRevalidationRequest(RequestInterface $request, Response $response)
Definition: DefaultRevalidation.php:101
Guzzle\Plugin\Cache\DefaultRevalidation\handle304Response
handle304Response(RequestInterface $request, Response $validateResponse, Response $response)
Definition: DefaultRevalidation.php:154
Guzzle\Plugin\Cache\CanCacheStrategyInterface
Definition: CanCacheStrategyInterface.php:11
Guzzle\Plugin\Cache\DefaultRevalidation\$canCache
$canCache
Definition: DefaultRevalidation.php:24
Guzzle\Plugin\Cache\DefaultRevalidation\__construct
__construct(CacheStorageInterface $cache, CanCacheStrategyInterface $canCache=null)
Definition: DefaultRevalidation.php:30
Guzzle\Http\Exception\RequestException\getRequest
getRequest()
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Exception/RequestException.php:38
Guzzle\Http\Message\RequestInterface\getMethod
getMethod()
Guzzle\Http\Exception\BadResponseException\getResponse
getResponse()
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Exception/BadResponseException.php:68
Guzzle\Http\Message\MessageInterface\getHeader
getHeader($header)
Guzzle\Plugin\Cache\DefaultRevalidation
Definition: DefaultRevalidation.php:12
Guzzle\Plugin\Cache\DefaultRevalidation\handleBadResponse
handleBadResponse(BadResponseException $e)
Definition: DefaultRevalidation.php:83
Guzzle\Http\Message\Response\getEtag
getEtag()
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Message/Response.php:562
Guzzle\Plugin\Cache\CacheStorageInterface
Definition: CacheStorageInterface.php:11
Guzzle\Http\Exception\BadResponseException
Definition: lib/vendor/guzzle/guzzle/src/Guzzle/Http/Exception/BadResponseException.php:11
Guzzle\Plugin\Cache\CachePlugin
Definition: CachePlugin.php:27
Guzzle\Plugin\Cache\DefaultRevalidation\handle200Response
handle200Response(RequestInterface $request, Response $validateResponse)
Definition: DefaultRevalidation.php:135