Skip to content

Asset Gzip cache serve

World Wide Web Server edited this page Jul 4, 2012 · 41 revisions

[h4]gzip/cache/serve js,css, jpg, png etc..[/h4]

[pre]This helper can be used if

  1. You wish to reduce your assets size
  2. You wish cache your assets
  3. You wish to hide the full path of assets in your html
  4. You wish all of the above to be done with as little effort as possible [/pre] [quote] [b][size=4][url =http://www.flexablecontrol.com/downloads/gz_asset_helper_example.zip]gz_asset_helper_example.zip[/url][/size][/b] [/quote] [em]The only area you need to change is the settings area at the beginning of the class.[/em]

[code] var $debug = FALSE; [/code] [em] set for true to output all the settings instead of the asset[/em] [i]Hence the name [color=red]debug[/color][/i] [code] var $headers = array(); var $target_file = array(); var $sysValues = array(); [/code] [em] set some arrays for storing values[/em] [code] var $set = array( 'VERSION' => '0.75', 'path2assets' => APPPATH, 'asset_exp' => 25920000, 'uri' => '', ); [/code] [em]path2assests: is the path to your assets folders [/em] [em]asset_exp: is the expiry date of the cached asset (in milliseconds) [/em] [code] var $asset_types = array( "htm" => "text/html", "html" => "text/html", "js" => "text/javascript", "css" => "text/css", "xml" => "text/xml", "gif" => "image/gif", "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "png" => "image/png", "txt" => "text/plain"
); [/code] [em]asset_types: asset content [url=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html]types [/url][/em] [code]
var $assets_folder = array( 'js'=>'assets/js/', 'css'=>'assets/css/', 'gif'=>'assets/images/', 'jpg'=>'assets/images/', 'jpeg'=>'assets/images/', 'png'=>'assets/images/' ); [/code] [b]assets_folder: folders where assets can be found.[/b] [h3]Special Notice[/h3][b] after document root e.g. IF: home/www/directory/my_application/cache_folder THEN: directory/my_application/cache_folder [/b] [code] var $cache_folder = array( 'js'=>'system/cache/', 'css'=>'system/cache/', 'gif'=>'system/cache/', 'jpg'=>'system/cache/', 'jpeg'=>'system/cache/', 'png'=>'system/cache/', 'swf'=>'system/cache/'
); [/code] [em]cache_folder: the folders that the assets will be cached[/em]

[h2]The rest of the class you don't need to change[/h2] [code] function krunch() {

            $this->set['uri'] = $_SERVER['REQUEST_URI'];
            $this->check_file();
            $this->initialize();

        }
        
        function check_file()
        {
            $this->target_file = pathinfo( $this->set['uri']);
            
            // @ used to suppress errors. is_real = '' will stop the script
            $this->target_file['dirname'] =    @$this->assets_folder[ $this->target_file['extension'] ];//rewrite dirname
            
            $this->target_file['fullpath'] = @$this->set['path2assets'] .$this->target_file['dirname']. $this->target_file['basename'] ;
            
            $this->target_file['is_real'] = @file_exists( $this->target_file['fullpath'] );    

        }//EOF
                    
        function initialize()
        {
        
        $this->_check_writable();

            //if file exists and cache folder is writable
            if( $this->target_file['is_real'] == TRUE && $this->sysValues['cache_writable'] == TRUE )
            {

                $this->_get_settings();
                                
                $this->_get_target_type();

                $this->set_caching();
                
                $this->output();
            
            }else{

                header( 'HTTP/1.1 404 Not Found' );    
                
                if($this->target_file['is_real'] == FALSE)
                {
                    
                    echo "<H3>file ".$this->target_file['basename']." with extension ".$this->target_file['extension']." was not found</H3>";    
                                
                    
                }elseif($this->sysValues['cache_writable'] == FALSE)
                {
                
                    echo "<H3>The cache folder is not writable. Sorry!</H3>";    
                
                }
                
                exit;                    

            }    

        }//EOF
        
        function _check_writable()
        {
        
            $this->sysValues['cache_folder'] = $_SERVER['DOCUMENT_ROOT'].'/'.$this->cache_folder[ $this->target_file['extension'] ];
            
            $this->sysValues['cache_writable'] = is_writable( $this->sysValues['cache_folder'] );

            // Check if windows because windows does not support chmod(cache_folder, 0777)
            $this->sysValues['OS'] = strtoupper( substr( PHP_OS, 0, 3 ) );
                        
                        
            if(! $this->sysValues['cache_writable'] && $this->sysValues['OS'] !== 'WIN' )
            {
            
                $this->sysValues['cache_writable'] = @chmod($this->sysValues['cache_folder'], 0777);
            
            }                
        
        
        }

        function _get_settings()
        {
        
            $this->sysValues['gzip'] = extension_loaded('zlib');
            
            $this->sysValues['gzip'] = isset($_SERVER['HTTP_ACCEPT_ENCODING']);
            
            $this->sysValues['gzip'] = ( strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE )? TRUE: FALSE;
            
            $this->sysValues['gzip_target'] = $this->sysValues['cache_folder'] . $this->target_file['basename'].'.gz';
            
            $this->sysValues['gzip'] = file_exists( $this->sysValues['gzip_target'] );

            if($this->sysValues['gzip'])
            {
                $this->sysValues['new'] = ( filemtime($this->target_file['fullpath']) >  filemtime($this->sysValues['gzip_target']) )? TRUE : FALSE;
            
                if($this->sysValues['new'])
                { 
                    
                    unlink&#40; $this->sysValues['gzip_target'] &#41;;
                    
                    $this->sysValues['gzip'] = FALSE; //cause I deleted it
                
                }else{
                
                    return FALSE;
                
                }
            }
        
        }
        
        
        function set_caching()        
        {
            $age = $this->set['asset_exp'];
        
            $file_used_last = filemtime( $this->target_file['fullpath'] );
            
            $this->headers['headers'][]= "Last-Modified: " . date( "r", $file_used_last );

            $this->headers['headers'][] = "Expires: " . date( "r", ( $age + $file_used_last ) );
            
            $this->headers['headers'][] = "ETag: " .  dechex($file_used_last);
            
            $this->headers['headers'][] = "Cache-Control: " .  "public, must-revalidate, proxy-revalidate, max-age=" . $age . ", s-maxage=" . $age;    
            
            $this->headers['headers'][] = "Content-Type: " . $this->asset_types[ $this->target_file['extension'] ];    
                            
            $this->headers['headers'][] = "Content-Length: " . filesize( $this->target_file['fullpath'] ) ;    
                
        }//EOF set_caching


    function output()
    {
        if($this->debug)
        {        
            echo "<pre>";
                print_r($this->_debugger());
            echo "</pre>";
            exit;
            
        }elseif(!$this->debug){
        
            ob_start();
        
            foreach( $this->headers['headers'] as $headers)
            {
                header( $headers );
                
            }
        
            readfile&#40;$this->target_file['fullpath']&#41;;
            
            ob_end_flush();
            exit;
        }        
                    
    
    }//EOF output

// Private method _get_target_type function _get_target_type() {

        if($this->sysValues['gzip'])//gzip version found
        {
            $this->target_file['modify'] = filemtime( $this->sysValues['gzip_target'] );
                            
            $this->headers['headers'][] = "Content-Encoding: gzip";
            
            $this->target_file['fullpath'] = $this->sysValues['gzip_target'];                                    

        }elseif(!$this->sysValues['gzip'])//gzip version NOT found
                {    

                    $this->_compressor( $this->target_file['fullpath'], $this->sysValues['gzip_target'] );
                    
                    $this->target_file['modify'] = filemtime( $this->sysValues['gzip_target'] );
                            
                    $this->headers['headers'][] = "Content-Encoding: gzip";                        
                    
                    $this->target_file['fullpath'] = $this->sysValues['gzip_target'];
                    
                }
                        
    }//EOF

// Private method _compressor function _compressor( $srcFileName, $dstFileName ) { if(strlen($srcFileName) >= 1000) {
//too small to gzip return; }else{
if ( $file_out = gzopen( $dstFileName, "wb" ) ) { if ( $file_in = fopen( $srcFileName, "rb" ) ) { while( !feof( $file_in ) ) gzwrite( $file_out, fread( $file_in, 1024*512 ) ); fclose( $file_in );
} } } }

// Private method _uncompressor
// This method is note being used... maybe later at some stage!
function _uncompressor( $srcFileName, $dstFileName, $fileSize ) { // getting content of the compressed file $zp = gzopen( $srcFileName, "r" ); $data = fread ( $zp, $fileSize ); gzclose( $zp );

        // writing uncompressed file
        $fp = fopen&#40; $dstFileName, "w" &#41;;
        fwrite( $fp, $data );
        fclose( $fp );
    }    

// Private method _debug function _debugger( $temp=array() ) {

        $temp['sysValues'] = $this->sysValues;
        
        $temp['cache_folder'] = $this->cache_folder;

        $temp['set'] = $this->set;
        
        $temp['Headers'] = $this->headers;
    
        $temp['target_file'] = $this->target_file;
            
        $temp['assest_types'] = $this->asset_types;

        $temp['assets_folder'] = $this->assets_folder;
        
        return $temp;
        
    }

}//end Krunch [/code]

Clone this wiki locally