diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index da3a2776847082d9b9ebba9f35d5e4e19254538a..e8dd01144ebadd062dc041ce7db3de2c655fe455 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -950,6 +950,23 @@ function variable_del($name) {
   unset($conf[$name]);
 }
 
+/**
+ * Gets the page cache cid for this request.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ *   The request for this page.
+ *
+ * @return string
+ *   The cid for this request.
+ */
+function drupal_page_cache_get_cid(Request $request) {
+  $cid_parts = array(
+    $request->getUri(),
+    Drupal::service('content_negotiation')->getContentType($request),
+  );
+  return sha1(implode(':', $cid_parts));
+}
+
 /**
  * Retrieves the current page from the cache.
  *
@@ -958,27 +975,15 @@ function variable_del($name) {
  * from a form submission, the contents of a shopping cart, or other user-
  * specific content that should not be cached and displayed to other users.
  *
- * @param $check_only
- *   (optional) Set to TRUE to only return whether a previous call found a
- *   cache entry.
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ *   The request for this page.
  *
  * @return
  *   The cache object, if the page was found in the cache, NULL otherwise.
  */
-function drupal_page_get_cache($check_only = FALSE) {
-  global $base_root;
-  static $cache_hit = FALSE;
-
-  if ($check_only) {
-    return $cache_hit;
-  }
-
+function drupal_page_get_cache(Request $request) {
   if (drupal_page_is_cacheable()) {
-    $cache = cache('page')->get($base_root . request_uri());
-    if ($cache !== FALSE) {
-      $cache_hit = TRUE;
-    }
-    return $cache;
+    return Drupal::cache('page')->get(drupal_page_cache_get_cid($request));
   }
 }
 
@@ -2035,7 +2040,6 @@ function _drupal_bootstrap_page_cache() {
     $cache_enabled = $config->get('cache.page.use_internal');
   }
 
-  // @todo this is *criminal*. but, necessary, until we fix bootstrap ordering.
   $request = Request::createFromGlobals();
   // If there is no session cookie and cache is enabled (or forced), try
   // to serve a cached page.
@@ -2043,7 +2047,7 @@ function _drupal_bootstrap_page_cache() {
     // Make sure there is a user object because its timestamp will be checked.
     $user = drupal_anonymous_user();
     // Get the page from the cache.
-    $cache = drupal_page_get_cache();
+    $cache = drupal_page_get_cache($request);
     // If there is a cached page, display it.
     if (is_object($cache)) {
       $response = new Response();
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 842136e28269463f5e18bb37b0764f8392e02710..26181c0a32691fd97f94ee7f63fb069330bb7df8 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3165,11 +3165,9 @@ function _drupal_bootstrap_full($skip = FALSE) {
  * @see drupal_page_header()
  */
 function drupal_page_set_cache(Response $response, Request $request) {
-  global $base_root;
-
   if (drupal_page_is_cacheable()) {
     $cache = (object) array(
-      'cid' => $base_root . $request->getRequestUri(),
+      'cid' => drupal_page_cache_get_cid($request),
       'data' => array(
         'path' => $request->attributes->get('_system_path'),
         'body' => $response->getContent(),
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
index ca2d7b3a2b0dec29f7cb879600e2f55fb9aef4f0..3bbc72956119f8543b95b023043b3ec90f3be4b3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Bootstrap;
 
+use Symfony\Component\Routing\RequestContext;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -40,6 +41,33 @@ function setUp() {
       ->save();
   }
 
+  /**
+   * Tests support for different cache items with different Accept headers.
+   */
+  function testAcceptHeaderRequests() {
+    $config = config('system.performance');
+    $config->set('cache.page.use_internal', 1);
+    $config->set('cache.page.max_age', 300);
+    $config->save();
+
+    $url_generator = \Drupal::urlGenerator();
+    $url_generator->setContext(new RequestContext());
+    $accept_header_cache_uri = $url_generator->getPathFromRoute('system_test.page_cache_accept_header');
+    $json_accept_header = array('Accept: application/json');
+
+    $this->drupalGet($accept_header_cache_uri);
+    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'HTML page was not yet cached.');
+    $this->drupalGet($accept_header_cache_uri);
+    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'HTML page was cached.');
+    $this->assertRaw('<p>oh hai this is html.</p>', 'The correct HTML response was returned.');
+
+    $this->drupalGet($accept_header_cache_uri, array(), $json_accept_header);
+    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Json response was not yet cached.');
+    $this->drupalGet($accept_header_cache_uri, array(), $json_accept_header);
+    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Json response was cached.');
+    $this->assertRaw('{"content":"oh hai this is json"}', 'The correct Json response was returned.');
+  }
+
   /**
    * Tests support of requests with If-Modified-Since and If-None-Match headers.
    */
diff --git a/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/PageCacheAcceptHeaderController.php b/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/PageCacheAcceptHeaderController.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc3b23167df4cb70e96906c4380843f06deaa914
--- /dev/null
+++ b/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/PageCacheAcceptHeaderController.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system_test\Controller\PageCacheAcceptHeaderController.
+ */
+
+namespace Drupal\system_test\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * Defines a controller to respond the page cache accept header test.
+ */
+class PageCacheAcceptHeaderController {
+
+  /**
+   * Processes a request that will vary with Accept header.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request object.
+   *
+   * @return mixed
+   */
+  public function content(Request $request) {
+    if ($request->headers->get('Accept') == 'application/json') {
+      return new JsonResponse(array('content' => 'oh hai this is json'));
+    }
+    else {
+      return "<p>oh hai this is html.</p>";
+    }
+  }
+}
+
diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1be2566eba9c8c96d2778cf1cf2a2ef3133268fb
--- /dev/null
+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -0,0 +1,7 @@
+system_test.page_cache_accept_header:
+  pattern: '/system-test/page-cache/accept-header'
+  defaults:
+    _controller: '\Drupal\system_test\Controller\PageCacheAcceptHeaderController::content'
+  requirements:
+    _access: 'TRUE'
+
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index dbbca14e1cc6f98e67473ef89d1547f053150ee4..f058445b484d406ce79fb46991e5bc969e0eb649 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -125,10 +125,10 @@ function _toolbar_initialize_page_cache() {
 
   // If we have a cache, serve it.
   // @see _drupal_bootstrap_page_cache()
-  $cache = drupal_page_get_cache();
+  $request = \Drupal::request();
+  $cache = drupal_page_get_cache($request);
   if (is_object($cache)) {
     $response = new Response();
-    $request = \Drupal::request();
     $response->headers->set('X-Drupal-Cache', 'HIT');
     date_default_timezone_set(drupal_get_user_timezone());