-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling ob_clean() after ob_start('gz_handler') does not set Content-Encoding #7953
Comments
ob_gzhandler isn't some special string that output buffering recognizes - it's an actual function - so it's not output buffering itself that is at fault. It's like you wrote your own callback that added a response header the first time it was called - that header will still be there after output buffering ends. I think it would be possible for ob_gzhandler to detect the PHP_OUTPUT_HANDLER_CLEAN flag and to unset the header and reset back to the initial state. (Equally possible in userland.) Or to remove the header automatically if there's been no output, but that would mean no more effectively-empty responses with just the compression container and instead actually-empty responses with no content at all, but any good client should be totally okay with that. |
Yes, I'm a PHP developer since 15 years back. I know it's a callback function. What I don't get is why ob_clean() unsets the header when stackoverflow and PHP documentations is full of comments that ob_clean() does not affect headers. Do you not see a problem with this? |
Hmm, looks like I remembered ob_gzhandler backwards: it is a special string after all. It's an alias that goes through slightly different handling in that it will initialize a context, which ob_gzhandler the function does too but in a slightly different way. Thus why Looking into it more, it's not that the headers are removed but that they aren't added at all. I'm also seeing odd behavior with a flush + clean in that the special "ob_gzhandler" issues a "Failed to delete buffer" notice while the wrapped ob_gzhandler() call does not. So it seems like there's some iffy behavior with how it handles the CLEAN phases in general. |
If an output handler has not yet been started, calling `ob_clean()` causes it to start. If that happens, we must not forget to set the `Content-Encoding` and `Vary` headers.
Well done 👍 |
The special ob_start(fn($buffer, $phase) => ob_gzhandler($buffer, $phase));
echo "Hello";
ob_flush();
ob_end_clean();
echo "world"; Note to self: check |
Indeed, it has basically the same issue, namely that the The "wrapper" issue isn't a thing, though, since |
I just want to point out ob_clean() doesn't need to be right after. Any use of ob_clean() long after ob_start('gzhandler') should cause the same problem.
Result:
|
Ah, right! More correctly, it is about calling |
Correct, that is how I stumbled upon this. |
* PHP-8.0: Fix GH-7953: ob_clean() only does not set Content-Encoding
* PHP-8.1: Fix GH-7953: ob_clean() only does not set Content-Encoding
The fix for phpGH-7953 introduced a regression by being to deliberate adding the respective headers. These must only be added, if the handler starts, but is not finalizing.
Description
The following code:
Resulted in this output:
But I expected this output instead:
There is no mention anywhere in the documentation that clearing the output buffer resets the Content-Encoding HTTP Header. If this is by design it should be stated, but it feels like an error.
PHP Version
PHP 8.0.10
Operating System
Windows 11 x64
The text was updated successfully, but these errors were encountered: