Welcome Guest, Not a member yet? Register   Sign In
Modification to CI: output caching with HTTP headers
#1

[eluser]Patrick Savalle[/eluser]
I needed the output caching to save the HTTP headers (serving JSON and XML from views). Currently CI does not save these headers in the cache. A modification is very simple. I hacked it into the system files. If you're not as lazy as me you could place these functions in a application/core/CI_Output.php override.

Two functions need to be overriden. These are the new versions.

(I also added LZF compression but did not test that. As I said: I'm lazy. The caching however works and now does save the headers with the cached file.)

In system/core/output.php

Code:
// --------------------------------------------------------------------

    /**
     * Write a Cache File
     *
     * @access public
     * @return void
     */
    function _write_cache( $output )
    {
        $CI = &get;_instance( );
        $path = $CI->config->item( 'cache_path' );

        $cache_path = ($path == '') ? APPPATH . 'cache/' : $path;

        if ( !is_dir( $cache_path ) OR !is_really_writable( $cache_path ) )
        {
            log_message( 'error', "Unable to write cache file: " . $cache_path );
            return;
        }

        $uri = $CI->config->item( 'base_url' ) . $CI->config->item( 'index_page' ) . $CI->uri->uri_string( );

        $cache_path .= md5( $uri );

        if ( !$fp = @fopen( $cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE ) )
        {
            log_message( 'error', "Unable to write cache file: " . $cache_path );
            return;
        }

        $expire = time( ) + ($this->cache_expiration * 60);

        if ( flock( $fp, LOCK_EX ) )
        {
            $cache = serialize( array( $expire, $this->headers, $output ) );

            if ( function_exists( 'lzf_decompress' ) && function_exists( 'lzf_compress' ) )
            {
                $cache = lzf_compress( $cache );
            }

            fwrite( $fp, $cache );
            flock( $fp, LOCK_UN );
        }
        else
        {
            log_message( 'error', "Unable to secure a file lock for file at: " . $cache_path );
            return;
        }
        fclose( $fp );
        @chmod( $cache_path, FILE_WRITE_MODE );

        log_message( 'debug', "Cache file written: " . $cache_path );
    }

    // --------------------------------------------------------------------

    /**
     * Update/serve a cached file
     *
     * @access public
     * @return void
     */
    function _display_cache( &$CFG, &$URI )
    {
        $cache_path = ($CFG->item( 'cache_path' ) == '') ? APPPATH . 'cache/' : $CFG->item( 'cache_path' );

        // Build the file path.  The file name is an MD5 hash of the full URI
        $uri = $CFG->item( 'base_url' ) . $CFG->item( 'index_page' ) . $URI->uri_string;

        $filepath = $cache_path . md5( $uri );

        if ( [email protected]_exists( $filepath ) )
        {
            return FALSE;
        }

        if ( !$fp = @fopen( $filepath, FOPEN_READ ) )
        {
            return FALSE;
        }

        flock( $fp, LOCK_SH );

        $cache = NULL;
        if ( filesize( $filepath ) > 0 )
        {
            $cache = fread( $fp, filesize( $filepath ) );
        }

        flock( $fp, LOCK_UN );
        fclose( $fp );

        if ( function_exists( 'lzf_decompress' ) && function_exists( 'lzf_compress' ) )
        {
            $cache = lzf_decompress( $cache );
        }

        list( $expire, $headers, $output ) = unserialize( $cache );

        // Has the file expired? If so we'll delete it.
        if ( time( ) >= $expire )
        {
            if ( is_really_writable( $cache_path ) )
            {
                @unlink( $filepath );
                log_message( 'debug', "Cache file has expired. File deleted" );
                return FALSE;
            }
        }

        // Output the headers
        if ( count( $headers ) > 0 )
        {
            foreach ( $headers as $header )
            {
                header( $header[0], $header[1] );
            }
        }

        // Display the cache
        $this->_display( $output );
        log_message( 'debug', "Cache file is current. Sending it to browser." );
        return TRUE;
    }
#2

[eluser]Patrick Savalle[/eluser]
Ok, ok. I made a MY_Output.php override for it.

Just place this class in /application/core/MY_Output.php and you will have a better output caching.

Code:
<?php
if ( !defined( 'BASEPATH' ) )
    exit( 'No direct script access allowed' );

class MY_Output extends CI_Output
{
    /**
     * Write a Cache File
     *
     * @access public
     * @return void
     */
    function _write_cache( $output )
    {
        $CI = &get;_instance( );
        $path = $CI->config->item( 'cache_path' );

        $cache_path = ($path == '') ? APPPATH . 'cache/' : $path;

        if ( !is_dir( $cache_path ) OR !is_really_writable( $cache_path ) )
        {
            log_message( 'error', "Unable to write cache file: " . $cache_path );
            return;
        }

        $uri = $CI->config->item( 'base_url' ) . $CI->config->item( 'index_page' ) . $CI->uri->uri_string( );

        $cache_path .= md5( $uri );

        if ( !$fp = @fopen( $cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE ) )
        {
            log_message( 'error', "Unable to write cache file: " . $cache_path );
            return;
        }

        $expire = time( ) + ($this->cache_expiration * 60);

        if ( flock( $fp, LOCK_EX ) )
        {
            $cache = serialize( array( $expire, $this->headers, $output ) );

            if ( function_exists( 'lzf_decompress' ) && function_exists( 'lzf_compress' ) )
            {
                $cache = lzf_compress( $cache );
            }

            fwrite( $fp, $cache );
            flock( $fp, LOCK_UN );
        }
        else
        {
            log_message( 'error', "Unable to secure a file lock for file at: " . $cache_path );
            return;
        }
        fclose( $fp );
        @chmod( $cache_path, FILE_WRITE_MODE );

        log_message( 'debug', "Cache file written: " . $cache_path );
    }

    // --------------------------------------------------------------------

    /**
     * Update/serve a cached file
     *
     * @access public
     * @return void
     */
    function _display_cache( &$CFG, &$URI )
    {
        $cache_path = ($CFG->item( 'cache_path' ) == '') ? APPPATH . 'cache/' : $CFG->item( 'cache_path' );

        // Build the file path.  The file name is an MD5 hash of the full URI
        $uri = $CFG->item( 'base_url' ) . $CFG->item( 'index_page' ) . $URI->uri_string;

        $filepath = $cache_path . md5( $uri );

        if ( [email protected]_exists( $filepath ) )
        {
            return FALSE;
        }

        if ( !$fp = @fopen( $filepath, FOPEN_READ ) )
        {
            return FALSE;
        }

        flock( $fp, LOCK_SH );

        $cache = NULL;
        if ( filesize( $filepath ) > 0 )
        {
            $cache = fread( $fp, filesize( $filepath ) );
        }

        flock( $fp, LOCK_UN );
        fclose( $fp );

        if ( function_exists( 'lzf_decompress' ) && function_exists( 'lzf_compress' ) )
        {
            $cache = lzf_decompress( $cache );
        }

        list( $expire, $headers, $output ) = unserialize( $cache );

        // Has the file expired? If so we'll delete it.
        if ( time( ) >= $expire )
        {
            if ( is_really_writable( $cache_path ) )
            {
                @unlink( $filepath );
                log_message( 'debug', "Cache file has expired. File deleted" );
                return FALSE;
            }
        }

        // Output the headers
        if ( count( $headers ) > 0 )
        {
            foreach ( $headers as $header )
            {
                header( $header[0], $header[1] );
            }
        }

        // Display the cache
        $this->_display( $output );
        log_message( 'debug', "Cache file is current. Sending it to browser." );
        return TRUE;
    }  
}




Theme © iAndrew 2016 - Forum software by © MyBB