Able to Echo before header() - php

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()

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.

php flush() triggers headers_sent() even without content

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().

Why does this header location redirect work after content has already been echoed?

<?
echo "lalala";
header("Location: http://www.google.com/");
If i put this in a plain php file and deliver over a standard apache2 server with mod-php (PHP Version 5.3.2-1ubuntu4.10) the redirect to google works.
<?
echo "lalala";
flush();
header("Location: http://www.google.com/");
this code does obviously not produce a working redirect.
My question is how the first code is beeing processed and why it works. Because I remember times when things like this were not possible. Is mod-php or apache intelligent enough to buffer the whole request and arrange headers before content?
And:
Can I rely on this if I make sure I don't flush the output manually? Because it would make my application much easier...
Output buffering is probably enabled by default. You should enable it manually if you want to rely on this functionality.
http://php.net/manual/en/function.ob-start.php
The header function ADDS an http common header to the HTTP response. So, the redirect is setted and the browser gets the 302 message before showing you the output.
flush orders php to send the http response already prepared at the point it is called. That's why the second code won't set the header (it must be setted before sending ANY output).
And, the PHP should not output a single thing until:
The script is processed (even if an error stops the parsing)
you set it to send the output somewhere in the script with flush()
Finally, check this on output control http://www.php.net/manual/en/intro.outcontrol.php

Can send header even though I have output

Should'nt the following give an error message? It sends me to domain.com/asdad/ instead of giving me an error message.
<?php
echo 'asdadasdasd';
if ($_SERVER['REQUEST_URI'] == '/newtest.php') {
header("Location: /asdad/");
exit;
}
?>
I view this directly, no other files or code before or after this. Should'nt header give me an error and NOT send me to the new page as I have output before the header?
Check your phpinfo(), you probably have output_buffering switched on.
PHP output, like most IO, is often put into a temporary buffer until a critical amount is reached (or a user calls flush), at which point the contents are flushed to the browser. If you manage to send a header before the output buffer is flushed, you can get away with it.
However, this is not something you rely on, as the buffer size (or, indeed, buffering at all) can vary between installations.

PHP output_buffering on/off issue

I have created a PHP application with output_buffering = On.
Now, if i do output_buffering = Off then i have get following error
"Cannot modify header information - headers already sent by ".
How can i remove this error?
What can be the drawback if i upload application on live site with output_buffering = Off?
From PHP Tag Wiki:
Q. "Headers have already been sent..."
A. You're outputting content and triggering PHP's default content-type:text/html header before making your own call to header(). There are a few ways this can happen, check for a stray echo or print, whitespace before and after the tags or maybe a Unicode BOM. Consider using output buffering. With many scripts, there is no need to include the ending ?> and the problem is easily fixed by removing the ending ?> tag from your files.
There is also a myriad of duplicates for this.
Send out your headers before any output goes to the browser.
header('Foo: bar');
echo "foo";
If you turn output buffering off, you are not allowed to send any additional headers (this includes cookies e.g.) after you've send any piece of data to the client (namely using echo or some other output function).
You can use headers_sent() to check where you started to output data to the client.
Ensure all header('') tags go right at the top of the script with no white space!
EG:
<?php
header('type of header');
?>
If you really have to do it further down the page you can call ob_start() at the top of the script. Call ob_end_flush() at the end of the script too.

Categories