diff --git a/core/core.services.yml b/core/core.services.yml
index 2cd6077..a72ff6f 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -172,7 +172,7 @@ services:
     arguments: ['@service_container']
   http_kernel:
     class: Drupal\Core\HttpKernel
-    arguments: ['@event_dispatcher', '@service_container', '@controller_resolver']
+    arguments: ['@event_dispatcher', '@controller_resolver', '@request']
   language_manager:
     class: Drupal\Core\Language\LanguageManager
   string_translator.custom_strings:
@@ -222,6 +222,13 @@ services:
   router.dynamic:
     class: Symfony\Cmf\Component\Routing\DynamicRouter
     arguments: ['@router.request_context', '@router.matcher', '@url_generator']
+  fragment_handler:
+    class: Symfony\Component\HttpKernel\Fragment\FragmentHandler
+  renderer_inline:
+    class: Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer
+    arguments: ['@http_kernel']
+    tags:
+      - { name: render_strategy }
   legacy_generator:
     class: Drupal\Core\Routing\NullGenerator
   legacy_url_matcher:
@@ -305,7 +312,7 @@ services:
       - { name: route_enhancer, priority: 10 }
   controller.page:
     class: Drupal\Core\Controller\HtmlPageController
-    arguments: ['@http_kernel']
+    arguments: ['@http_kernel', '@fragment_handler']
   controller.dialog:
     class: Drupal\Core\Controller\DialogController
     arguments: ['@http_kernel']
diff --git a/core/includes/session.inc b/core/includes/session.inc
index 40e495f..6f46f71 100644
--- a/core/includes/session.inc
+++ b/core/includes/session.inc
@@ -181,7 +181,7 @@ function _drupal_session_write($sid, $value) {
       // Either ssid or sid or both will be added from $key below.
       $fields = array(
         'uid' => $user->uid,
-        'hostname' => Drupal::request()->getClientIP(),
+        'hostname' => Drupal::request()->getClientIP() ?: '',
         'session' => $value,
         'timestamp' => REQUEST_TIME,
       );
diff --git a/core/lib/Drupal/Core/Controller/HtmlPageController.php b/core/lib/Drupal/Core/Controller/HtmlPageController.php
index fd89081..89337a4 100644
--- a/core/lib/Drupal/Core/Controller/HtmlPageController.php
+++ b/core/lib/Drupal/Core/Controller/HtmlPageController.php
@@ -9,6 +9,8 @@
 
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
@@ -24,12 +26,23 @@ class HtmlPageController {
   protected $httpKernel;
 
   /**
+   * The html fragment handler.
+   *
+   * @var \Symfony\Component\HttpKernel\Fragment\FragmentHandler
+   */
+  protected $fragmentHandler;
+
+  /**
    * Constructs a new HtmlPageController.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $kernel
+   *   The central http kernel.
+   * @param \Symfony\Component\HttpKernel\Fragment\FragmentHandler $fragment_handler
+   *   The html fragment handler.
    */
-  public function __construct(HttpKernelInterface $kernel) {
+  public function __construct(HttpKernelInterface $kernel, FragmentHandler $fragment_handler) {
     $this->httpKernel = $kernel;
+    $this->fragmentHandler = $fragment_handler;
   }
 
   /**
@@ -58,13 +71,11 @@ public function content(Request $request, $_content) {
     $attributes->remove('system_path');
     $attributes->remove('_content');
 
-    $response = $this->httpKernel->forward($controller, $attributes->all(), $request->query->all());
+    $attributes_array = $attributes->all() ?: array();
+    $query = $request->query->all() ?: array();
+    $page_content = $this->fragmentHandler->render(new ControllerReference($controller, $attributes_array, $query));
 
-    // For successful (HTTP status 200) responses, decorate with blocks.
-    if ($response->isOk()) {
-      $page_content = $response->getContent();
-      $response = new Response(drupal_render_page($page_content));
-    }
+    $response = new Response(drupal_render_page($page_content));
 
     return $response;
   }
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 472105a..e95dbca 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -17,6 +17,7 @@
 use Drupal\Core\DependencyInjection\Compiler\RegisterParamConvertersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterFragmentRenderersPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Reference;
@@ -63,6 +64,8 @@ public function build(ContainerBuilder $container) {
     $container->addCompilerPass(new ListCacheBinsPass());
     // Add the compiler pass for appending string translators.
     $container->addCompilerPass(new RegisterStringTranslatorsPass());
+    // Add a compiler pass for registering fragment renderers.
+    $container->addCompilerPass(new RegisterFragmentRenderersPass());
   }
 
   /**
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterFragmentRenderersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterFragmentRenderersPass.php
new file mode 100644
index 0000000..6310aa1
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterFragmentRenderersPass.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\Compiler\RegisterFragmentRenderersPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Adds services tagged 'render_strategy' to the 'fragment_handler' service.
+ */
+class RegisterFragmentRenderersPass implements CompilerPassInterface {
+
+  /**
+   * Adds services tagged 'render_strategy' to the 'fragment_handler' service.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *  The container to process.
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('fragment_handler')) {
+      return;
+    }
+    $matcher = $container->getDefinition('fragment_handler');
+    foreach ($container->findTaggedServiceIds('render_strategy') as $id => $attributes) {
+      $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
+      $matcher->addMethodCall('addRenderer', array(new Reference($id)));
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/HttpKernel.php b/core/lib/Drupal/Core/HttpKernel.php
index 07c79c7..ae528ee 100644
--- a/core/lib/Drupal/Core/HttpKernel.php
+++ b/core/lib/Drupal/Core/HttpKernel.php
@@ -2,12 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Core\HttpKernel.
- *
- * @todo This file is copied verbatim, with the exception of the namespace
- * change and this commment block, from Symfony full stack's FrameworkBundle.
- * Once the FrameworkBundle is available as a Composer package we should switch
- * to pulling it via Composer.
+ * Contains \Drupal\Core\HttpKernel.
  */
 
 namespace Drupal\Core;
@@ -23,226 +18,65 @@
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
- * This HttpKernel is used to manage scope changes of the DI container.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ * HttpKernel extension to allow easy in-process subrequests.
  */
-class HttpKernel extends BaseHttpKernel
-{
-    protected $container;
+class HttpKernel extends BaseHttpKernel {
 
-    private $esiSupport;
-
-    public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver)
-    {
-        parent::__construct($dispatcher, $controllerResolver);
-
-        $this->container = $container;
-    }
-
-    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
-    {
-        $request->headers->set('X-Php-Ob-Level', ob_get_level());
-
-        $this->container->enterScope('request');
-        $this->container->set('request', $request, 'request');
-
-        try {
-            $response = parent::handle($request, $type, $catch);
-        } catch (\Exception $e) {
-            $this->container->leaveScope('request');
-
-            throw $e;
-        }
-
-        $this->container->leaveScope('request');
-
-        return $response;
-    }
-
-    /**
-     * Forwards the request to another controller.
-     *
-     * @param string|NULL $controller
-     *   The controller name (a string like BlogBundle:Post:index).
-     * @param array $attributes
-     *   An array of request attributes.
-     * @param array $query
-     *   An array of request query parameters.
-     *
-     * @return Response
-     *   A Response instance
-     */
-    public function forward($controller, array $attributes = array(), array $query = array())
-    {
-      $subrequest = $this->setupSubrequest($controller, $attributes, $query);
-
-      return $this->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
-    }
-
-    /**
-     * Renders a Controller and returns the Response content.
-     *
-     * Note that this method generates an esi:include tag only when both the standalone
-     * option is set to true and the request has ESI capability (@see Symfony\Component\HttpKernel\HttpCache\ESI).
-     *
-     * Available options:
-     *
-     *  * attributes: An array of request attributes (only when the first argument is a controller)
-     *  * query: An array of request query parameters (only when the first argument is a controller)
-     *  * ignore_errors: true to return an empty string in case of an error
-     *  * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments)
-     *  * standalone: whether to generate an esi:include tag or not when ESI is supported
-     *  * comment: a comment to add when returning an esi:include tag
-     *
-     * @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
-     * @param array  $options    An array of options
-     *
-     * @return string The Response content
-     */
-    public function render($controller, array $options = array())
-    {
-        $options = array_merge(array(
-            'attributes'    => array(),
-            'query'         => array(),
-            'ignore_errors' => !$this->container->getParameter('kernel.debug'),
-            'alt'           => array(),
-            'standalone'    => false,
-            'comment'       => '',
-        ), $options);
-
-        if (!is_array($options['alt'])) {
-            $options['alt'] = array($options['alt']);
-        }
-
-        if (null === $this->esiSupport) {
-            $this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request'));
-        }
-
-        if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) {
-            $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']);
-
-            $alt = '';
-            if ($options['alt']) {
-                $alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
-            }
-
-            return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
-        }
-
-        if ('js' === $options['standalone']) {
-            $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query'], false);
-            $defaultContent = null;
-
-            if ($template = $this->container->getParameter('templating.hinclude.default_template')) {
-                $defaultContent = $this->container->get('templating')->render($template);
-            }
-
-            return $this->renderHIncludeTag($uri, $defaultContent);
-        }
-
-        $request = $this->container->get('request');
-
-        // controller or URI?
-        if (0 === strpos($controller, '/')) {
-            $subRequest = Request::create($request->getUriForPath($controller), 'get', array(), $request->cookies->all(), array(), $request->server->all());
-            if ($session = $request->getSession()) {
-                $subRequest->setSession($session);
-            }
-        } else {
-            $options['attributes']['_controller'] = $controller;
-
-            if (!isset($options['attributes']['_format'])) {
-                $options['attributes']['_format'] = $request->getRequestFormat();
-            }
-
-            $options['attributes'][RouteObjectInterface::ROUTE_OBJECT] = '_internal';
-            $subRequest = $request->duplicate($options['query'], null, $options['attributes']);
-            $subRequest->setMethod('GET');
-        }
-
-        $level = ob_get_level();
-        try {
-            $response = $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
-
-            if (!$response->isSuccessful()) {
-                throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
-            }
-
-            if (!$response instanceof StreamedResponse) {
-                return $response->getContent();
-            }
-
-            $response->sendContent();
-        } catch (\Exception $e) {
-            if ($options['alt']) {
-                $alt = $options['alt'];
-                unset($options['alt']);
-                $options['attributes'] = isset($alt[1]) ? $alt[1] : array();
-                $options['query'] = isset($alt[2]) ? $alt[2] : array();
-
-                return $this->render($alt[0], $options);
-            }
-
-            if (!$options['ignore_errors']) {
-                throw $e;
-            }
-
-            // let's clean up the output buffers that were created by the sub-request
-            while (ob_get_level() > $level) {
-                ob_get_clean();
-            }
-        }
-    }
-
-    /**
-     * Generates an internal URI for a given controller.
-     *
-     * This method uses the "_internal" route, which should be available.
-     *
-     * @param string  $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
-     * @param array   $attributes An array of request attributes
-     * @param array   $query      An array of request query parameters
-     * @param boolean $secure
-     *
-     * @return string An internal URI
-     */
-    public function generateInternalUri($controller, array $attributes = array(), array $query = array(), $secure = true)
-    {
-        if (0 === strpos($controller, '/')) {
-            return $controller;
-        }
+  /**
+   * The synchronized request object.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
 
-        $path = http_build_query($attributes, '', '&');
-        $uri = $this->container->get('router')->generate($secure ? '_internal' : '_internal_public', array(
-            'controller' => $controller,
-            'path'       => $path ?: 'none',
-            '_format'    => $this->container->get('request')->getRequestFormat(),
-        ));
+  /**
+   * Constructs a \Drupal\Core\HttpKernel object.
+   *
+   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
+   *   The event dispatcher.
+   * @param \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface $resolver
+   *   The controller resolver.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The synchronized request object.
+   */
+  public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, Request $request) {
+    parent::__construct($dispatcher, $resolver);
 
-        if ($queryString = http_build_query($query, '', '&')) {
-            $uri .= '?'.$queryString;
-        }
+    $this->setRequest($request);
+  }
 
-        return $uri;
-    }
+  /**
+   * Set the request object.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The synchronized request object.
+   */
+  public function setRequest(Request $request = NULL) {
+    $this->request = $request;
+  }
 
-    /**
-     * Renders an HInclude tag.
-     *
-     * @param string $uri A URI
-     * @param string $defaultContent Default content
-     */
-    public function renderHIncludeTag($uri, $defaultContent = null)
-    {
-        return sprintf('<hx:include src="%s">%s</hx:include>', $uri, $defaultContent);
-    }
+  /**
+   * Forwards the request to another controller.
+   *
+   * If what you want back is just a string, do not use this method. Use
+   * the FragmentHandler. Only use this method if you want back a Response
+   * object.
+   *
+   * @param string $controller
+   *   The controller name (a string like BlogBundle:Post:index)
+   * @param array  $attributes
+   *   An array of request attributes
+   * @param array  $query
+   *   An array of request query parameters
+   *
+   * @return Response
+   *   A Response instance
+   */
+  public function forward($controller, array $attributes = array(), array $query = array()) {
+    $sub_request = $this->setupSubrequest($controller, $attributes, $query);
 
-    public function hasEsiSupport()
-    {
-        return $this->esiSupport;
-    }
+    return $this->handle($sub_request, HttpKernelInterface::SUB_REQUEST);
+  }
 
   /**
    * Creates a request object for a subrequest.
@@ -265,7 +99,7 @@ public function setupSubrequest($controller, array $attributes, array $query) {
     else {
       unset($attributes['_controller']);
     }
-    return $this->container->get('request')->duplicate($query, NULL, $attributes);
+    return $this->request->duplicate($query, NULL, $attributes);
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/HttpKernelTest.php b/core/tests/Drupal/Tests/Core/HttpKernelTest.php
index b51e108..6c877eb 100644
--- a/core/tests/Drupal/Tests/Core/HttpKernelTest.php
+++ b/core/tests/Drupal/Tests/Core/HttpKernelTest.php
@@ -48,7 +48,7 @@ public function testSetupSubrequest() {
     $dispatcher = new EventDispatcher();
     $controller_resolver = new ControllerResolver($container);
 
-    $http_kernel = new HttpKernel($dispatcher, $container, $controller_resolver);
+    $http_kernel = new HttpKernel($dispatcher, $controller_resolver, $request);
 
     $test_controller = '\Drupal\Tests\Core\Controller\TestController';
     $random_attribute = $this->randomName();
