diff options
author | Andrey Andreev <narf@devilix.net> | 2014-01-10 14:50:54 +0100 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2014-01-10 14:50:54 +0100 |
commit | 155ee7231c0ef72dc362c7d6423b2e4600024d3c (patch) | |
tree | a3d585cd4e224eba87bbaaa95317dd17b1f44ef0 | |
parent | a0a73c977ce25911f56948d89de817b3ca83adcb (diff) |
Compress output before storing it to cache, if output compression is enabled
Based on PR #964
-rw-r--r-- | application/config/config.php | 3 | ||||
-rw-r--r-- | system/core/Output.php | 82 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 1 | ||||
-rw-r--r-- | user_guide_src/source/general/caching.rst | 3 |
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. |