Aquarionics

Wednesday 9th July 2003

Gzip Compression with PHP

Mark re-recommended compressing pages today, which is always a useful idea. Sneaky (The server Aqcom wallows on) has mod_gzip installed, which automagically compresses all static pages before sending them. Great, but not so cool for the dynamic PHP pages that the rest of the site works on.

My solution to this was to kill two birds with one stone. The first is that since Aquarionics caches every page the first time it’s loaded the cache directory can get quite large – esspecially when something like Google comes in and looks at (and therefore generates) all the pages on the site. First thing was then to modify my cache generation system as follows:

The cache-save system – which writes the contents of the output buffer to a file – just used @gzopen@ and @gzwrite@ instead of the standard PHP file-write code, and the cache-load decompressed it.

Next, testing for compression and sending if possible. First was simple, PHP gives you an array $HTTP_SERVER_VARS containing all the stuff the client sends, so I just needed to check the HTTP_ACCEPT_ENCODING variable for the string “gzip”:

if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], "gzip")){
$compress = true;
} else {
$compress = false;
}

and then the complicated bit, sending the right version. If the compression was on, all I needed to do was send the right headers and pass through the contents of the cache. If not, I would decompress the cache and pass that. Note that while there is a function to directly output the contents of a gzip file (gzpassthru) I tend to avoid it because I want to send a content-length header too, and I can’t get that if I only know the length after the output. gzpassthru returns the number of bytes out, but header("Content-Length: ".gzpassthru($cachename)) was abandoned for readiblity, though it’s prefectly valid. Anyway, the code:

header ("ETag: "$etag""); 
if ($etagval==$etag || $HTTP_IF_MODIFIED_SINCE == $gmt_mtime) {
header("HTTP/1.1 304 Not Modified");
} elseif ($compress){
header("X-Compression: gzip");
header("Content-Encoding: gzip");
header("Content-Length: ".filesize($_EP['cachedir']."/".$cachename));
readfile($_EP['cachedir']."/".$cachename) or die("Couldn't open cache");
} else {
header("X-Compression: None");
$zd = gzopen ($_EP['cachedir']."/".$cachename, "r") or die("Couldn't open cache");
$contents = gzread ($zd, 1000000);
header("Content-Length: ".strlen($contents));
echo $contents;
gzclose ($zd);
}

(I’ve left the etag code in for context), so now all pages should be gzipped any time they are accessed after the first (First time it generates the content, echos it, then compresses it and writes it to the cache) The full code for all this is at the top and bottom of Epistula.php

Those who spoke on this:

gravatar image

Ronaldo:

2003-07-10 12:44 19 hrs after the Original Article

Starting from PHP 4.0.4, you can automatically compress your pages via the buffering engine. It just required the following line at the beginning of the file:

ob_start “ob_gzhandler”);

Comment Link

gravatar image

pol:

2003-07-12 14:11 2 days after Ronaldo

As far as I can tell mod_gzip does stream compression on everything set by the server – not just static content. This is the reason that ob_gzhandler isn’t enabled on Sneaky.

Comment Link


Nicholas 'Aquarion' Avenell is a web developer in London, you can find out more about him or how to get in touch.

There are more Articles, Projects, Journal Entries, Photographs and things that defy description here, too.

If you're looking for something specific, there are Calendar & Category -based lists of everything.

And if you want to follow stuff that appears here, try a Syndication Feed, or the generic Feed of everything.


Aquarion's last Twitter was: [updating]
Twitter last updated


More Journal:

[RSS Icon]
[ESF Icon]
[CDF Icon]

That which is relevant:


Explain Ads
© 2000 to 2008 inclusive Nicholas Avenell
All comments are the property of their creators, published with permission
(Unless otherwise indicated, the opinions and sentiments expressed on this site are those of the author and not of any organisation of which he is an affiliate, including his employer. Caveat Lector, E&OE. sigh)
0.310 seconds, 19 queries, 2.66Mb on Wed, 01 Oct 2008 10:41:11 +0000
Generated by Epistula Version 2.0.3