2

As suggested in a reply to a previous question (PHP External Oauth : how to displaying a waiting message while waiting for callback (not using AJAX) ), I am using transfer encoding: chunked to display a waiting message while some tasks are performed. My first attempts failed, and I found a solution in this question “Transfer-Encoding: chunked” header in PHP. There is a "padding" of 1024 blank space. Without this padding it doesn't work. I have googled around but I can't find what this padding is for. Here is the sample code (from the related question).

<?php
        header('Content-Encoding', 'chunked');
        header('Transfer-Encoding', 'chunked');
        header('Content-Type', 'text/html');
        header('Connection', 'keep-alive');

        ob_flush();
        flush();

        $p = "";  //padding
        for ($i=0; $i < 1024; $i++) { 
            $p .= " ";
        };
        echo $p;

        ob_flush();
        flush();

        for ($i = 0; $i < 10000; $i++) {
            echo "string";
            ob_flush();
            flush();
            sleep(2);
        }

?>

Does anybody have an explanation why it works with and doesn't work without the "padding" ?

Community
  • 1
  • 1
Jean-Marc Dormoy
  • 129
  • 1
  • 2
  • 9
  • What exactly happens without the padding? – deceze Nov 26 '12 at 13:46
  • sorry, I was out for a while. Without the padding, the page stay blank until it the script is complete, and then all the content is served (I have not try with 10.000 iterations, but only 10 :) ) – Jean-Marc Dormoy Nov 26 '12 at 14:47

2 Answers2

2

The padding is for filling the server buffer, as I understand.

Without it the server will wait until PHP will fill it and after this will flush it - even if in PHP code you do flush().

Related:

Community
  • 1
  • 1
Dmitriy Sushko
  • 242
  • 1
  • 6
1

I have no idea what this padding is supposed to do, and actually it shouldn't work (someone may enlighten me if I'm wrong on this). The idea with chunked encoding is that you send your data in chunks. Each chunk consists of a line containing the length of a chunk, followed by a newline and then the data of the chunk. A response can contain as many chunks as you want to have. So basically the response of 3 chunks containing "Hello" would look like this:

5 <--- this is the length of the chunk, that is "Hello" == 5 chars
Hello  <--- This is a the actual data
<-- an empty line is between the chunks
5
Hello

5
Hello

<-- send two empty lines to end the transmission

So I'd rewrite this to something like:

<?php
        header('Content-Encoding', 'chunked');
        header('Transfer-Encoding', 'chunked');
        header('Content-Type', 'text/html');
        header('Connection', 'keep-alive');

        ob_flush();
        flush();

        for ($i = 0; $i < 10000; $i++) {
            $string = "string";
            echo strlen($string)."\r\n"; // this is the length
            echo $string."\r\n"; // this is the date
            echo "\r\n"; // newline between chunks
            ob_flush(); // rinse and repeat
            flush();
            sleep(2);
        } 
        echo  "\r\n"; // send final empty line
        ob_flush();
        flush();

?>

The code above will not work at all circumstances (e.g. with strings containing newlines or non-ascii encodings), so you will have to adapt it to your use case.

Jan Thomä
  • 13,296
  • 6
  • 55
  • 83
  • this script gives me the following output : "6 string 6 string 6 string 6 string 6 string 6 string 6 string 6 string 6 string 6 string " (with 10 iterations only), but transfer is not chunked. What am I missing ? Is there anything special to set up on Apache / nginx (used as reverse proxy with the directive _proxy_buffering off;_ ) – Jean-Marc Dormoy Nov 26 '12 at 14:54