From c5dc50de9b5b3d18bc37801b72282204e45e01d2 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 22 May 2016 01:52:26 +0200 Subject: [PATCH] Move duplicated logic from Esi/Ssi to an AbstractSurrogate Fabbot fixes Move duplicated logic from Esi/Ssi::process in AbstractSurrogate::removeFromControl Fabbot fixes Fix comment --- .../HttpCache/AbstractSurrogate.php | 138 +++++++++++++++++ .../Component/HttpKernel/HttpCache/Esi.php | 144 +----------------- .../Component/HttpKernel/HttpCache/Ssi.php | 100 +----------- 3 files changed, 145 insertions(+), 237 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php diff --git a/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php b/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php new file mode 100644 index 0000000000..4e5fc6a3d7 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php @@ -0,0 +1,138 @@ + + * + * 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\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Abstract class implementing Surrogate capabilities to Request and Response instances. + * + * @author Fabien Potencier + * @author Robin Chalas + */ +abstract class AbstractSurrogate implements SurrogateInterface +{ + protected $contentTypes; + protected $phpEscapeMap = array( + array('', '', '', ''), + ); + + /** + * Constructor. + * + * @param array $contentTypes An array of content-type that should be parsed for Surrogate information. + * (default: text/html, text/xml, application/xhtml+xml, and application/xml) + */ + public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) + { + $this->contentTypes = $contentTypes; + } + + /** + * Returns a new cache strategy instance. + * + * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance + */ + public function createCacheStrategy() + { + return new ResponseCacheStrategy(); + } + + /** + * {@inheritdoc} + */ + public function hasSurrogateCapability(Request $request) + { + if (null === $value = $request->headers->get('Surrogate-Capability')) { + return false; + } + + return false !== strpos($value, sprintf('%s/1.0', strtoupper($this->getName()))); + } + + /** + * {@inheritdoc} + */ + public function addSurrogateCapability(Request $request) + { + $current = $request->headers->get('Surrogate-Capability'); + $new = sprintf('symfony2="%s/1.0"', strtoupper($this->getName())); + + $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); + } + + /** + * {@inheritdoc} + */ + public function needsParsing(Response $response) + { + if (!$control = $response->headers->get('Surrogate-Control')) { + return false; + } + + $pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName())); + + return (bool) preg_match($pattern, $control); + } + + /** + * {@inheritdoc} + */ + public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) + { + $subRequest = Request::create($uri, Request::METHOD_GET, array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); + + try { + $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); + + if (!$response->isSuccessful()) { + throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); + } + + return $response->getContent(); + } catch (\Exception $e) { + if ($alt) { + return $this->handle($cache, $alt, '', $ignoreErrors); + } + + if (!$ignoreErrors) { + throw $e; + } + } + } + + /** + * Remove the Surrogate from the Surrogate-Control header. + * + * @param Response $response + */ + protected function removeFromControl(Response $response) + { + if (!$response->headers->has('Surrogate-Control')) { + return; + } + + $value = $response->headers->get('Surrogate-Control'); + $upperName = strtoupper($this->getName()); + + if (sprintf('content="%s/1.0"', $upperName) == $value) { + $response->headers->remove('Surrogate-Control'); + } elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) { + $response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value)); + } elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) { + $response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value)); + } + } +} diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php index c12d241fec..d09907ea62 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php @@ -13,7 +13,6 @@ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Esi implements the ESI capabilities to Request and Response instances. @@ -26,75 +25,15 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; * * @author Fabien Potencier */ -class Esi implements SurrogateInterface +class Esi extends AbstractSurrogate { - private $contentTypes; - private $phpEscapeMap = array( - array('', '', '', ''), - ); - - /** - * Constructor. - * - * @param array $contentTypes An array of content-type that should be parsed for ESI information. - * (default: text/html, text/xml, application/xhtml+xml, and application/xml) - */ - public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) - { - $this->contentTypes = $contentTypes; - } - public function getName() { return 'esi'; } /** - * Returns a new cache strategy instance. - * - * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance - */ - public function createCacheStrategy() - { - return new ResponseCacheStrategy(); - } - - /** - * Checks that at least one surrogate has ESI/1.0 capability. - * - * @param Request $request A Request instance - * - * @return bool true if one surrogate has ESI/1.0 capability, false otherwise - */ - public function hasSurrogateCapability(Request $request) - { - if (null === $value = $request->headers->get('Surrogate-Capability')) { - return false; - } - - return false !== strpos($value, 'ESI/1.0'); - } - - /** - * Adds ESI/1.0 capability to the given Request. - * - * @param Request $request A Request instance - */ - public function addSurrogateCapability(Request $request) - { - $current = $request->headers->get('Surrogate-Capability'); - $new = 'symfony2="ESI/1.0"'; - - $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); - } - - /** - * Adds HTTP headers to specify that the Response needs to be parsed for ESI. - * - * This method only adds an ESI HTTP header if the Response has some ESI tags. - * - * @param Response $response A Response instance + * {@inheritdoc} */ public function addSurrogateControl(Response $response) { @@ -104,30 +43,7 @@ class Esi implements SurrogateInterface } /** - * Checks that the Response needs to be parsed for ESI tags. - * - * @param Response $response A Response instance - * - * @return bool true if the Response needs to be parsed, false otherwise - */ - public function needsParsing(Response $response) - { - if (!$control = $response->headers->get('Surrogate-Control')) { - return false; - } - - return (bool) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control); - } - - /** - * Renders an ESI tag. - * - * @param string $uri A URI - * @param string $alt An alternate URI - * @param bool $ignoreErrors Whether to ignore errors or not - * @param string $comment A comment to add as an esi:include tag - * - * @return string + * {@inheritdoc} */ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '') { @@ -145,12 +61,7 @@ class Esi implements SurrogateInterface } /** - * Replaces a Response ESI tags with the included resource content. - * - * @param Request $request A Request instance - * @param Response $response A Response instance - * - * @return Response + * {@inheritdoc} */ public function process(Request $request, Response $response) { @@ -199,51 +110,6 @@ class Esi implements SurrogateInterface $response->headers->set('X-Body-Eval', 'ESI'); // remove ESI/1.0 from the Surrogate-Control header - if ($response->headers->has('Surrogate-Control')) { - $value = $response->headers->get('Surrogate-Control'); - if ('content="ESI/1.0"' == $value) { - $response->headers->remove('Surrogate-Control'); - } elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) { - $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value)); - } elseif (preg_match('#content="ESI/1.0",\s*#', $value)) { - $response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value)); - } - } - } - - /** - * Handles an ESI from the cache. - * - * @param HttpCache $cache An HttpCache instance - * @param string $uri The main URI - * @param string $alt An alternative URI - * @param bool $ignoreErrors Whether to ignore errors or not - * - * @return string - * - * @throws \RuntimeException - * @throws \Exception - */ - public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) - { - $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); - - try { - $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - - if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); - } - - return $response->getContent(); - } catch (\Exception $e) { - if ($alt) { - return $this->handle($cache, $alt, '', $ignoreErrors); - } - - if (!$ignoreErrors) { - throw $e; - } - } + $this->removeFromControl($response); } } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php index 43311b6dc8..3178c33515 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php @@ -13,32 +13,14 @@ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Ssi implements the SSI capabilities to Request and Response instances. * * @author Sebastian Krebs */ -class Ssi implements SurrogateInterface +class Ssi extends AbstractSurrogate { - private $contentTypes; - private $phpEscapeMap = array( - array('', '', '', ''), - ); - - /** - * Constructor. - * - * @param array $contentTypes An array of content-type that should be parsed for SSI information. - * (default: text/html, text/xml, application/xhtml+xml, and application/xml) - */ - public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) - { - $this->contentTypes = $contentTypes; - } - /** * {@inheritdoc} */ @@ -47,37 +29,6 @@ class Ssi implements SurrogateInterface return 'ssi'; } - /** - * {@inheritdoc} - */ - public function createCacheStrategy() - { - return new ResponseCacheStrategy(); - } - - /** - * {@inheritdoc} - */ - public function hasSurrogateCapability(Request $request) - { - if (null === $value = $request->headers->get('Surrogate-Capability')) { - return false; - } - - return false !== strpos($value, 'SSI/1.0'); - } - - /** - * {@inheritdoc} - */ - public function addSurrogateCapability(Request $request) - { - $current = $request->headers->get('Surrogate-Capability'); - $new = 'symfony2="SSI/1.0"'; - - $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); - } - /** * {@inheritdoc} */ @@ -88,18 +39,6 @@ class Ssi implements SurrogateInterface } } - /** - * {@inheritdoc} - */ - public function needsParsing(Response $response) - { - if (!$control = $response->headers->get('Surrogate-Control')) { - return false; - } - - return (bool) preg_match('#content="[^"]*SSI/1.0[^"]*"#', $control); - } - /** * {@inheritdoc} */ @@ -154,41 +93,6 @@ class Ssi implements SurrogateInterface $response->headers->set('X-Body-Eval', 'SSI'); // remove SSI/1.0 from the Surrogate-Control header - if ($response->headers->has('Surrogate-Control')) { - $value = $response->headers->get('Surrogate-Control'); - if ('content="SSI/1.0"' == $value) { - $response->headers->remove('Surrogate-Control'); - } elseif (preg_match('#,\s*content="SSI/1.0"#', $value)) { - $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="SSI/1.0"#', '', $value)); - } elseif (preg_match('#content="SSI/1.0",\s*#', $value)) { - $response->headers->set('Surrogate-Control', preg_replace('#content="SSI/1.0",\s*#', '', $value)); - } - } - } - - /** - * {@inheritdoc} - */ - public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) - { - $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); - - try { - $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - - if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); - } - - return $response->getContent(); - } catch (\Exception $e) { - if ($alt) { - return $this->handle($cache, $alt, '', $ignoreErrors); - } - - if (!$ignoreErrors) { - throw $e; - } - } + $this->removeFromControl($response); } }