Skip to content

Commit 305d111

Browse files
committed
feature #10702 [HttpKernel][FrameworkBundle] SSI support (KingCrunch)
This PR was merged into the 2.6-dev branch. Discussion ---------- [HttpKernel][FrameworkBundle] SSI support | Q | A | ------------- | --- | Bug fix? | No | New feature? | Yes | BC breaks? | No | Deprecations? | No | Tests pass? | Yes | Fixed tickets | #9419 (, #10684) | License | MIT It does not support comments, or alternative URIs, or "continue" in case of errors. Maybe I can workaround that, but I've decided to left it out for this PR. Especially as far as I can see a "alternative URIs"-hack would _always_ lead to two requests, even if it's not needed. Commits ------- 06cea08 SSI support
2 parents 53afef7 + 6617460 commit 305d111

16 files changed

+942
-205
lines changed

EventListener/EsiListener.php

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,13 @@
1111

1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

14-
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
15-
use Symfony\Component\HttpKernel\KernelEvents;
16-
use Symfony\Component\HttpKernel\HttpCache\Esi;
17-
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18-
1914
/**
2015
* EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
2116
*
2217
* @author Fabien Potencier <[email protected]>
18+
*
19+
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use SurrogateListener instead
2320
*/
24-
class EsiListener implements EventSubscriberInterface
21+
class EsiListener extends SurrogateListener
2522
{
26-
private $esi;
27-
28-
/**
29-
* Constructor.
30-
*
31-
* @param Esi $esi An ESI instance
32-
*/
33-
public function __construct(Esi $esi = null)
34-
{
35-
$this->esi = $esi;
36-
}
37-
38-
/**
39-
* Filters the Response.
40-
*
41-
* @param FilterResponseEvent $event A FilterResponseEvent instance
42-
*/
43-
public function onKernelResponse(FilterResponseEvent $event)
44-
{
45-
if (!$event->isMasterRequest() || null === $this->esi) {
46-
return;
47-
}
48-
49-
$this->esi->addSurrogateControl($event->getResponse());
50-
}
51-
52-
public static function getSubscribedEvents()
53-
{
54-
return array(
55-
KernelEvents::RESPONSE => 'onKernelResponse',
56-
);
57-
}
5823
}

EventListener/SurrogateListener.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\EventListener;
13+
14+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
15+
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
16+
use Symfony\Component\HttpKernel\KernelEvents;
17+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18+
19+
/**
20+
* SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates
21+
*
22+
* @author Fabien Potencier <[email protected]>
23+
*/
24+
class SurrogateListener implements EventSubscriberInterface
25+
{
26+
private $surrogate;
27+
28+
/**
29+
* Constructor.
30+
*
31+
* @param SurrogateInterface $surrogate An SurrogateInterface instance
32+
*/
33+
public function __construct(SurrogateInterface $surrogate = null)
34+
{
35+
$this->surrogate = $surrogate;
36+
}
37+
38+
/**
39+
* Filters the Response.
40+
*
41+
* @param FilterResponseEvent $event A FilterResponseEvent instance
42+
*/
43+
public function onKernelResponse(FilterResponseEvent $event)
44+
{
45+
if (!$event->isMasterRequest() || null === $this->surrogate) {
46+
return;
47+
}
48+
49+
$this->surrogate->addSurrogateControl($event->getResponse());
50+
}
51+
52+
public static function getSubscribedEvents()
53+
{
54+
return array(
55+
KernelEvents::RESPONSE => 'onKernelResponse',
56+
);
57+
}
58+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Fragment;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpKernel\Controller\ControllerReference;
17+
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
18+
19+
/**
20+
* Implements Surrogate rendering strategy.
21+
*
22+
* @author Fabien Potencier <[email protected]>
23+
*/
24+
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
25+
{
26+
private $surrogate;
27+
private $inlineStrategy;
28+
29+
/**
30+
* Constructor.
31+
*
32+
* The "fallback" strategy when surrogate is not available should always be an
33+
* instance of InlineFragmentRenderer.
34+
*
35+
* @param SurrogateInterface $surrogate An Surrogate instance
36+
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
37+
*/
38+
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy)
39+
{
40+
$this->surrogate = $surrogate;
41+
$this->inlineStrategy = $inlineStrategy;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*
47+
* Note that if the current Request has no surrogate capability, this method
48+
* falls back to use the inline rendering strategy.
49+
*
50+
* Additional available options:
51+
*
52+
* * alt: an alternative URI to render in case of an error
53+
* * comment: a comment to add when returning the surrogate tag
54+
*
55+
* Note, that not all surrogate strategies support all options. For now
56+
* 'alt' and 'comment' are only supported by ESI.
57+
*
58+
* @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
59+
*/
60+
public function render($uri, Request $request, array $options = array())
61+
{
62+
if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
63+
return $this->inlineStrategy->render($uri, $request, $options);
64+
}
65+
66+
if ($uri instanceof ControllerReference) {
67+
$uri = $this->generateFragmentUri($uri, $request);
68+
}
69+
70+
$alt = isset($options['alt']) ? $options['alt'] : null;
71+
if ($alt instanceof ControllerReference) {
72+
$alt = $this->generateFragmentUri($alt, $request);
73+
}
74+
75+
$tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
76+
77+
return new Response($tag);
78+
}
79+
}

Fragment/EsiFragmentRenderer.php

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,69 +11,13 @@
1111

1212
namespace Symfony\Component\HttpKernel\Fragment;
1313

14-
use Symfony\Component\HttpFoundation\Request;
15-
use Symfony\Component\HttpFoundation\Response;
16-
use Symfony\Component\HttpKernel\Controller\ControllerReference;
17-
use Symfony\Component\HttpKernel\HttpCache\Esi;
18-
1914
/**
2015
* Implements the ESI rendering strategy.
2116
*
2217
* @author Fabien Potencier <[email protected]>
2318
*/
24-
class EsiFragmentRenderer extends RoutableFragmentRenderer
19+
class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
2520
{
26-
private $esi;
27-
private $inlineStrategy;
28-
29-
/**
30-
* Constructor.
31-
*
32-
* The "fallback" strategy when ESI is not available should always be an
33-
* instance of InlineFragmentRenderer.
34-
*
35-
* @param Esi $esi An Esi instance
36-
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when ESI is not supported
37-
*/
38-
public function __construct(Esi $esi = null, InlineFragmentRenderer $inlineStrategy)
39-
{
40-
$this->esi = $esi;
41-
$this->inlineStrategy = $inlineStrategy;
42-
}
43-
44-
/**
45-
* {@inheritdoc}
46-
*
47-
* Note that if the current Request has no ESI capability, this method
48-
* falls back to use the inline rendering strategy.
49-
*
50-
* Additional available options:
51-
*
52-
* * alt: an alternative URI to render in case of an error
53-
* * comment: a comment to add when returning an esi:include tag
54-
*
55-
* @see Symfony\Component\HttpKernel\HttpCache\ESI
56-
*/
57-
public function render($uri, Request $request, array $options = array())
58-
{
59-
if (!$this->esi || !$this->esi->hasSurrogateEsiCapability($request)) {
60-
return $this->inlineStrategy->render($uri, $request, $options);
61-
}
62-
63-
if ($uri instanceof ControllerReference) {
64-
$uri = $this->generateFragmentUri($uri, $request);
65-
}
66-
67-
$alt = isset($options['alt']) ? $options['alt'] : null;
68-
if ($alt instanceof ControllerReference) {
69-
$alt = $this->generateFragmentUri($alt, $request);
70-
}
71-
72-
$tag = $this->esi->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
73-
74-
return new Response($tag);
75-
}
76-
7721
/**
7822
* {@inheritdoc}
7923
*/

Fragment/SsiFragmentRenderer.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Fragment;
13+
14+
use Symfony\Component\HttpKernel\Controller\ControllerReference;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpKernel\UriSigner;
17+
18+
/**
19+
* Implements the ESI rendering strategy.
20+
*
21+
* @author Sebastian Krebs <[email protected]>
22+
*/
23+
class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
24+
{
25+
/** @var UriSigner */
26+
private $signer;
27+
28+
/**
29+
* Set uri signer
30+
*
31+
* @param UriSigner $signer
32+
*/
33+
public function setUriSigner(UriSigner $signer)
34+
{
35+
$this->signer = $signer;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function getName()
42+
{
43+
return 'ssi';
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true)
50+
{
51+
$uri = parent::generateFragmentUri($reference, $request, $absolute, $strict);
52+
53+
if ($this->signer) {
54+
$uri = $this->signer->sign($uri);
55+
}
56+
57+
return $uri;
58+
}
59+
}

0 commit comments

Comments
 (0)