Commit 1a0616fa authored by catch's avatar catch

Issue #1855260 by beejeebus, msonnabaum, larowlan: Fixed Page caching broken...

Issue #1855260 by beejeebus, msonnabaum, larowlan: Fixed Page caching broken by accept header-based routing.
parent fd76691c
...@@ -950,6 +950,23 @@ function variable_del($name) { ...@@ -950,6 +950,23 @@ function variable_del($name) {
unset($conf[$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. * Retrieves the current page from the cache.
* *
...@@ -958,27 +975,15 @@ function variable_del($name) { ...@@ -958,27 +975,15 @@ function variable_del($name) {
* from a form submission, the contents of a shopping cart, or other user- * 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. * specific content that should not be cached and displayed to other users.
* *
* @param $check_only * @param \Symfony\Component\HttpFoundation\Request $request
* (optional) Set to TRUE to only return whether a previous call found a * The request for this page.
* cache entry.
* *
* @return * @return
* The cache object, if the page was found in the cache, NULL otherwise. * The cache object, if the page was found in the cache, NULL otherwise.
*/ */
function drupal_page_get_cache($check_only = FALSE) { function drupal_page_get_cache(Request $request) {
global $base_root;
static $cache_hit = FALSE;
if ($check_only) {
return $cache_hit;
}
if (drupal_page_is_cacheable()) { if (drupal_page_is_cacheable()) {
$cache = cache('page')->get($base_root . request_uri()); return Drupal::cache('page')->get(drupal_page_cache_get_cid($request));
if ($cache !== FALSE) {
$cache_hit = TRUE;
}
return $cache;
} }
} }
...@@ -2035,7 +2040,6 @@ function _drupal_bootstrap_page_cache() { ...@@ -2035,7 +2040,6 @@ function _drupal_bootstrap_page_cache() {
$cache_enabled = $config->get('cache.page.use_internal'); $cache_enabled = $config->get('cache.page.use_internal');
} }
// @todo this is *criminal*. but, necessary, until we fix bootstrap ordering.
$request = Request::createFromGlobals(); $request = Request::createFromGlobals();
// If there is no session cookie and cache is enabled (or forced), try // If there is no session cookie and cache is enabled (or forced), try
// to serve a cached page. // to serve a cached page.
...@@ -2043,7 +2047,7 @@ function _drupal_bootstrap_page_cache() { ...@@ -2043,7 +2047,7 @@ function _drupal_bootstrap_page_cache() {
// Make sure there is a user object because its timestamp will be checked. // Make sure there is a user object because its timestamp will be checked.
$user = drupal_anonymous_user(); $user = drupal_anonymous_user();
// Get the page from the cache. // 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 there is a cached page, display it.
if (is_object($cache)) { if (is_object($cache)) {
$response = new Response(); $response = new Response();
......
...@@ -3165,11 +3165,9 @@ function _drupal_bootstrap_full($skip = FALSE) { ...@@ -3165,11 +3165,9 @@ function _drupal_bootstrap_full($skip = FALSE) {
* @see drupal_page_header() * @see drupal_page_header()
*/ */
function drupal_page_set_cache(Response $response, Request $request) { function drupal_page_set_cache(Response $response, Request $request) {
global $base_root;
if (drupal_page_is_cacheable()) { if (drupal_page_is_cacheable()) {
$cache = (object) array( $cache = (object) array(
'cid' => $base_root . $request->getRequestUri(), 'cid' => drupal_page_cache_get_cid($request),
'data' => array( 'data' => array(
'path' => $request->attributes->get('_system_path'), 'path' => $request->attributes->get('_system_path'),
'body' => $response->getContent(), 'body' => $response->getContent(),
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace Drupal\system\Tests\Bootstrap; namespace Drupal\system\Tests\Bootstrap;
use Symfony\Component\Routing\RequestContext;
use Drupal\simpletest\WebTestBase; use Drupal\simpletest\WebTestBase;
/** /**
...@@ -40,6 +41,33 @@ function setUp() { ...@@ -40,6 +41,33 @@ function setUp() {
->save(); ->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. * Tests support of requests with If-Modified-Since and If-None-Match headers.
*/ */
......
<?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>";
}
}
}
system_test.page_cache_accept_header:
pattern: '/system-test/page-cache/accept-header'
defaults:
_controller: '\Drupal\system_test\Controller\PageCacheAcceptHeaderController::content'
requirements:
_access: 'TRUE'
...@@ -125,10 +125,10 @@ function _toolbar_initialize_page_cache() { ...@@ -125,10 +125,10 @@ function _toolbar_initialize_page_cache() {
// If we have a cache, serve it. // If we have a cache, serve it.
// @see _drupal_bootstrap_page_cache() // @see _drupal_bootstrap_page_cache()
$cache = drupal_page_get_cache(); $request = \Drupal::request();
$cache = drupal_page_get_cache($request);
if (is_object($cache)) { if (is_object($cache)) {
$response = new Response(); $response = new Response();
$request = \Drupal::request();
$response->headers->set('X-Drupal-Cache', 'HIT'); $response->headers->set('X-Drupal-Cache', 'HIT');
date_default_timezone_set(drupal_get_user_timezone()); date_default_timezone_set(drupal_get_user_timezone());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment