/** * Revalidate a cached response * * @param RequestInterface $request Request to revalidate * @param Response $response Response to revalidate * * @return bool */ public function revalidate(RequestInterface $request, Response $response) { $revalidate = clone $request; $revalidate->getEventDispatcher()->removeSubscriber($this); $revalidate->removeHeader('Pragma')->removeHeader('Cache-Control')->setHeader('If-Modified-Since', $response->getDate()); if ($response->getEtag()) { $revalidate->setHeader('If-None-Match', '"' . $response->getEtag() . '"'); } try { $validateResponse = $revalidate->send(); if ($validateResponse->getStatusCode() == 200) { // The server does not support validation, so use this response $request->setResponse($validateResponse); // Store this response in cache if possible if ($validateResponse->canCache()) { $this->saveCache($this->getCacheKey($request), $validateResponse, $validateResponse->getMaxAge()); } return false; } if ($validateResponse->getStatusCode() == 304) { // Make sure that this response has the same ETage if ($validateResponse->getEtag() != $response->getEtag()) { return false; } // Replace cached headers with any of these headers from the // origin server that might be more up to date $modified = false; foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { if ($validateResponse->hasHeader($name)) { $modified = true; $response->setHeader($name, $validateResponse->getHeader($name)); } } // Store the updated response in cache if ($modified && $response->canCache()) { $this->saveCache($this->getCacheKey($request), $response, $response->getMaxAge()); } return true; } } catch (BadResponseException $e) { // 404 errors mean the resource no longer exists, so remove from // cache, and prevent an additional request by throwing the exception if ($e->getResponse()->getStatusCode() == 404) { $this->getCacheAdapter()->delete($this->getCacheKey($request)); throw $e; } } // Other exceptions encountered in the revalidation request are ignored // in hopes that sending a request to the origin server will fix it return false; }
public function canCacheResponse(Response $response) { return $response->isSuccessful() && $response->canCache(); }
public function isCacheable() { return $this->_response->canCache(); }
/** * Handle a 304 response and ensure that it is still valid * * @param RequestInterface $request Request that was sent * @param Response $validateResponse Response received * @param Response $response Original cached response * * @return bool Returns true if valid, false if invalid */ protected function handle304Response(RequestInterface $request, Response $validateResponse, Response $response) { static $replaceHeaders = array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'); // Make sure that this response has the same ETag if ($validateResponse->getEtag() != $response->getEtag()) { return false; } // Replace cached headers with any of these headers from the // origin server that might be more up to date $modified = false; foreach ($replaceHeaders as $name) { if ($validateResponse->hasHeader($name)) { $modified = true; $response->setHeader($name, $validateResponse->getHeader($name)); } } // Store the updated response in cache if ($modified && $response->canCache()) { $this->storage->cache($this->cacheKey->getCacheKey($request), $response, $response->getMaxAge()); } return true; }
/** * @covers Guzzle\Http\Message\Response::canCache */ public function testDeterminesIfItCanBeCached() { $this->assertTrue($this->getResponse(200)->canCache()); $this->assertTrue($this->getResponse(410)->canCache()); $this->assertFalse($this->getResponse(404)->canCache()); $this->assertTrue($this->getResponse(200, array('Cache-Control' => 'public'))->canCache()); // This has the no-store directive $this->assertFalse($this->getResponse(200, array('Cache-Control' => 'private, no-store'))->canCache()); // The body cannot be read, so it cannot be cached $tmp = tempnam('/tmp', 'not-readable'); $resource = fopen($tmp, 'w'); $this->assertFalse($this->getResponse(200, array('Transfer-Encoding' => 'chunked'), EntityBody::factory($resource, 10))->canCache()); unlink($tmp); // The body is 0 length, cannot be read, so it can be cached $tmp = tempnam('/tmp', 'not-readable'); $resource = fopen($tmp, 'w'); $this->assertTrue($this->getResponse(200, array(array('Content-Length' => 0)), EntityBody::factory($resource, 0))->canCache()); unlink($tmp); // When an HTTPS request is sent and the Cache-Control directive does // not include a 'public' value, then the response is not to be cached $request = RequestFactory::getInstance()->create('GET', 'https://www.test.com/'); $response = new Response(200); $response->setRequest($request); $this->assertFalse($response->canCache()); // This response can be cache because it is public $response->setHeader('Cache-Control', 'public'); $this->assertTrue($response->canCache()); }