Forum Moderators: coopster

Message Too Old, No Replies

Content length header with gzip enabled

gzip, content length, header, cache, size of file

         

topwebdesigns

1:35 pm on Nov 23, 2009 (gmt 0)

10+ Year Member



This seems to be a fairly obvious problem and I even found a PHP bug report for it, but there doesn't seem to be an adequate solution available.

Basically i'm trying to cache various css files into one compressed file. This works perfectly. However when I output a content-length header, it will load for ages.

I discovered that this is because i've got gzip turned on and although the file is 20kb on my server (what I was putting in the content-length) the browser sees it as being 4kb due to the gzip.

Now a simple solution to getting the right content-length would normally be something like this:

if (stripos($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false) {
ob_start("ob_gzhandler");
} else {
ob_start();
}
echo $contentOutput;
header('Content-Length: '.ob_get_length());
ob_end_flush();

However when I do this on my server. I get an error saying ob_gzhandler cannot be set twice. This makes sense since i'm guessing PHP sets this at the very beginning when gzip is on.

However, I would have thought if I then did:

ob_start();
echo $contentOutput;
header('Content-Length: '.ob_get_length());
ob_end_flush();

The ob_get_length(); would get the gzip size. But it doesn't, which leaves me a bit stuck.

Now i'm sure I could come up with some sort of work around. Possibly using gzencode and strlen on the $contentOutput. However i'd quite like to redistribute this script to the community, which means i'd have to do various checks dependant on the users server settings. So really what i'm asking is.

1) How can I check if gzip is turned on.
2) If it is, what's the best way to get the length. Do I need to use gzencode and strlen or is there a better way?

I'm guessing i'll end up with something like this:

if(gzip is turned_on) {
contentOutput = gzencode($contentOutput, 5);
header("Content-Length: ".strlen(contentOutput));
} else {
if(gzip isn't on but browser accepts it) {
ob_start("ob_gzhandler");
} else {
ob_start();
}
echo $contentOutput;
header('Content-Length: '.ob_get_length());
ob_end_flush();
}

I'm just not sure exactly what to check for, or if this is actually the best way to do it.

tfk11

3:57 am on Nov 30, 2009 (gmt 0)

10+ Year Member



I had a similar issue... ended up putting the output into a regular output buffer and then handling the compression manually.

ob_start();

// output all your css

if( strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false ) {

header('Content-Length: '.ob_length();

} else {

// gzip the response and prepend the gzip header
$gz_output = "\x1f\x8b\x08\x00\x00\x00\x00\x00".gzcompress( ob_get_contents(), 9);
$gz_content_length = strlen($gz_page);

// purge the output buffer
ob_clean();

header('Content-Length: '.$gz_content_length);
header('Content-Encoding: gzip');
header('Vary: Accept-Encoding');

echo $gz_output;

}

exit;