php flush() triggers headers_sent() even without content - php

The headers_sent() function from php does not work on my target server. It does not evaluate to True even when things are echoed. This can be fixed by changing the output_buffering value in php.ini but unfortunately I do not have access. A workaround as mentioned in this stackoverflow question is to use the flush() function.
However when using flush() the headers_sent() function always evaluates to True. This is because flush() will send headers + content(if any) as lafor pointed out .
<?php
flush();
if(headers_sent())
echo 'headers were sent';
//will output 'headers were sent'
I wanted to use the headers_sent() function to check if anything has been written/outputted yet.
The headers itself are not of importance to me.
Can anyone help me with a way of checking if there has been some output earlier?
(extra context: I want to check if any functions did echo() some warning messages earlier in execution time, of course these functions could/should also do some more sophisticated error reporting, but that is a different story)

What is your purpose for doing this? A little more explanation might help us put it into context.
If output buffering is needed, you can skip the php.ini function and just use ob_start(); and a function like ob_get_clean(); to return the contents without outputting.

http://us1.php.net/flush describes a number of cases where buffering may cause output not to be sent when expected. See also http://www.tuxradar.com/practicalphp/13/9/0#null. The flush() function is supposed to send "everything" to the browser, which would include HTTP headers. However, it's not clear from what I've read whether the headers are sent even if there is no other output. From your reported experience, I would surmise that at least for your server (and maybe browser), headers are flushed regardless of whether there is other output.

When output buffering is on, headers don't get sent until the output is flushed, so headers_sent() returning false before that is correct.
flush() flushes all buffered content (if any) and headers, so headers_sent() returning true after that is also correct. I don't see how the function is "not working" or "useless".
If your purpose is to check whether any headers were set to be sent (using header() function which, with no output buffering, would also send the header right away), you might wanna look into headers_list() or register a custom callback with header_register_callback().

Related

Is output buffering not working?

(I set output_buffering and implicit_flush to Off.)
I know PHP has its own output buffering. (Not output buffering that starts with ob_start())
<?php
echo 'hello';
header('HTTP/1.1 200 OK');
echo 'hello';
?>
So I expected that the above source code would work fine because of the output buffering unless I call flsuh().
However, a warning occurs. (Warning: Cannot modify header information - headers already sent by)
I do not know why. I want you to let me know if I have misunderstood.
You cannot output anything before setting headers.
Functions that send or modify HTTP headers must be invoked before any output is made, regardless of php.ini settings.
This is why sometimes the unintentional space before or after <?php, ?> will cause this error to be thrown.
In any request, headers are sent first and then output. You are effectively outputting, then sending/modifying headers, and then outputting again.
At the first invocation of any output, PHP will flush header buffers meaning they are already set, so trying to change them after is impossible; and that is why the error occurs.

absolutely no response php exit technique?

The docs I read don't seem clear on this issue.
When calling exit() with no arguments, does the server still send something back to the client?
If so, is there an alternative or way to keep anything from being sent to the client on exit?
exit is basically the same as reaching the end of the file. Anything that has already been sent will be received by the browsers, and any output buffers will be processed and also sent.
You can force an empty response by include ob_start() as your first line of code, and using this function:
function exitEmpty() {
while(ob_get_level()) ob_end_clean();
exit;
}
However the headers will still be sent. This just empties the response body.
exit() will still send headers, if they haven't already been sent, but otherwise it will send nothing else.

Check if part of output has already been sent in PHP

In PHP, is there a (ready-made) way to check if a part of the output has already been sent to the client?
I know that with headers_sent() you can check if the headers have already been sent, but I also want to check if any output has been sent (so that e.g. the HTTP header Content-Length > 0).
(Notice that ob_start() starts output buffering from the moment when it is called. But third-party systems implementing my code might already have sent output, thus output buffering is unusable as far as I know.)
You could wrap your own ob_start around everything else and flush it when you decide to. It works even if other ob_start's and flushes are inside. Take this example :
ob_start();
[...]
//some 3rd party app which is included on the way
[...]
ob_start();
[...]
ob_flush(); //at this moment the buffer isn't flushed to the client
//but to the parent ob_start, which is yours, so no output
//is sent yet
[...]
//ok, we're done, we can output now
ob_flush();
PHP in most cases sends headers to Apache only with some content or on the end of script execution. So, if headers are sent, some content is sent too. Furthemore, as I understand, Content-Length is calculated anyway after the script execution.

Able to Echo before header()

Came across something strange while migrating to my new server.
I have a script that will redirect users to another web page based on certain conditions. What I was doing, however, is echoing out 'Redirecting...', then using the header() function to actually redirect. Here is how the code looked:
if( $condition ) {
echo 'Redirecting...';
header( 'Location: ' . $url );
}
Now I only noticed that this is incorrect after switching over to our new server, tested it out, and saw that it would NOT redirect just output Redirecting... and once I searched about it, learned you cannot have any kind of output (unless using ob_start etc) before using the header() function.
Question is, why is this code, that should NOT work in ANY PHP installation, work on my old server? It will redirect with the echo before header() no problem.
Thanks!
You may have had output buffering on on the old server: output buffering will not output anything until the script finishes running. That allows it to get the header out before the actual output (as it knows the headers should be sent first).
If that makes sense.
Maybe your old installation had output_buffering defined to true in the php.ini. This delayed the output allowing you to set the headers even after echoing.
You must have had buffering turned on, even though you did not actively do so yourself. output_buffering = On in php.ini?
It worked on your old server as you had output buffering on by default, set by the php.ini.
The old server probably had output buffering enabled by default. This meant that it wouldn't echo right away, but rather wait until the whole script has finished, and then echo. This also means that the header would be sent before the echo (since it was buffered), and therefore would not result in a warning.
On the new server, you most likely do not have output buffering enabled by default, and this would mean that it would echo straight away, without buffering it, and therefore it would be sent before the headers and result in a warning.
I would encourage you to use headers_sent() to check if the headers has been sent before using headers() after echo, like this:
<?php
echo "Foobar\n";
if(!headers_sent())
header('Location: /helloworld.php');
?>
Related links:
Output Control
Runtime configuration for Output Control - how to enable output control in your php.ini file
ob_start() function for manually enabling output buffering anywhere in your script.
header_sent()

When do header(..) statements take effect in PHP?

after all stuff behind is run
immediately
Which is the case? Can anyone verify this?
Refer the following link.
http://php.net/manual/en/function.header.php
To make sure that a page is directly redirected, add a exit; after the header.
depends on the output_buffering setting
headers_sent() function can verify
If output buffering is disabled then it will be sent immediately. It must be sent before any other content (however you can perform processing logic before sending the header)
Depends on output buffering, but the PHP interpreter still only uses them after having interpreted all the code before, just like a normal function. Still, there must not be any HTML before a header(), or things will screw up.

Categories