Allow to easily ask Symfony not to set a response to private automatically

This commit is contained in:
Yanick Witschi 2018-03-27 10:50:49 +02:00 committed by Fabien Potencier
parent 5b27c2f61f
commit 0f36710708
2 changed files with 47 additions and 6 deletions

View File

@ -20,13 +20,22 @@ use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Sets the session in the request.
* Sets the session onto the request on the "kernel.request" event and saves
* it on the "kernel.response" event.
*
* In addition, if the session has been started it overrides the Cache-Control
* header in such a way that all caching is disabled in that case.
* If you have a scenario where caching responses with session information in
* them makes sense, you can disable this behaviour by setting the header
* AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*/
abstract class AbstractSessionListener implements EventSubscriberInterface
{
const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
protected $container;
public function __construct(ContainerInterface $container = null)
@ -60,13 +69,20 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
return;
}
$response = $event->getResponse();
if ($session->isStarted() || ($session instanceof Session && $session->hasBeenStarted())) {
$event->getResponse()
->setPrivate()
->setMaxAge(0)
->headers->addCacheControlDirective('must-revalidate');
if (!$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER)) {
$response
->setPrivate()
->setMaxAge(0)
->headers->addCacheControlDirective('must-revalidate');
}
}
// Always remove the internal header if present
$response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER);
if ($session->isStarted()) {
/*
* Saves the session, in case it is still open, before sending the response/headers.

View File

@ -56,7 +56,7 @@ class SessionListenerTest extends TestCase
$this->assertSame($session, $request->getSession());
}
public function testResponseIsPrivate()
public function testResponseIsPrivateIfSessionStarted()
{
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
$session->expects($this->exactly(2))->method('isStarted')->willReturn(false);
@ -74,6 +74,31 @@ class SessionListenerTest extends TestCase
$this->assertTrue($response->headers->hasCacheControlDirective('private'));
$this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate'));
$this->assertSame('0', $response->headers->getCacheControlDirective('max-age'));
$this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER));
}
public function testResponseIsStillPublicIfSessionStartedAndHeaderPresent()
{
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
$session->expects($this->exactly(2))->method('isStarted')->willReturn(false);
$session->expects($this->once())->method('hasBeenStarted')->willReturn(true);
$container = new Container();
$container->set('initialized_session', $session);
$listener = new SessionListener($container);
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock();
$response = new Response();
$response->setSharedMaxAge(60);
$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');
$listener->onKernelResponse(new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response));
$this->assertTrue($response->headers->hasCacheControlDirective('public'));
$this->assertFalse($response->headers->hasCacheControlDirective('private'));
$this->assertFalse($response->headers->hasCacheControlDirective('must-revalidate'));
$this->assertSame('60', $response->headers->getCacheControlDirective('s-maxage'));
$this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER));
}
public function testUninitilizedSession()