Revisiting output control code

php.internals

Michael Wallner

20 years ago
Hi, I'd like to suggest that we revisit the output control (output buffering) code base. The current implementation uses way too less commands to do too many different operations, which almost always causes problems with output handlers that need to maintain a state or context. Short example: ob_clean() causes havoc with ext/zlib ob handlers and any handlers found in pecl/http. ob_clean() passes currently buffered input through the handler and discards it, which means in the case of the gz handler that the gzip/zlib header bytes (and more) are missing from the sent data. Things I think that should come with the new code: Support for an opaque handler context, which will be passed to the handler. More distinct commands like FLUSH, RESTART and/or CLEAN. Thoughts/comments/flames? Regards,
-- Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz

Jared Williams

20 years ago
> I'd like to suggest that we revisit the output control > (output buffering) code base. > The current implementation uses way too less commands to do > too many different operations, which almost always causes > problems with output handlers that need to maintain a state > or context. > > Short example: > ob_clean() causes havoc with ext/zlib ob handlers and any > handlers found in pecl/http. > ob_clean() passes currently buffered input through the > handler and discards it, which means in the case of the gz > handler that the gzip/zlib header bytes (and more) are > missing from the sent data. > > Things I think that should come with the new code: > Support for an opaque handler context, which will be > passed to the handler. > More distinct commands like FLUSH, RESTART and/or CLEAN. > Thoughts/comments/flames?
Sounds like should be built upon/replaced with streams. Jared

Jasper Bryant-Greene

20 years ago
Michael Wallner wrote:
> I'd like to suggest that we revisit the output control (output > buffering) code base.
On a semi-related note, I'd like to see the docs mention that print_r and var_export (with the second parameter set to TRUE), and debug_print_backtrace, internally use the output buffering code to capture their output, meaning that using them inside an output buffering handler will always cause a fatal error. Alternatively, I'd like to see these functions *not* use the ob functions to do their work. I realise the former is probably easier though. Jasper

Friedhelm Betz

20 years ago
Jasper Bryant-Greene wrote:
> Michael Wallner wrote: >> I'd like to suggest that we revisit the output control (output >> buffering) code base. > > On a semi-related note, I'd like to see the docs mention that print_r > and var_export (with the second parameter set to TRUE), and > debug_print_backtrace, internally use the output buffering code to > capture their output, meaning that using them inside an output buffering > handler will always cause a fatal error.
Open a bug report at bugs.php.net "Documentation Problem"? Friedhelm

Zeev Suraski

20 years ago
At 13:51 27/02/2006, Michael Wallner wrote:
>Hi, > >I'd like to suggest that we revisit the output control (output >buffering) code base. >The current implementation uses way too less commands to do too many different >operations, which almost always causes problems with output handlers that need >to maintain a state or context. > >Short example: >ob_clean() causes havoc with ext/zlib ob handlers and any handlers >found in pecl/http. >ob_clean() passes currently buffered input through the handler and >discards it, which >means in the case of the gz handler that the gzip/zlib header bytes >(and more) are >missing from the sent data.
Why would you call ob_end_clean() in those cases? It seems to me that what you want to do is actually create another layer of output buffering on top of those custom output handlers, if you want to control the contents itself. If you think of custom output buffers as a filter, then it makes perfect sense that calling ob_end_clean() would cause problems. If you do it in another layer of output buffering, then the format of zlib/gz will remain intact without any problems. I'm also not sure about what you're saying with the gzip/zlib headers missing - do you mean the footers? Zeev

Hannes Magnusson

20 years ago
On 2/28/06, Zeev Suraski <zeev@zend.com> wrote:
> I'm also not sure about what you're saying with the gzip/zlib headers > missing - do you mean the footers? >
Refering to http://bugs.php.net/bug.php?id=36514 I belive - Hannes

Zeev Suraski

20 years ago
I misread the post, I thought we were talking about ob_end_clean(). Yes, ob_clean() may cause this problem to happen, but again, the right approach would be having an 'applicative' output buffer on top of the gzip output buffer. We can look into letting output handlers denote that ob_clean() is not allowed on them. Zeev At 18:58 28/02/2006, Hannes Magnusson wrote:

Michael Wallner

20 years ago
Zeev Suraski wrote:
> I misread the post, I thought we were talking about ob_end_clean(). > Yes, ob_clean() may cause this problem to happen, but again, the right > approach would be having an 'applicative' output buffer on top of the > gzip output buffer. We can look into letting output handlers denote > that ob_clean() is not allowed on them.
This would be in deed an option. If you still consider a rather fundamental enhancement of the output control code, please take a look at my initial try. It already /seems to work/ but probably misses a few things. I must admit though, that I did not fully understand the current implementation. Considered issues: Support of contexts for internal output handlers that had to maintain it in a global variable, which caused those handlers being only usable once; while often natural, like for the gz handler, still a limitation. Conflict handlers, so that one doesn't need to incorporate that code directly in output.c, but register them from within an extension etc. Distinct ops, like FLUSH and CLEAN to signal the handler what's going on; there should also be a possibility to change the abilities of a handler in runtime, which is not implemented yet, eg. the gz handler could remove the CLEANABLE and REMOVABLE flags when the first output did pass through it. Unfortunately I don't know which version of re2c Ilia used to generate the url scanner, so a big part of the diff is pretty useless; note that the patch is against current 5_1 CVS. http://dev.iworks.at/PATCHES/ob.patch.txt.gz http://dev.iworks.at/PATCHES/output.c.txt http://dev.iworks.at/PATCHES/php_output.h.txt Thanks a lot,
-- Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz

Marcus Börger

20 years ago
Hello Michael, i never liked the output buffering code much becuase i find it too complex and too much stuff there is interacting in a way one cannot understand easily. If there is a simple solution at hand that solves some problem and that thing disables selective features by just disallowing invocation of certain control function i'd never be against. If it fixed a problem at hand i'd be all for it of course. Anyway that would only increase the complexity. So yes a redisign wouldn't hurt. And if that means we could get rid of strange side effects of stuff that is imo abusing the output buffering by using a temporary output buffer i'd appreciate it. However as said on irc i am not sure it's worth the effort and cannot make out how much new problems we'd head to. That you even provide a nice looking patch here shows that you are confident with the idea and agree to do the work. best regards marcus Thursday, March 2, 2006, 7:24:09 PM, you wrote:
> Zeev Suraski wrote: >> I misread the post, I thought we were talking about ob_end_clean(). >> Yes, ob_clean() may cause this problem to happen, but again, the right >> approach would be having an 'applicative' output buffer on top of the >> gzip output buffer. We can look into letting output handlers denote >> that ob_clean() is not allowed on them.
> This would be in deed an option.
> If you still consider a rather fundamental enhancement of the output control > code, please take a look at my initial try. It already /seems to work/ but > probably misses a few things. I must admit though, that I did not fully > understand the current implementation.
> Considered issues: > Support of contexts for internal output handlers that had to maintain > it in a global variable, which caused those handlers being only usable > once; while often natural, like for the gz handler, still a limitation. > Conflict handlers, so that one doesn't need to incorporate that > code directly in output.c, but register them from within an extension etc. > Distinct ops, like FLUSH and CLEAN to signal the handler what's > going on; there should also be a possibility to change the abilities of > a handler in runtime, which is not implemented yet, eg. the gz handler > could remove the CLEANABLE and REMOVABLE flags when the first output > did pass through it.
> Unfortunately I don't know which version of re2c Ilia used to generate > the url scanner, so a big part of the diff is pretty useless; note that > the patch is against current 5_1 CVS.
> http://dev.iworks.at/PATCHES/ob.patch.txt.gz > http://dev.iworks.at/PATCHES/output.c.txt > http://dev.iworks.at/PATCHES/php_output.h.txt
> Thanks a lot, > -- > Michael - <mike(@)php.net> > http://dev.iworks.at/ext-http/http-functions.html.gz
Best regards, Marcus

Michael Wallner

20 years ago
Marcus Boerger wrote:
> i never liked the output buffering code much becuase i find it too complex > and too much stuff there is interacting in a way one cannot understand > easily.
[...]
> So yes a redisign wouldn't hurt. And if that means we could get rid of > strange side effects of stuff that is imo abusing the output buffering by > using a temporary output buffer i'd appreciate it.
[...]
> That you even provide a nice looking patch here shows that you > are confident with the idea and agree to do the work.
Thanks for your response, Marcus. I hope others will find the time for a quick review and statement, too?
>>http://dev.iworks.at/PATCHES/ob.patch.txt.gz >>http://dev.iworks.at/PATCHES/output.c.txt >>http://dev.iworks.at/PATCHES/php_output.h.txt
Thank you,
-- Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz

Michael Wallner

20 years ago
Marcus Boerger wrote:
> And if that means we could get rid of > strange side effects of stuff that is imo abusing the output buffering by > using a temporary output buffer i'd appreciate it.
I guess you mean var_dump() and friends? I didn't touch anything beneath Zend/ though. Regards,
-- Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz

Xuefer Tinys

20 years ago
is there any chance that a buffer in output buffer will be supported? supposing u're implementing "send the whole page in html to friends" function. using smarty as email template. if (isset($_GET['send_html_to'])) { ob_start('send_as_html'); } function send_as_html($content) { $tpl = new Smarty("html_email"); prepair_html($content); $tpl->assign($html, $content); $content = $tpl->fetch(); <- this use ob_start to catch all output from the compiled template } q: why not do "$content = ob_get_clean() and $tpl->fetch() after it" in this case? a: because i can't put ob_get_clean() code in all the php pages. q: but u can do ob_start('send_as_html') in all pages? because i can put it in a common lib that every page include.

Michael Wallner

20 years ago
Xuefer wrote:
> is there any chance that a buffer in output buffer will be supported?
Nope, as this can cause all sorts of evil things. Regards,
-- Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz