- Impact
- 5
Hey, I had an issue where I needed to make browsers cache my static content (images, css, javascript, etc.) to reduce the server load. However due to the incompetent host I was unable to use Apache's EXPIRES_MODULE, so I came up with this solution:
Step 1: Create the following directory structure: (static/images, static/css, static/javascript) that is publicly accessible; i.e. http://www.example.com/static/images/xample.jpg
Step 2: Add the following to your .htaccess:
Step 3: Create a static.php file in your "static" directory (http://www.example.com/static/static.php) with this code:
Step 4: Call your static content like so: http://www.example.com/images/myimage.jpg, http://www.example.com/css/mystylesheet.css, http://www.example.com/javascript/myscript.js, http://www.example.com/images/subdir/myimage2.jpg
* note this was just a quick and dirty script that has not been optimized in any way, it was tested with the latest version of Firefox and IE. If you see any issues let me know
Step 1: Create the following directory structure: (static/images, static/css, static/javascript) that is publicly accessible; i.e. http://www.example.com/static/images/xample.jpg
Step 2: Add the following to your .htaccess:
Code:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(images|css|javascript)/(.*)$ static/static.php?requested_file=$1/$2 [L]
Step 3: Create a static.php file in your "static" directory (http://www.example.com/static/static.php) with this code:
PHP:
<?php
/*
* The aim of this file is to handle static files {images, javascript, css,
* html, etc.} by setting file expiration headers so that the browsers cache the
* files instead of requesting them again and again on each request.
*
* **** THIS IS TO BYPASS THE NEED FOR THE APACHE EXPIRES_MODULE ****
*/
$requested_file = $_GET["requested_file"];
/*
* Make sure a filename was passed and that it exists on the server.
*/
isset($requested_file) or die("Invalid file: {$requested_file}");
is_file($requested_file) or die("The file '{$requested_file}' does not exist.");
/*
* The accepted mime types
*/
$mime_map = array('bm' => 'image/bmp', 'bmp' => 'image/bmp',
'css' => 'text/css', 'gif' => 'image/gif', 'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg', 'mjpg' => 'video/x-motion-jpeg', 'xml' => 'text/xml',
'png' => 'image/png');
/*
*
*/
class File {
var $filepath, $mtime;
var $dirname, $name, $extension;
function __construct($file) {
$this->filepath = $file;
$this->mtime = filemtime($this);
$path_parts = pathinfo($this);
$this->dirname = $path_parts['dirname'];
$this->name = $path_parts['basename'];
$this->extension = strtolower($path_parts['extension']);
}
function get_etag() {
return md5($this->mtime.$this);
}
function content() {
ob_start();
readfile($this);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
function __toString() {
return (string)$this->filepath;
}
}
$file = new File($requested_file);
/*
* Make sure the file type is supported
*/
array_key_exists($file->extension, $mime_map)
or die("Invalid file type: $file->extension");
/*
* Caching headers
*/
$etag = $file->get_etag();
$time = gmdate('r', $file->mtime);
$test1 = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
&& $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $time;
$test2 = isset($_SERVER['HTTP_IF_NONE_MATCH'])
&& str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == $etag;
if($test1 || $test2){
header('HTTP/1.1 304 Not Modified');
exit();
}
header("Last-Modified: $time");
header("Cache-Control: must-revalidate");
header("Expires: $time");
header("Etag: $etag");
header("Content-type: ".$mime_map[$file->extension]);
echo $file->content();
?>
Step 4: Call your static content like so: http://www.example.com/images/myimage.jpg, http://www.example.com/css/mystylesheet.css, http://www.example.com/javascript/myscript.js, http://www.example.com/images/subdir/myimage2.jpg
* note this was just a quick and dirty script that has not been optimized in any way, it was tested with the latest version of Firefox and IE. If you see any issues let me know
Last edited: