Skip to content

Commit

Permalink
[HttpKernel] added a way to change the ESI cache strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Feb 22, 2011
1 parent fb00539 commit cef86a3
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php
Expand Up @@ -5,6 +5,7 @@
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand Down
10 changes: 10 additions & 0 deletions src/Symfony/Component/HttpKernel/HttpCache/Esi.php
Expand Up @@ -41,6 +41,16 @@ public function __construct(array $contentTypes = array('text/html', 'text/xml',
$this->contentTypes = $contentTypes;
}

/**
* Returns a new cache strategy instance.
*
* @return EsiResponseCacheStrategyInterface A EsiResponseCacheStrategyInterface instance
*/
public function createCacheStrategy()
{
return new EsiResponseCacheStrategy();
}

/**
* Checks that at least one surrogate has ESI/1.0 capability.
*
Expand Down
@@ -0,0 +1,68 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This code is partially based on the Rack-Cache library by Ryan Tomayko,
* which is released under the MIT license.
* (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Response;

/**
* EsiResponseCacheStrategy knows how to compute the Response cache HTTP header
* based on the different ESI response cache headers.
*
* This implementation changes the master response TTL to the smallest TTL received
* or force validation if one of the ESI has validation cache strategy.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface
{
protected $cacheable = true;
protected $ttls = array();
protected $maxAges = array();

/**
* Adds a Response.
*
* @param Response $response
*/
public function add(Response $response)
{
if ($response->isValidateable()) {
$this->cacheable = false;
} else {
$this->ttls[] = $response->getTtl();
$this->maxAges[] = $response->getMaxAge();
}
}

/**
* Updates the Response HTTP headers based on the embedded Responses.
*
* @param Response $response
*/
public function update(Response $response)
{
if (!$this->cacheable) {
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');

return;
}

$maxAge = min($this->maxAges);
$response->setSharedMaxAge($maxAge);
$response->setMaxAge(0);
$response->headers->set('Age', $maxAge - min($this->ttls));
}
}
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This code is partially based on the Rack-Cache library by Ryan Tomayko,
* which is released under the MIT license.
* (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Response;

/**
* EsiResponseCacheStrategyInterface implementations know how to compute the
* Response cache HTTP header based on the different ESI response cache headers.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
interface EsiResponseCacheStrategyInterface
{
/**
* Adds a Response.
*
* @param Response $response
*/
function add(Response $response);

/**
* Updates the Response HTTP headers based on the embedded Responses.
*
* @param Response $response
*/
function update(Response $response);
}
39 changes: 7 additions & 32 deletions src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
Expand Up @@ -31,7 +31,7 @@ class HttpCache implements HttpKernelInterface
protected $store;
protected $request;
protected $esi;
protected $esiTtls;
protected $esiCacheStrategy;

/**
* Constructor.
Expand Down Expand Up @@ -137,7 +137,9 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
if (HttpKernelInterface::MASTER_REQUEST === $type) {
$this->traces = array();
$this->request = $request;
$this->esiTtls = array();
if (null !== $this->esi) {
$this->esiCacheStrategy = $this->esi->createCacheStrategy();
}
}

$path = $request->getPathInfo();
Expand All @@ -163,43 +165,16 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
}

if (null !== $this->esi) {
$this->addEsiTtl($response);
$this->esiCacheStrategy->add($response);

if ($request === $this->request) {
$this->updateResponseCacheControl($response);
if (HttpKernelInterface::MASTER_REQUEST === $type) {
$this->esiCacheStrategy->update($response);
}
}

return $response;
}

/**
* Stores the response's TTL locally.
*
* @param Response $response
*/
protected function addEsiTtl(Response $response)
{
$this->esiTtls[] = $response->isValidateable() ? -1 : $response->getTtl();
}

/**
* Changes the master response TTL to the smallest TTL received or force validation if
* one of the ESI has validation cache strategy.
*
* @param Response $response
*/
protected function updateResponseCacheControl(Response $response)
{
$ttl = min($this->esiTtls);
if (-1 === $ttl) {
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
} else {
$response->setSharedMaxAge($ttl);
$response->setMaxAge(0);
}
}

/**
* Forwards the Request to the backend without storing the Response in the cache.
*
Expand Down

0 comments on commit cef86a3

Please sign in to comment.