summaryrefslogtreecommitdiffstatshomepage
path: root/core/lib
diff options
context:
space:
mode:
Diffstat (limited to 'core/lib')
-rw-r--r--core/lib/Drupal/Core/DrupalKernel.php26
-rw-r--r--core/lib/Drupal/Core/StackMiddleware/Session.php31
-rw-r--r--core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php8
3 files changed, 57 insertions, 8 deletions
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index dd67a2b5416f..d778693888f6 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -28,6 +28,8 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
@@ -582,6 +584,11 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
(bool) Settings::get(RequestSanitizer::SANITIZE_LOG, FALSE)
);
+ // Ensure that there is a session on every request.
+ if (!$request->hasSession()) {
+ $this->initializeEphemeralSession($request);
+ }
+
$this->loadLegacyIncludes();
// Load all enabled modules.
@@ -1638,4 +1645,23 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
return $config['profile'] ?? NULL;
}
+ /**
+ * Initializes a session backed by in-memory store and puts it on the request.
+ *
+ * A simple in-memory store is sufficient for command line tools and tests.
+ * Web requests will be processed by the session middleware where the mock
+ * session is replaced by a session object backed with persistent storage and
+ * a real session handler.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The request.
+ *
+ * @see \Drupal\Core\StackMiddleware\Session::handle()
+ */
+ protected function initializeEphemeralSession(Request $request): void {
+ $session = new Session(new MockArraySessionStorage());
+ $session->start();
+ $request->setSession($session);
+ }
+
}
diff --git a/core/lib/Drupal/Core/StackMiddleware/Session.php b/core/lib/Drupal/Core/StackMiddleware/Session.php
index d9da60ac6025..94841e1508dd 100644
--- a/core/lib/Drupal/Core/StackMiddleware/Session.php
+++ b/core/lib/Drupal/Core/StackMiddleware/Session.php
@@ -49,19 +49,42 @@ class Session implements HttpKernelInterface {
* {@inheritdoc}
*/
public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response {
+ // Initialize and start a session for web requests. Command line tools and
+ // the parent site in functional tests must continue to use the ephemeral
+ // session initialized and started in DrupalKernel::preHandle().
if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli') {
- $session = $this->container->get($this->sessionServiceName);
- $session->start();
- $request->setSession($session);
+ $this->initializePersistentSession($request);
}
$result = $this->httpKernel->handle($request, $type, $catch);
- if ($type === self::MAIN_REQUEST && $request->hasSession()) {
+ if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli' && $request->hasSession()) {
$request->getSession()->save();
}
return $result;
}
+ /**
+ * Initializes a session backed by persistent store and puts it on the request.
+ *
+ * Sessions for web requests need to be backed by a persistent session store
+ * and a real session handler (responsible for session cookie management).
+ * In contrast, a simple in-memory store is sufficient for command line tools
+ * and tests. Hence, the persistent session should only ever be placed on web
+ * requests while command line tools and the parent site in functional tests
+ * must continue to use the ephemeral session initialized in
+ * DrupalKernel::preHandle().
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The request.
+ *
+ * @see \Drupal\Core\DrupalKernel::preHandle()
+ */
+ protected function initializePersistentSession(Request $request): void {
+ $session = $this->container->get($this->sessionServiceName);
+ $session->start();
+ $request->setSession($session);
+ }
+
}
diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
index 2e7083ff86f0..737f1ef247e7 100644
--- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
+++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
@@ -23,6 +23,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
use Drupal\Core\Routing\RouteObjectInterface;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Routing\Route;
/**
@@ -210,10 +212,6 @@ trait FunctionalTestSetupTrait {
protected function rebuildContainer() {
// Rebuild the kernel and bring it back to a fully bootstrapped state.
$this->container = $this->kernel->rebuildContainer();
-
- // Make sure the URL generator has a request object, otherwise calls to
- // $this->drupalGet() will fail.
- $this->prepareRequestForGenerator();
}
/**
@@ -254,6 +252,7 @@ trait FunctionalTestSetupTrait {
*/
protected function prepareRequestForGenerator($clean_urls = TRUE, $override_server_vars = []) {
$request = Request::createFromGlobals();
+ $request->setSession(new Session(new MockArraySessionStorage()));
$base_path = $request->getBasePath();
if ($clean_urls) {
$request_path = $base_path ? $base_path . '/user' : 'user';
@@ -265,6 +264,7 @@ trait FunctionalTestSetupTrait {
$server = array_merge($request->server->all(), $override_server_vars);
$request = Request::create($request_path, 'GET', [], [], [], $server);
+ $request->setSession(new Session(new MockArraySessionStorage()));
// Ensure the request time is REQUEST_TIME to ensure that API calls
// in the test use the right timestamp.
$request->server->set('REQUEST_TIME', REQUEST_TIME);