2

I read some articles about setting the content-length of a file that will be served. It has some benefits comparing to chunked downloads. The server serve chunks (don't know what the size of a chunk is anyway) when the content-length is unknown.

In PHP I use the ob_gzhandler to gzip html,js and css files and other text-based content. Setting the raw content-length before gzip output, results in strange side-effects because the length does not match the length of the gzipped output. I notice a delay or the browser reports an encoding error.

I saw a trick (also on stackoverflow) to set the content-length after gzip compression to be sure it reports the correct size. But when I do this, the content is no longer compressed.

The question is, is this behaviour correct? Is gzipped content always send chuncked? Is content-length only needed for files that are not gzipped?

Here some snippets of code:

1 Results in gzipped and chunked file transfer:

ob_start('ob_gzhandler');
echo $sResult;

2 Results in normal file transfer with content-length specified (but expect gzipped and content-length):

ob_start('ob_gzhandler');
echo $sResult;
header('Content-Length: '.ob_get_length()); 

Here some pictures of http header results: 1 Gzipped and Chuncked

2 Expect Gzipped but normal transfer when set content-length

Codebeat
  • 6,501
  • 6
  • 57
  • 99
  • possible duplicate of [How to determine the Content-Length of a gzipped file?](http://stackoverflow.com/questions/815961/how-to-determine-the-content-length-of-a-gzipped-file) – Ja͢ck Dec 02 '13 at 23:07
  • It is not a duplicate because he/she is talking about a gzipped FILE. Besides this can be also a file but it is about serving content, not specific a file. Want to know why it is not working the way I described here. Didn't know that it relies on similar method. Still do not know/understand WHY it works. The CSS file I used in this example is a non-existing file because it composed out of several CSS files. – Codebeat Dec 02 '13 at 23:21
  • It works because it uses two levels of output buffering; at the first `ob_end_flush()` it flushes the inner output buffering belonging to `ob_gzhandler`; then the content length is known ... afterwards, the second call flushes the outer buffer. – Ja͢ck Dec 02 '13 at 23:24
  • Personally I wouldn't bother too much about chunked data transfer; it works fine because chunks aren't typically read one by one, rather the whole responses is read using 8kB buffers and dechunking is done in memory. – Ja͢ck Dec 02 '13 at 23:30
  • Well, I do. There is a reason that this exists: See the answer of: http://stackoverflow.com/questions/2419281/content-length-header-versus-chunked-encoding – Codebeat Dec 03 '13 at 00:01
  • That answer doesn't exactly discuss the merits of such an approach in terms of performance gain. In the case of CSS it's fine to use output buffering, but why not simply generate the CSS beforehand and have the web server handle the delivery (using gzip)? :) – Ja͢ck Dec 03 '13 at 00:16
  • I don't want to start a discussion why it is good for or not. I think it is ok. About the CSS: Because it is dynamic and minified on the fly. The original files are on the server. – Codebeat Dec 03 '13 at 00:31
  • Even dynamic CSS can be controlled by hashing it against something that changes in tandem, i.e. one CSS per user. I'm just guessing here, so without more information from you, I will just leave it at this. – Ja͢ck Dec 03 '13 at 00:33
  • What do you mean with hashing? Like I said before, it will be minified/optimized, things you are not able to do with the basics. – Codebeat Dec 03 '13 at 00:39
  • You can store generated content once and then have the web server handle it for you; perhaps [this answer](http://stackoverflow.com/questions/10596116/caching-http-responses-when-they-are-dynamically-created-by-php/10596231#10596231) can help you understand how that would work, it also explains how to have the browser cache dynamic resources. – Ja͢ck Dec 03 '13 at 02:17

1 Answers1

2

Found the solution/trick here: How to determine the Content-Length of a gzipped file?

Made into this:

// clear output buffers
while( ob_get_level() )
 { ob_end_clean(); }

< send http headers here >

ob_start();
ob_start('ob_gzhandler');
echo $sResult;
if( !headers_sent() )
{
   ob_end_flush(); // Flush the output from ob_gzhandler
   header('Content-Length: '.ob_get_length());
   ob_end_flush(); // Flush the outer ob_start()
}

To me is not clear why this works but seems to work perfectly. The content is now gzipped and has a content-length (not chunked).

To prove it, here is a screenshot:

gzipped and content-length

Cheers! ;-)

Community
  • 1
  • 1
Codebeat
  • 6,501
  • 6
  • 57
  • 99