Output handler is killed by flush()
chrisgraham opened this issue · 5 comments
If you do a flush(), PHP will send headers, and the extension will fail to be able to set the Content-Encoding
header. You'll get a binary mess in the browser.
At minimum I'd:
- Document not to do
flush();
- If you can't do headers, bomb out of the output handler completely without doing Brotli
But actually this problem doesn't exist for the zlib output handler. I have no idea how they do it, as I can see PHP plumbs flush();
directly into the SAPI. But I have just double checked that I can use flush with zlib and still get a zlib-encoded web response. PHP also documents that flush
is a null-op on zlib output.
Can you provide a sample code?
<?php
ini_set('zlib.output_compression', 'Off');
ini_set('brotli.output_compression', 'On');
echo 'test';
flush();
Thanks.
I will check and correct it.
To make it equal to zlib.output_compression
in cae70ba Fixed.
For the case of mode_php (httpd/prefork) and fpm (with nginx), you can use It seemed to behave differently.
gzip behavior
Accessed by Accept-Encoding:gzip
.
ini_set('zlib.output_compression', 'On');
echo 'test';
// For the process so far
// Content-Encoding is gzip for both mode_php and fpm
flush();
// If you do a flush(), you can use the
// mode_php has no Content-Encoding (uncompressed output)
// fpm has a Content-Encoding of gzip
brotli behavior
Fixed in cae70ba.
Accessed by Accept-Encoding:br
.
ini_set('brotli.output_compression', 'On');
echo 'test';
// For the process so far
// Content-Encoding is br for both mode_php and fpm
flush();
// If you do a flush(), you can use the
// mode_php has no Content-Encoding (uncompressed output)
// fpm has a Content-Encoding of br
Thanks. That looks like a good fix.
Looking back at this with fresh eyes, I don't think I explained the issue very well.
So for anyone else reading this, the issue is that a compression output handler has to compress everything in one go (compression is not iterative at the byte level). Doing a 'flush' will break that basic assumption.
Except for CGI I guess, because CGI is not iterative, everything will be sent to the SAPI in a single go regardless due to the nature of the CGI/web-server interface.
Edit: Fix confirmed working.