发布表单时使用输出缓冲区的PHP头重定向不起作用 - 但在其他情况下呢?

I have an unusual problem, only happening on one server. Following code

....
elseif ($_GET['action']=='login') {

 if (empty($_POST['login_name'])) { $_POST['login_name']=''; }
 if (empty($_POST['login_pass'])) { $_POST['login_pass']=''; }
 if (!empty($_POST['send'])) {
  if (($_POST['login_name']==_ADMIN_NAME) and    ($_POST['login_pass']==_ADMIN_PASS)) {
   //Successfully logged in
   $_SESSION['logged']=1;

// DOES NOT WORK
   header('Location: '.$filename);
   die('Command '.$filename);
  }
 }
// Show Form;
include('plogin.inc.php');
} 
elseif ($_GET['action']=='logout') {
 $_SESSION['logged']=-1;
// DOES WORK!
 header('Location: '.$filename);
}

So the problem is this if i click the link logout, all goes well and i get redirected to $filename. If i submit the login form it checks if the post is correct, set's the session var, but then dies instead of redirecting.

I got output buffers on, all error reporting but (no errors), it doesn't redirect when I post with the form even though it definitely passes (because the session var is set and I get to the die part)

What could be the cause for this behavior? Thanks

might be a simple thing. The header() function does set a header, but does not terminate a script so that the header is sent immidiately after calling header().

You need to make php send the script result to the client. As you use output buffering, this result is held back until you trigger your output. Try this instead:

header('Location: '.$filename);
ob_end_flush();
exit();

Regards, Mario

Did you test that a) the code is reached and b) the error reporting really is in effect?

//Successfully logged in
$_SESSION['logged']=1;
// code reached, error_reporting test echo 'debug: would send location header', $filename, $unsetVariableTriggeringWarning; flush();
if (headers_sent()) { die('cannot send location header (anymore)'); } else { header('Location: '.$filename); die(); }

The line with

die('Command '.$filename);

would probably be the culprit. If the die (or exit) functions (or actually language constructs) take a string as a parameter, it is printed out on the other side before halting. PHP doesn't like you trying to output anything if you are sending headers.

If you are using a reasonably new PHP (>= 4.3.0 iirc), you can use integers 0..255 to mark exit conditions (if you want to), which will not be printed.

I, also, found redirect don't work sometimes after POST request. It is a browser not server-side problem, I think.

I use something like this:

if( sizeof( $_POST ) == 0 ) header( "Location: " . $url );
else echo '<html><head><meta http-equiv="refresh" content="1;url=' . $url . '"/></head><body>Redirecting to ' . $url . '</body></html>'

In short, if it is a POST request - then I use html refresh redirect, else - normal header redirect.

from my experience you can't send any content when you're doing redirect. So I'd guess your problem is the die() parameter.

I can't find this in documentation right now but try dying() it without a parameter or just use exit; I bet it will work.

When you send a redirect, PHP puts the values in the HTTP Response header. The body follows the header. Therefore, if you echo/print any kind of value before using the Header function, it fails, since the Response Headers are already out. Try the same script before printing any text and it will work.

Normal HTTP Response

HTTP/1.1 200 OK Date: Wed, 12 Jan 2011 18:40:22 GMT Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.14 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html

[Body of the message]

HTTP/1.1 302 Found Date: Wed, 12 Jan 2011 18:40:22 GMT Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.14 Location: profile.php Content-Type: text/html

   header('Location: '.$filename);
flush(); //Try to force server to send header before script die
   die('Command '.$filename);

I had the same problem: script: header('Location: ...'); die();

Script before sending headers received some data via POST, and if data new make changes to DB. It is curious, when POST data small and little changes to DB redirect WORK, when POST data bigger and a lot of changes to DB redirect DON'T WORK. Using flush() after header() solve my problem.

PHP Version 5.2.17 Apache/2.2.3 (CentOS)

On my opinion, it looks like server push headers to buffer and dies before sending the buffer content to user, and that is why flush() helped.

If flush does not working, see comments about output buffering settings and zlib.compression: http://ru2.php.net/manual/en/function.flush.php