diff --git a/core/core.services.yml b/core/core.services.yml
index c43da8c..5bc9f82 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -391,7 +391,7 @@ services:
       - { name: http_middleware, priority: 200 }
   http_middleware.kernel_pre_handle:
     class: Drupal\Core\StackMiddleware\KernelPreHandle
-    arguments: ['@kernel']
+    arguments: ['@module_handler', '@request_stack', '@config.factory']
     tags:
       - { name: http_middleware, priority: 100 }
   language_manager:
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 5377c36..46439b5 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -21,6 +21,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Site\Settings;
+use Drupal\Core\StackMiddleware\KernelInitializeTrait;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
@@ -46,6 +47,8 @@
  */
 class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
 
+  use KernelInitializeTrait;
+
   const CONTAINER_BASE_CLASS = '\Drupal\Core\DependencyInjection\Container';
 
   /**
@@ -154,13 +157,6 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
   protected $serviceProviders;
 
   /**
-   * Whether the request globals have been initialized.
-   *
-   * @var bool
-   */
-  protected static $isRequestInitialized = FALSE;
-
-  /**
    * Whether the PHP environment has been initialized.
    *
    * This legacy phase can only be booted once because it sets session INI
@@ -419,43 +415,11 @@ public function getContainer() {
 
   /**
    * {@inheritdoc}
-   */
-  public function preHandle(Request $request) {
-    // Load all enabled modules.
-    $this->container->get('module_handler')->loadAll();
-
-    // Initialize legacy request globals.
-    $this->initializeRequestGlobals($request);
-
-    // Initialize cookie globals.
-    $this->initializeCookieGlobals($request);
-
-    // Put the request on the stack.
-    $this->container->get('request_stack')->push($request);
-
-    // Make sure all stream wrappers are registered.
-    file_get_stream_wrappers();
-
-    // Set the allowed protocols once we have the config available.
-    $allowed_protocols = $this->container->get('config.factory')->get('system.filter')->get('protocols');
-    if (!isset($allowed_protocols)) {
-      // \Drupal\Component\Utility\UrlHelper::filterBadProtocol() is called by
-      // the installer and update.php, in which case the configuration may not
-      // exist (yet). Provide a minimal default set of allowed protocols for
-      // these cases.
-      $allowed_protocols = array('http', 'https');
-    }
-    UrlHelper::setAllowedProtocols($allowed_protocols);
-  }
-
-  /**
-   * {@inheritdoc}
    *
    * @todo Invoke proper request/response/terminate events.
    */
   public function handlePageCache(Request $request) {
     $this->boot();
-    $this->initializeCookieGlobals($request);
 
     // Check for a cache mode force from settings.php.
     if (Settings::get('page_cache_without_database')) {
@@ -573,7 +537,6 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
    */
   public function prepareLegacyRequest(Request $request) {
     $this->boot();
-    $this->preHandle($request);
     // Enter the request scope so that current_user service is available for
     // locale/translation sake.
     $this->container->get('request_stack')->push($request);
@@ -785,153 +748,6 @@ public static function bootEnvironment() {
   }
 
   /**
-   * Bootstraps the legacy global request variables.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @todo D8: Eliminate this entirely in favor of Request object.
-   */
-  protected function initializeRequestGlobals(Request $request) {
-    // Provided by settings.php.
-    global $base_url;
-    // Set and derived from $base_url by this function.
-    global $base_path, $base_root, $script_path;
-    global $base_secure_url, $base_insecure_url;
-
-    // @todo Refactor with the Symfony Request object.
-    _current_path(request_path());
-
-    if (isset($base_url)) {
-      // Parse fixed base URL from settings.php.
-      $parts = parse_url($base_url);
-      if (!isset($parts['path'])) {
-        $parts['path'] = '';
-      }
-      $base_path = $parts['path'] . '/';
-      // Build $base_root (everything until first slash after "scheme://").
-      $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
-    }
-    else {
-      // Create base URL.
-      $http_protocol = $request->isSecure() ? 'https' : 'http';
-      $base_root = $http_protocol . '://' . $request->server->get('HTTP_HOST');
-
-      $base_url = $base_root;
-
-      // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is
-      // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'.
-      if ($dir = rtrim(dirname($request->server->get('SCRIPT_NAME')), '\/')) {
-        // Remove "core" directory if present, allowing install.php, update.php,
-        // and others to auto-detect a base path.
-        $core_position = strrpos($dir, '/core');
-        if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) {
-          $base_path = substr($dir, 0, $core_position);
-        }
-        else {
-          $base_path = $dir;
-        }
-        $base_url .= $base_path;
-        $base_path .= '/';
-      }
-      else {
-        $base_path = '/';
-      }
-    }
-    $base_secure_url = str_replace('http://', 'https://', $base_url);
-    $base_insecure_url = str_replace('https://', 'http://', $base_url);
-
-    // Determine the path of the script relative to the base path, and add a
-    // trailing slash. This is needed for creating URLs to Drupal pages.
-    if (!isset($script_path)) {
-      $script_path = '';
-      // We don't expect scripts outside of the base path, but sanity check
-      // anyway.
-      if (strpos($request->server->get('SCRIPT_NAME'), $base_path) === 0) {
-        $script_path = substr($request->server->get('SCRIPT_NAME'), strlen($base_path)) . '/';
-        // If the request URI does not contain the script name, then clean URLs
-        // are in effect and the script path can be similarly dropped from URL
-        // generation. For servers that don't provide $_SERVER['REQUEST_URI'],
-        // we do not know the actual URI requested by the client, and
-        // request_uri() returns a URI with the script name, resulting in
-        // non-clean URLs unless
-        // there's other code that intervenes.
-        if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) {
-          $script_path = '';
-        }
-        // @todo Temporary BC for install.php, update.php, and other scripts.
-        //   - http://drupal.org/node/1547184
-        //   - http://drupal.org/node/1546082
-        if ($script_path !== 'index.php/') {
-          $script_path = '';
-        }
-      }
-    }
-
-  }
-
-  /**
-   * Initialize cookie settings.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @todo D8: Eliminate this entirely in favor of a session object.
-   */
-  protected function initializeCookieGlobals(Request $request) {
-    // If we do this more then once per page request we are likely to cause
-    // errors.
-    if (static::$isRequestInitialized) {
-      return;
-    }
-    global $cookie_domain;
-
-    if ($cookie_domain) {
-      // If the user specifies the cookie domain, also use it for session name.
-      $session_name = $cookie_domain;
-    }
-    else {
-      // Otherwise use $base_url as session name, without the protocol
-      // to use the same session identifiers across HTTP and HTTPS.
-      $session_name = $request->getHost() . $request->getBasePath();
-      // Replace "core" out of session_name so core scripts redirect properly,
-      // specifically install.php and update.php.
-      $session_name = preg_replace('/\/core$/', '', $session_name);
-      // HTTP_HOST can be modified by a visitor, but has been sanitized already
-      // in DrupalKernel::bootEnvironment().
-      if ($cookie_domain = $request->server->get('HTTP_HOST')) {
-        // Strip leading periods, www., and port numbers from cookie domain.
-        $cookie_domain = ltrim($cookie_domain, '.');
-        if (strpos($cookie_domain, 'www.') === 0) {
-          $cookie_domain = substr($cookie_domain, 4);
-        }
-        $cookie_domain = explode(':', $cookie_domain);
-        $cookie_domain = '.' . $cookie_domain[0];
-      }
-    }
-    // Per RFC 2109, cookie domains must contain at least one dot other than the
-    // first. For hosts such as 'localhost' or IP Addresses we don't set a
-    // cookie domain.
-    if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
-      ini_set('session.cookie_domain', $cookie_domain);
-    }
-    // To prevent session cookies from being hijacked, a user can configure the
-    // SSL version of their website to only transfer session cookies via SSL by
-    // using PHP's session.cookie_secure setting. The browser will then use two
-    // separate session cookies for the HTTPS and HTTP versions of the site. So
-    // we must use different session identifiers for HTTPS and HTTP to prevent a
-    // cookie collision.
-    if ($request->isSecure()) {
-      ini_set('session.cookie_secure', TRUE);
-    }
-    $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
-
-    session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
-
-    static::$isRequestInitialized = TRUE;
-  }
-
-  /**
    * Returns service instances to persist from an old container to a new one.
    */
   protected function getServicesToPersist(ContainerInterface $container) {
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index ca7af2b..954f6c6 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -107,13 +107,4 @@ public function handlePageCache(Request $request);
    *   Only used by legacy front-controller scripts.
    */
   public function prepareLegacyRequest(Request $request);
-
-  /**
-   * Helper method that does request related initialization.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   */
-  public function preHandle(Request $request);
-
 }
diff --git a/core/lib/Drupal/Core/StackMiddleware/KernelInitializeTrait.php b/core/lib/Drupal/Core/StackMiddleware/KernelInitializeTrait.php
new file mode 100644
index 0000000..1594a29
--- /dev/null
+++ b/core/lib/Drupal/Core/StackMiddleware/KernelInitializeTrait.php
@@ -0,0 +1,172 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StackMiddleware\KernelInitializeTrait.
+ */
+
+namespace Drupal\Core\StackMiddleware;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * A trait containing helper methods for kernel initialization.
+ */
+trait KernelInitializeTrait {
+
+  /**
+   * Whether the request globals have been initialized.
+   *
+   * @var bool
+   */
+  protected static $isRequestInitialized = FALSE;
+
+  /**
+   * Bootstraps the legacy global request variables.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   *
+   * @todo D8: Eliminate this entirely in favor of Request object.
+   */
+  protected function initializeRequestGlobals(Request $request) {
+    // Provided by settings.php.
+    global $base_url;
+    // Set and derived from $base_url by this function.
+    global $base_path, $base_root, $script_path;
+    global $base_secure_url, $base_insecure_url;
+
+    // @todo Refactor with the Symfony Request object.
+    _current_path(request_path());
+
+    if (isset($base_url)) {
+      // Parse fixed base URL from settings.php.
+      $parts = parse_url($base_url);
+      if (!isset($parts['path'])) {
+        $parts['path'] = '';
+      }
+      $base_path = $parts['path'] . '/';
+      // Build $base_root (everything until first slash after "scheme://").
+      $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
+    }
+    else {
+      // Create base URL.
+      $http_protocol = $request->isSecure() ? 'https' : 'http';
+      $base_root = $http_protocol . '://' . $request->server->get('HTTP_HOST');
+
+      $base_url = $base_root;
+
+      // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is
+      // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'.
+      if ($dir = rtrim(dirname($request->server->get('SCRIPT_NAME')), '\/')) {
+        // Remove "core" directory if present, allowing install.php, update.php,
+        // and others to auto-detect a base path.
+        $core_position = strrpos($dir, '/core');
+        if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) {
+          $base_path = substr($dir, 0, $core_position);
+        }
+        else {
+          $base_path = $dir;
+        }
+        $base_url .= $base_path;
+        $base_path .= '/';
+      }
+      else {
+        $base_path = '/';
+      }
+    }
+    $base_secure_url = str_replace('http://', 'https://', $base_url);
+    $base_insecure_url = str_replace('https://', 'http://', $base_url);
+
+    // Determine the path of the script relative to the base path, and add a
+    // trailing slash. This is needed for creating URLs to Drupal pages.
+    if (!isset($script_path)) {
+      $script_path = '';
+      // We don't expect scripts outside of the base path, but sanity check
+      // anyway.
+      if (strpos($request->server->get('SCRIPT_NAME'), $base_path) === 0) {
+        $script_path = substr($request->server->get('SCRIPT_NAME'), strlen($base_path)) . '/';
+        // If the request URI does not contain the script name, then clean URLs
+        // are in effect and the script path can be similarly dropped from URL
+        // generation. For servers that don't provide $_SERVER['REQUEST_URI'],
+        // we do not know the actual URI requested by the client, and
+        // request_uri() returns a URI with the script name, resulting in
+        // non-clean URLs unless
+        // there's other code that intervenes.
+        if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) {
+          $script_path = '';
+        }
+        // @todo Temporary BC for install.php, update.php, and other scripts.
+        //   - http://drupal.org/node/1547184
+        //   - http://drupal.org/node/1546082
+        if ($script_path !== 'index.php/') {
+          $script_path = '';
+        }
+      }
+    }
+
+  }
+
+  /**
+   * Initialize cookie settings.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   *
+   * @todo D8: Eliminate this entirely in favor of a session object.
+   */
+  protected function initializeCookieGlobals(Request $request) {
+    // If we do this more then once per page request we are likely to cause
+    // errors.
+    if (static::$isRequestInitialized) {
+      return;
+    }
+
+    global $cookie_domain;
+
+    if ($cookie_domain) {
+      // If the user specifies the cookie domain, also use it for session name.
+      $session_name = $cookie_domain;
+    }
+    else {
+      // Otherwise use $base_url as session name, without the protocol
+      // to use the same session identifiers across HTTP and HTTPS.
+      $session_name = $request->getHost() . $request->getBasePath();
+      // Replace "core" out of session_name so core scripts redirect properly,
+      // specifically install.php and update.php.
+      $session_name = preg_replace('/\/core$/', '', $session_name);
+      // HTTP_HOST can be modified by a visitor, but has been sanitized already
+      // in DrupalKernel::bootEnvironment().
+      if ($cookie_domain = $request->server->get('HTTP_HOST')) {
+        // Strip leading periods, www., and port numbers from cookie domain.
+        $cookie_domain = ltrim($cookie_domain, '.');
+        if (strpos($cookie_domain, 'www.') === 0) {
+          $cookie_domain = substr($cookie_domain, 4);
+        }
+        $cookie_domain = explode(':', $cookie_domain);
+        $cookie_domain = '.' . $cookie_domain[0];
+      }
+    }
+    // Per RFC 2109, cookie domains must contain at least one dot other than the
+    // first. For hosts such as 'localhost' or IP Addresses we don't set a
+    // cookie domain.
+    if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+      ini_set('session.cookie_domain', $cookie_domain);
+    }
+    // To prevent session cookies from being hijacked, a user can configure the
+    // SSL version of their website to only transfer session cookies via SSL by
+    // using PHP's session.cookie_secure setting. The browser will then use two
+    // separate session cookies for the HTTPS and HTTP versions of the site. So
+    // we must use different session identifiers for HTTPS and HTTP to prevent a
+    // cookie collision.
+    if ($request->isSecure()) {
+      ini_set('session.cookie_secure', TRUE);
+    }
+    $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
+
+    session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
+
+    static::$isRequestInitialized = TRUE;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php b/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php
index 1ccdea1..5714b23 100644
--- a/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php
+++ b/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php
@@ -7,8 +7,12 @@
 
 namespace Drupal\Core\StackMiddleware;
 
+use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\DrupalKernelInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
@@ -16,6 +20,8 @@
  */
 class KernelPreHandle implements HttpKernelInterface {
 
+  use KernelInitializeTrait;
+
   /**
    * The wrapped HTTP kernel.
    *
@@ -31,24 +37,70 @@ class KernelPreHandle implements HttpKernelInterface {
   protected $drupalKernel;
 
   /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * The request stack.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * The system filter config object.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $config;
+
+  /**
    * Constructs a new KernelPreHandle instance.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
    *   The wrapped HTTP kernel.
    *
-   * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel
-   *   The main Drupal kernel.
+   *
    */
-  public function __construct(HttpKernelInterface $http_kernel, DrupalKernelInterface $drupal_kernel) {
+  public function __construct(HttpKernelInterface $http_kernel, ModuleHandlerInterface $module_handler, RequestStack $request_stack, ConfigFactoryInterface $config_factory) {
     $this->httpKernel = $http_kernel;
-    $this->drupalKernel = $drupal_kernel;
+    $this->moduleHandler = $module_handler;
+    $this->requestStack = $request_stack;
+    $this->config = $config_factory->get('system.filter');
   }
 
   /**
    * {@inheritdoc}
    */
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    $this->drupalKernel->preHandle($request);
+    // Load all enabled modules.
+    $this->moduleHandler->loadAll();
+
+    // Initialize legacy request globals.
+    $this->initializeRequestGlobals($request);
+
+    // Initialize cookie globals.
+    $this->initializeCookieGlobals($request);
+
+    // Put the request on the stack.
+    $this->requestStack->push($request);
+
+    // Make sure all stream wrappers are registered.
+    file_get_stream_wrappers();
+
+    // Set the allowed protocols once we have the config available.
+    $allowed_protocols = $this->config->get('protocols');
+    if (!isset($allowed_protocols)) {
+      // \Drupal\Component\Utility\UrlHelper::filterBadProtocol() is called by
+      // the installer and update.php, in which case the configuration may not
+      // exist (yet). Provide a minimal default set of allowed protocols for
+      // these cases.
+      $allowed_protocols = array('http', 'https');
+    }
+    UrlHelper::setAllowedProtocols($allowed_protocols);
 
     return $this->httpKernel->handle($request, $type, $catch);
   }
