Skip to content

Instantly share code, notes, and snippets.

@msonnabaum
Created May 19, 2013 20:06
Show Gist options
  • Save msonnabaum/5608804 to your computer and use it in GitHub Desktop.
Save msonnabaum/5608804 to your computer and use it in GitHub Desktop.
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index fd3b719..e9afc2c 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2289,6 +2289,8 @@ function _drupal_bootstrap_configuration() {
* Attempts to serve a page from the cache.
*/
function _drupal_bootstrap_page_cache() {
+ // Not sure what to do with all this yet, but the whole phase most likely
+ // needs to be removed.
global $user;
// Allow specifying special cache handlers in settings.php, like
@@ -2297,6 +2299,7 @@ function _drupal_bootstrap_page_cache() {
foreach (variable_get('cache_backends', array()) as $include) {
require_once DRUPAL_ROOT . '/' . $include;
}
+ /*
// Check for a cache mode force from settings.php.
if (variable_get('page_cache_without_database')) {
$cache_enabled = TRUE;
@@ -2340,6 +2343,7 @@ function _drupal_bootstrap_page_cache() {
header('X-Drupal-Cache: MISS');
}
}
+*/
}
/**
diff --git a/core/includes/common.inc b/core/includes/common.inc
index aceaac8..3afba02 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -4928,62 +4928,6 @@ function _drupal_bootstrap_full($skip = FALSE) {
}
/**
- * Stores the current page in the cache.
- *
- * If page_compression is enabled, a gzipped version of the page is stored in
- * the cache to avoid compressing the output on each request. The cache entry
- * is unzipped in the relatively rare event that the page is requested by a
- * client without gzip support.
- *
- * Page compression requires the PHP zlib extension
- * (http://php.net/manual/ref.zlib.php).
- *
- * @param $body
- * The response body.
- * @return
- * The cached object or NULL if the page cache was not set.
- *
- * @see drupal_page_header()
- */
-function drupal_page_set_cache($body) {
- global $base_root;
-
- if (drupal_page_is_cacheable()) {
- $cache = (object) array(
- 'cid' => $base_root . request_uri(),
- 'data' => array(
- 'path' => current_path(),
- 'body' => $body,
- 'title' => drupal_get_title(),
- 'headers' => array(),
- ),
- 'tags' => array('content' => TRUE),
- 'expire' => CacheBackendInterface::CACHE_PERMANENT,
- 'created' => REQUEST_TIME,
- );
-
- // Restore preferred header names based on the lower-case names returned
- // by drupal_get_http_header().
- $header_names = _drupal_set_preferred_header_name();
- foreach (drupal_get_http_header() as $name_lower => $value) {
- $cache->data['headers'][$header_names[$name_lower]] = $value;
- if ($name_lower == 'expires') {
- // Use the actual timestamp from an Expires header if available.
- $cache->expire = strtotime($value);
- }
- }
-
- if ($cache->data['body']) {
- if (config('system.performance')->get('response.gzip') && extension_loaded('zlib')) {
- $cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
- }
- cache('page')->set($cache->cid, $cache->data, $cache->expire, $cache->tags);
- }
- return $cache;
- }
-}
-
-/**
* Executes a cron run when called.
*
* Do not call this function from a test. Use $this->cronRun() instead.
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 869d4ee..70024e2 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -36,6 +36,16 @@ class DrupalKernel extends Kernel {
}
/**
+ * Overrides Kernel::boot().
+ */
+ public function boot() {
+ // We bootstrap code here rather than init() so that we don't do the heavy
+ // code-load during a cache hit.
+ drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+ parent::boot();
+ }
+
+ /**
* Returns an array of available bundles.
*/
public function registerBundles() {
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 8065349..6da9916 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -71,11 +71,8 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
// use partial page caching more extensively.
// Commit the user session, if needed.
drupal_session_commit();
- if (config('system.performance')->get('cache.page.enabled') && ($cache = drupal_page_set_cache($response->getContent()))) {
- drupal_serve_page_from_cache($cache);
- // drupal_serve_page_from_cache() already printed the response.
- $response->setContent('');
- $response->headers->remove('cache-control');
+ if (config('system.performance')->get('cache.page.enabled')) {
+ $this->setCacheHeaders($response, $event);
}
else {
$response->headers->set('Expires', 'Sun, 19 Nov 1978 05:00:00 GMT');
@@ -83,6 +80,22 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
}
}
+ public function setCacheHeaders($response, $event) {
+ $response->isNotModified($event->getRequest());
+
+ $vary = array('Accept-Encoding');
+ // @todo: get this value from config('system.performance').
+ if (!variable_get('omit_vary_cookie', FALSE)) {
+ $vary[] = 'Cookie';
+ }
+ $response->setVary($vary);
+
+ $max_age = (int)config('system.performance')->get('cache.page.max_age');
+ $max_age = !isset($_COOKIE[session_name()]) ? $max_age : 0;
+ $response->setPublic();
+ $response->setMaxAge($max_age);
+ }
+
/**
* Registers the methods in this class that should be listeners.
*
diff --git a/core/lib/Drupal/Core/HttpCache.php b/core/lib/Drupal/Core/HttpCache.php
new file mode 100644
index 0000000..e1da291
--- /dev/null
+++ b/core/lib/Drupal/Core/HttpCache.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\Core;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\HttpCache\HttpCache as SymfonyHttpCache;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpCache\Esi;
+use Symfony\Component\HttpKernel\HttpCache\Store;
+use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
+
+class HttpCache extends SymfonyHttpCache {
+
+ /**
+ * Constructor.
+ *
+ * @param HttpKernelInterface $kernel
+ * An HttpKernelInterface instance
+ * @param string $cacheDir
+ * The cache directory (default used if null)
+ */
+ public function __construct(HttpKernelInterface $kernel, StoreInterface $store, array $options = array()) {
+ // @todo: this is a total hack to make tests work. Refactor this out when
+ // our chimera of old-skool bootstrap and Symfony is less monstrous.
+ drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
+
+ // @todo Make this conditional. I suppose it will replace the block cache setting.
+ $esi = $this->createEsi();
+ parent::__construct($kernel, $store, $esi, array_merge(array('debug' => $kernel->isDebug()), $this->getOptions()));
+ }
+
+ /**
+ * Forwards the Request to the backend and returns the Response.
+ *
+ * @param Request $request
+ * A Request instance
+ * @param Boolean $raw
+ * Whether to catch exceptions or not
+ * @param Response $entry
+ * A Response instance (the stale entry if present, null otherwise)
+ *
+ * @return Response A Response instance
+ */
+ protected function forward(Request $request, $raw = false, Response $entry = null) {
+ $this->getKernel()->boot();
+ $this->getKernel()->getContainer()->set('cache', $this);
+ $this->getKernel()->getContainer()->set('esi', $this->getEsi());
+
+ return parent::forward($request, $raw, $entry);
+ }
+
+ protected function createEsi() {
+ return new Esi();
+ }
+
+ protected function getOptions() {
+ return array(
+ 'debug' => TRUE
+ );
+ }
+}
diff --git a/index.php b/index.php
index 38177ab..db58ff6 100644
--- a/index.php
+++ b/index.php
@@ -13,6 +13,8 @@
use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\HttpCache;
+use Symfony\Component\HttpKernel\HttpCache\Store;
/**
* Root directory of Drupal installation.
@@ -25,11 +27,15 @@ define('DRUPAL_ROOT', getcwd());
// @see Drupal\Core\EventSubscriber\PathSubscriber;
// @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
-drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
// @todo Figure out how best to handle the Kernel constructor parameters.
$kernel = new DrupalKernel('prod', FALSE);
+if (config('system.performance')->get('cache.page.enabled')) {
+ $kernel = new HttpCache($kernel, new Store(variable_get('file_public_path', conf_path() . '/files/http_cache')));
+}
+
// Create a request object from the HTTPFoundation.
$request = Request::createFromGlobals();
$response = $kernel->handle($request)->prepare($request)->send();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment