summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-01-10 14:50:54 +0100
committerAndrey Andreev <narf@devilix.net>2014-01-10 14:50:54 +0100
commit155ee7231c0ef72dc362c7d6423b2e4600024d3c (patch)
treea3d585cd4e224eba87bbaaa95317dd17b1f44ef0
parenta0a73c977ce25911f56948d89de817b3ca83adcb (diff)
Compress output before storing it to cache, if output compression is enabled
Based on PR #964
-rw-r--r--application/config/config.php3
-rw-r--r--system/core/Output.php82
-rw-r--r--user_guide_src/source/changelog.rst1
-rw-r--r--user_guide_src/source/general/caching.rst3
4 files changed, 69 insertions, 20 deletions
diff --git a/application/config/config.php b/application/config/config.php
index cd2ca479b..c46839330 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -381,6 +381,9 @@ $config['csrf_exclude_uris'] = array();
| Even if it does, however, not all browsers support compression
| so enable only if you are reasonably sure your visitors can handle it.
|
+| Only used if zlib.output_compression is turned off in your php.ini.
+| Please do not use it together with httpd-level output compression.
+|
| VERY IMPORTANT: If you are getting a blank page when compression is enabled it
| means you are prematurely outputting something to your browser. It could
| even be a line of whitespace at the end of one of your scripts. For
diff --git a/system/core/Output.php b/system/core/Output.php
index 10332f0d8..d2005cc41 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -58,21 +58,21 @@ class CI_Output {
*
* @var array
*/
- public $headers = array();
+ public $headers = array();
/**
* List of mime types
*
* @var array
*/
- public $mimes = array();
+ public $mimes = array();
/**
* Mime-type for the current page
*
* @var string
*/
- protected $mime_type = 'text/html';
+ protected $mime_type = 'text/html';
/**
* Enable Profiler flag
@@ -82,11 +82,18 @@ class CI_Output {
public $enable_profiler = FALSE;
/**
- * zLib output compression flag
+ * php.ini zlib.output_compression flag
*
* @var bool
*/
- protected $_zlib_oc = FALSE;
+ protected $_zlib_oc = FALSE;
+
+ /**
+ * CI output compression flag
+ *
+ * @var bool
+ */
+ protected $_compress_output = FALSE;
/**
* List of profiler sections
@@ -102,7 +109,7 @@ class CI_Output {
*
* @var bool
*/
- public $parse_exec_vars = TRUE;
+ public $parse_exec_vars = TRUE;
/**
* Class constructor
@@ -113,7 +120,14 @@ class CI_Output {
*/
public function __construct()
{
+ global $CFG;
+
$this->_zlib_oc = (bool) @ini_get('zlib.output_compression');
+ $this->_compress_output = (
+ $this->_zlib_oc === FALSE
+ && $CFG->item('compress_output') === TRUE
+ && extension_loaded('zlib')
+ );
// Get mime types for later
$this->mimes =& get_mimes();
@@ -436,15 +450,14 @@ class CI_Output {
if ($this->parse_exec_vars === TRUE)
{
$memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
-
$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
}
// --------------------------------------------------------------------
// Is compression requested?
- if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
- && extension_loaded('zlib')
+ if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed
+ && $this->_compress_output === TRUE
&& isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
{
ob_start('ob_gzhandler');
@@ -468,6 +481,21 @@ class CI_Output {
// simply echo out the data and exit.
if ( ! isset($CI))
{
+ if ($this->_compress_output === TRUE)
+ {
+ if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
+ {
+ header('Content-Encoding: gzip');
+ header('Content-Length: '.strlen($output));
+ }
+ else
+ {
+ // User agent doesn't support gzip compression,
+ // so we'll have to decompress our cache
+ $output = gzinflate(substr($output, 10, -8));
+ }
+ }
+
echo $output;
log_message('debug', 'Final output sent to browser');
log_message('debug', 'Total execution time: '.$elapsed);
@@ -530,9 +558,9 @@ class CI_Output {
return;
}
- $uri = $CI->config->item('base_url').
- $CI->config->item('index_page').
- $CI->uri->uri_string();
+ $uri = $CI->config->item('base_url')
+ .$CI->config->item('index_page')
+ .$CI->uri->uri_string();
$cache_path .= md5($uri);
@@ -542,16 +570,29 @@ class CI_Output {
return;
}
- $expire = time() + ($this->cache_expiration * 60);
-
- // Put together our serialized info.
- $cache_info = serialize(array(
- 'expire' => $expire,
- 'headers' => $this->headers
- ));
-
if (flock($fp, LOCK_EX))
{
+ // If output compression is enabled, compress the cache
+ // itself, so that we don't have to do that each time
+ // we're serving it
+ if ($this->_compress_output === TRUE)
+ {
+ $output = gzencode($output);
+
+ if ($this->get_header('content-type') === NULL)
+ {
+ $this->set_content_type($this->mime_type);
+ }
+ }
+
+ $expire = time() + ($this->cache_expiration * 60);
+
+ // Put together our serialized info.
+ $cache_info = serialize(array(
+ 'expire' => $expire,
+ 'headers' => $this->headers
+ ));
+
fwrite($fp, $cache_info.'ENDCI--->'.$output);
flock($fp, LOCK_UN);
}
@@ -560,6 +601,7 @@ class CI_Output {
log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
return;
}
+
fclose($fp);
@chmod($cache_path, FILE_WRITE_MODE);
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 0488d9d4a..0e656a10d 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -439,6 +439,7 @@ Release Date: Not Released
- Added a second argument to method ``set_content_type()`` that allows setting the document charset as well.
- Added methods ``get_content_type()`` and ``get_header()``.
- Added method ``delete_cache()``.
+ - Changed caching behavior to compress the output before storing it, if ``$config['compress_output']`` is enabled.
- :doc:`Config Library <libraries/config>` changes include:
diff --git a/user_guide_src/source/general/caching.rst b/user_guide_src/source/general/caching.rst
index 48385d6c9..f499f6e93 100644
--- a/user_guide_src/source/general/caching.rst
+++ b/user_guide_src/source/general/caching.rst
@@ -45,6 +45,9 @@ you. Once the tag is in place, your pages will begin being cached.
caching will only work if you are generating display for your
controller with a :doc:`view <./views>`.
+.. important:: If you change configuration options that might affect
+ your output, you have to manually delete your cache files.
+
.. note:: Before the cache files can be written you must set the file
permissions on your *application/cache/* directory such that
it is writable.