For some reasons it might make sense to deliver static assets via memcached. As nginx is able to directly talk to memcached, this is even more obvious. But sometimes, there is no backend to put the files into the cache. Therefore, we will have to do it ourselves. Here’s a litte howto, that extends what is written here. I had to extend it as some files were crippled. Therefore, we read the files into a buffer, do some fancy GD operations (mainly not to lose transparency on PNG and GIF) and finally push the buffer into memcached from where nginx takes it.
Nginx expects DOCUMENT_URI as key and the file as value.
First of all, you will need the right nginx config. Like that:
[sourcecode language=”shell”]
# this is just to make sure we deliver the proper content type
location ~* \.jpg$ {
gzip off;
expires max;
# this is to know whether the caching works
add_header x-header-memcached true;
default_type image/jpeg;
#here we define the key
set $memcached_key $uri;
memcached_pass localhost:11211;
memcached_buffer_size 8k;
# cache misses will redirect to this
error_page 404 = @cache_miss;
}
location ~* \.png$ {
gzip off;
expires max;
add_header x-header-memcached true;
default_type image/png;
set $memcached_key $uri;
memcached_pass localhost:11211;
error_page 404 = @cache_miss;
}
location ~* \.gif$ {
gzip off;
expires max;
add_header x-header-memcached true;
default_type image/gif;
set $memcached_key $uri;
memcached_pass localhost:11211;
error_page 404 = @cache_miss;
}
# here is what we do in case a file could not be found
location @cache_miss {
# we need to specify the document root as @cache_miss is a virtual location
root /var/www/www.example.com/htdocs;
# this is just for us so that we know that the delivered file was came from the file system
add_header x-header-memcached false;
}[/sourcecode]
And finally, we need a script that imports all the files into the cache. Like the one below. Important: You will have to run the script in your document root as the final file operations are performed with the mangled file name.
[php]
<?
$mylist=rscandir("/var/www/www.example.com/htdocs"); // where to scan
$srch = array(‘/var/www/www.example.com/htdocs’); // file name mangling
$newval = array(”); //here you could enter something that will be replaced
$memcache = new Memcache;
$memcache->addServer(‘127.0.0.1’);
$memcache->addServer(‘127.0.0.2’); // Add more servers if you like to
// here we recursively scan the given directory and add .jpg, .png and.gif to the file array
function rscandir($base=”, &$data=array()) {
$array = array_diff(scandir($base), array(‘.’, ‘..’));
foreach($array as $value) {
if (is_dir($base."/".$value)) {
$data = rscandir($base."/".$value,$data);
}
elseif (is_file($base."/".$value)) {
$rest = substr($value, -4);
if ((!strcmp($rest,’.jpg’)) || (!strcmp($rest,’.png’)) || (!strcmp($rest,’.gif’)) ) {
$data[] = $base."/".$value;
}
}
}
return $data;
}
while (list($key, $val) = each($mylist)) {
// the URL will be used as key
$url=str_replace($srch,$newval,$val);
// detect the file type from the file’s content
$mime_type = exif_imagetype($val);
if ( $mime_type == 2) { //JPEG
$image=imagecreatefromjpeg($val);
ob_start();
imagejpeg($image);
$output=ob_get_contents();
imagedestroy($image);
ob_end_clean();
$memcache->add($url,$output,false,0);
} elseif ( $mime_type == 3) { //PNG
$image=imagecreatefrompng($val);
imageinterlace($image, true);
imagealphablending($image, true);
imagesavealpha($image, true);
ob_start();
imagepng($image);
$output=ob_get_contents();
imagedestroy($image);
ob_end_clean();
$memcache->add($url,$output,false,0);
} elseif ( $mime_type == 1) { //GIF
$image=imagecreatefromgif($val);
imageinterlace($image, true);
$background = imagecolorallocate($image, 0, 0, 0);
imagecolortransparent($image, $background);
ob_start();
imagegif($image);
$output=ob_get_contents();
imagedestroy($image);
ob_end_clean();
$memcache->add($url,$output,false,0);
}
echo "$val – $mime_type\n";
}
?>
[/php]