/** * @dataProvider getConfigureParams * * @param Response $response * @param Request $request * @param int $lifetime * @param array $private_headers * @param bool $expected_public */ public function testConfigure(Response $response, Request $request, $lifetime, array $private_headers, $expected_public) { $last_modified = new \DateTime(); if ($response->getEtag()) { $etag = $response->getEtag(); } else { $etag = md5('bar'); $this->key_builder->expects($this->once())->method('getEtag')->with($response)->will($this->returnValue($etag)); $etag = '"' . $etag . '"'; } $this->request_stack->expects($this->once())->method('getMasterRequest')->will($this->returnValue($request)); $expires = null; if ($lifetime >= 0) { $expires = clone $last_modified; $expires->modify(sprintf('now +%s seconds', $lifetime)); } $configurator = new ResponseConfigurator($this->key_builder, $this->request_stack, $private_headers); // exec test method $configured_response = $configurator->configure($response, $last_modified, $lifetime); $this->assertEquals($response, $configured_response); $this->assertEquals($last_modified, $response->getLastModified()); $this->assertEquals($etag, $response->getEtag()); $this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate')); $this->assertTrue($response->headers->hasCacheControlDirective($expected_public ? 'public' : 'private')); if ($lifetime >= 0) { $this->assertEquals($lifetime, $response->headers->getCacheControlDirective('max-age')); $this->assertEquals($expires, $response->getExpires()); if ($expected_public) { $this->assertEquals($lifetime, $response->headers->getCacheControlDirective('s-maxage')); } } }
/** * output image direct to browser, retrieve from cache if activated. * * @param Request $request * @param $id * @param string $format * * @return Response */ public function viewImageAction(Request $request, $id, $format = 'reference') { $media = $this->getMedia($id); if (!$media) { throw new NotFoundHttpException(sprintf('unable to find the media with the id : %s', $id)); } if (!$this->get('sonata.media.pool')->getDownloadSecurity($media)->isGranted($media, $request)) { throw new AccessDeniedException(); } /** @var \Networking\InitCmsBundle\Lib\PhpCache $phpCache */ $phpCache = $this->get('networking_init_cms.lib.php_cache'); if ($phpCache->isActive()) { if ($phpCache->get(sprintf('image_%s_updated_at', $id)) != $media->getUpdatedAt()) { $phpCache->delete('image_' . $id); } if (!($response = $phpCache->get('image_' . $media->getId()))) { $provider = $this->getProvider($media); if ($format == 'reference') { $file = $provider->getReferenceFile($media); } else { $file = $provider->getFilesystem()->get($provider->generatePrivateUrl($media, $format)); } $content = $file->getContent(); $headers = array_merge(array('Content-Type' => $media->getContentType(), 'Accept-Ranges' => 'bytes', 'Content-Length' => $media->getSize(), 'Content-Disposition' => sprintf('inline; filename="%s"', $media->getMetadataValue('filename'))), array()); $response = new Response($content, 200, $headers); $response->setPublic(); $response->setMaxAge(604800); $response->setLastModified($media->getUpdatedAt()); $response->getEtag(md5(sprintf('image_%s_updated_at', $id))); $phpCache->set('image_' . $media->getId(), $response, null); $phpCache->set(sprintf('image_%s_updated_at', $media->getId()), $media->getUpdatedAt(), null); } else { $phpCache->touch('image_' . $media->getId(), null); $phpCache->touch(sprintf('image_%s_updated_at', $media->getId()), null); } } else { $provider = $this->getProvider($media); if ($format == 'reference') { $file = $provider->getReferenceFile($media); } else { $file = $provider->getFilesystem()->get($provider->generatePrivateUrl($media, $format)); } $content = $file->getContent(); $headers = array_merge(array('Content-Type' => $media->getContentType(), 'Accept-Ranges' => 'bytes', 'Content-Length' => $media->getSize(), 'Content-Disposition' => sprintf('inline; filename="%s"', $media->getMetadataValue('filename'))), array()); $response = new Response($content, 200, $headers); $response->setPublic(); $response->setMaxAge(604800); $response->setLastModified($media->getUpdatedAt()); $response->getEtag(md5(sprintf('image_%s_updated_at', $id))); } return $response; }
protected function logResponse(Response $response, Request $request) { if ($response->getStatusCode() >= 500) { $color = LogLevel::ERROR; } elseif ($response->getStatusCode() >= 400) { $color = LogLevel::WARNING; } elseif ($response->getStatusCode() >= 300) { $color = LogLevel::NOTICE; } elseif ($response->getStatusCode() >= 200) { $color = LogLevel::INFO; } else { $color = LogLevel::INFO; } $msg = 'Response {response_status_code} for "{request_method} {request_uri}"'; $context = array('request_method' => $request->getMethod(), 'request_uri' => $request->getRequestUri(), 'response_status_code' => $response->getStatusCode(), 'response_charset' => $response->getCharset(), 'response_date' => $response->getDate(), 'response_etag' => $response->getEtag(), 'response_expires' => $response->getExpires(), 'response_last_modified' => $response->getLastModified(), 'response_max_age' => $response->getMaxAge(), 'response_protocol_version' => $response->getProtocolVersion(), 'response_ttl' => $response->getTtl(), 'response_vary' => $response->getVary()); $this->logger->log($color, $msg, $context); }
public function testSetCache() { $response = new Response(); //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public') try { $response->setCache(array("wrong option" => "value")); $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported'); } catch (\Exception $e) { $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported'); $this->assertContains('"wrong option"', $e->getMessage()); } $options = array('etag' => '"whatever"'); $response->setCache($options); $this->assertEquals($response->getEtag(), '"whatever"'); $now = new \DateTime(); $options = array('last_modified' => $now); $response->setCache($options); $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp()); $options = array('max_age' => 100); $response->setCache($options); $this->assertEquals($response->getMaxAge(), 100); $options = array('s_maxage' => 200); $response->setCache($options); $this->assertEquals($response->getMaxAge(), 200); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); $response->setCache(array('public' => true)); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); $response->setCache(array('public' => false)); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); $response->setCache(array('private' => true)); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); $response->setCache(array('private' => false)); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); }
/** * Validates that a cache entry is fresh. * * The original request is used as a template for a conditional * GET request with the backend. * * @param Request $request A Request instance * @param Response $entry A Response instance to validate * @param bool $catch Whether to process exceptions * * @return Response A Response instance */ protected function validate(Request $request, Response $entry, $catch = false) { $subRequest = clone $request; // send no head requests because we want content $subRequest->setMethod('GET'); // add our cached last-modified validator $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); // Add our cached etag validator to the environment. // We keep the etags from the client to handle the case when the client // has a different private valid entry which is not cached here. $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array(); $requestEtags = $request->getETags(); if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { $subRequest->headers->set('if_none_match', implode(', ', $etags)); } $response = $this->forward($subRequest, $catch, $entry); if (304 == $response->getStatusCode()) { $this->record($request, 'valid'); // return the response and not the cache entry if the response is valid but not cached $etag = $response->getEtag(); if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) { return $response; } $entry = clone $entry; $entry->headers->remove('Date'); foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { if ($response->headers->has($name)) { $entry->headers->set($name, $response->headers->get($name)); } } $response = $entry; } else { $this->record($request, 'invalid'); } if ($response->isCacheable()) { $this->store($request, $response); } return $response; }
/** * Set ETag. * * Need set Last-Modified before ETag * * @param Response $response * * @return ResponseConfigurator */ protected function setEtag(Response $response) { if (!$response->getEtag()) { $response->setEtag($this->key_builder->getEtag($response)); } return $this; }
/** * @test */ public function willSetETagOnModifiedRequest() { $this->invokeListener('PATCH'); $this->assertRegExp('/\\d{10}\\.\\d+/', (string) $this->response->getEtag()); }
/** * @param Response $response * @param Request $request * * @return array */ protected function createContext(Response $response, Request $request) { $context = array('response_status_code' => $response->getStatusCode(), 'response_charset' => $response->getCharset(), 'response_date' => $response->getDate(), 'response_etag' => $response->getEtag(), 'response_expires' => $response->getExpires(), 'response_last_modified' => $response->getLastModified(), 'response_max_age' => $response->getMaxAge(), 'response_protocol_version' => $response->getProtocolVersion(), 'response_ttl' => $response->getTtl(), 'response_vary' => $response->getVary(), 'request_method' => $request->getMethod(), 'request_uri' => $request->getRequestUri(), 'request_route' => $request->attributes->get('_route'), 'response_time' => $this->getTime($request), 'response_memory' => $this->getMemory()); return $context; }