bug #31121 [HttpKernel] Fix get session when the request stack is empty (yceruto)

This PR was merged into the 4.2 branch.

Discussion
----------

[HttpKernel] Fix get session when the request stack is empty

| Q             | A
| ------------- | ---
| Branch?       | 4.2
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT

This bug happen behind an exception on a kernel response event, when one collector (e.g. `RequestDataCollector`) is trying to get the request session and the request stack is currently empty.

**Reproducer**
https://github.com/yceruto/get-session-bug (`GET /`)

See logs on terminal:
```bash
Apr 15 20:29:03 |ERROR| PHP    2019-04-15T20:29:03-04:00 Call to a member function isSecure() on null
Apr 15 20:29:03 |ERROR| PHP    PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Call to a member function isSecure() on null in /home/yceruto/demos/getsession/vendor/symfony/http-kernel/EventListener/SessionListener.php:43
Apr 15 20:29:03 |DEBUG| PHP    Stack trace:
Apr 15 20:29:03 |DEBUG| PHP    #0 /home/yceruto/demos/getsession/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php(59): Symfony\Component\HttpKernel\EventListener\SessionListener->getSession()
Apr 15 20:29:03 |DEBUG| PHP    #1 /home/yceruto/demos/getsession/vendor/symfony/http-foundation/Request.php(707): Symfony\Component\HttpKernel\EventListener\AbstractSessionListener->Symfony\Component\HttpKernel\EventListener\{closure}()
Apr 15 20:29:03 |DEBUG| PHP    #2 /home/yceruto/demos/getsession/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php(65): Symfony\Component\HttpFoundation\Request->getSession()
Apr 15 20:29:03 |DEBUG| PHP    #3 /home/yceruto/demos/getsession/vendor/symfony/http-kernel/Profiler/Profiler.php(167): Symfony\Component\HttpKernel\DataCollector\RequestDataCollector->collect(Object(Symfony\Component\HttpFoundation\Request), Object(Symfony\Component\HttpFoundation\Respo in /home/yceruto/demos/getsession/vendor/symfony/http-kernel/EventListener/SessionListener.php on line 43
```

Friendly ping @nicolas-grekas as author of the previous PR https://github.com/symfony/symfony/pull/28244

Commits
-------

d62ca37ab6 Fix get session when the request stack is empty
This commit is contained in:
Nicolas Grekas 2019-04-17 16:59:26 +02:00
commit c009e60fbb
2 changed files with 12 additions and 1 deletions

View File

@ -40,7 +40,8 @@ class SessionListener extends AbstractSessionListener
if ($this->container->has('session_storage')
&& ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage
&& $this->container->get('request_stack')->getMasterRequest()->isSecure()
&& ($masterRequest = $this->container->get('request_stack')->getMasterRequest())
&& $masterRequest->isSecure()
) {
$storage->setOptions(['cookie_secure' => true]);
}

View File

@ -15,8 +15,10 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@ -41,8 +43,16 @@ class SessionListenerTest extends TestCase
{
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
$requestStack = $this->getMockBuilder(RequestStack::class)->getMock();
$requestStack->expects($this->once())->method('getMasterRequest')->willReturn(null);
$sessionStorage = $this->getMockBuilder(NativeSessionStorage::class)->getMock();
$sessionStorage->expects($this->never())->method('setOptions')->with(['cookie_secure' => true]);
$container = new Container();
$container->set('session', $session);
$container->set('request_stack', $requestStack);
$container->set('session_storage', $sessionStorage);
$request = new Request();
$listener = new SessionListener($container);