Home » Php » php – Output Compression problems

php – Output Compression problems

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m facing a problem trying to use php output compression , I’ve been searching for many hours and I still have no clues…

Lets see a simple script :

<?php 
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";

if(function_exists('ob_gzhandler')) 
{
  ob_start('ob_gzhandler');
}
else {
  ob_start();
}


echo $response;
ob_end_flush();

This is a method I’ve found all over the internet, and it used to work for me … but not any more (and I’ve got no idea why) .

If i look at the http headers when I call this script :

Request :

Host: 192.168.51.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: max-age=0

Response :

Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:19:07 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: PHP/5.5.12

You can see that the response is NOT zipped (Firebird gives me a 0.06ko response), and the server sends the responses using chunked encoding.

I tried an alternate method to send zipped responses :

<?php 
    $response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh"; 
    $replyBody = gzencode($response, 9, FORCE_GZIP);
    header("Content-Encoding: gzip");
    echo $replyBody;

And the response headers are as follow (the request headers are always the same):

Response :

Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:29:01 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.12

As you can see, this is basically the same behavior as in the first method.

Then if I try this :

<?php 
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
$replyBody = gzencode($response, 9, FORCE_GZIP);
echo $replyBody;

I receive something that looks like a zipped response (random characters), and the output size is 0.03ko .

Here a the corresponding response http headers :

Connection: Keep-Alive
Content-Length: 31
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:32:46 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
X-Powered-By: PHP/5.5.12

It lets me think that the zipping part is working correctly because the output size has been reduced (it is obviously not readable because the browser can’t know that it is zipped content).

That’s where I’m lost …

If I understand it right, when I manually send zipped data (using gzencode) , If I set the header”Content-Encoding: gzip” , the webserver/php seems to UNZIP it before sending it to the browser ??? How is it possible ?

And Why is it sending it as “chunked” data instead of setting the Content-Length header ?

I tried to set the Content-Length manually in the response; it doesn’t change anything (it won’t appear in the response headers, I’ll still have a “chunked” response.

I’ve seen somewhere that I have to write the “Content-Length” header before sending other data or header to avoid the “chunked” response, I tried it and still had the same results.

I thought it could be a problem with BOM characters at the beginning of my php test script, but it is saved in UTF-8 without BOM encoding so I don’t think it ‘s the problem.

I have this problem on my dev computer (using wampserver) AND in the production environment (IIS), previously it was working on both servers.

I have this problem using several browsers, and I checked the response sizes I wrote previously with fiddler.

Does anyone see where the problem could be ?

Thanks in advance

How to&Answers:

I’d go through the following checklist if I were you.

1. Check zlib extension is installed or not.

ob_gzhandler needs the zlib extension to work. Without which it just silently falls back to default settings.

2. Verify that you don’t have zlib.output_compression enabled in your php.ini.

As explained here, even though zlib.output_compression is preferred over ob_gzhandler(), you can not use both simultaneously. So your code becomes..

if (extension_loaded('zlib') && !ini_get('zlib.output_compression')){
    ob_start('ob_gzhandler');
} 

3. Check if headers have already been sent eg. something got output-ted before the
ob_start(ob_gzhandler) This will prevent the compressed output from being detected as such. eg. Having some character before <?php or an echo somewhere up in the code.

4. Make sure you aren’t using all of the above in addition to the gzipping in apache(mod_deflate).
This will only cause the output to be double gzipped which most probably will confuse the browser.