简体   繁体   中英

PHP Header Location gets sent even inside an output buffer?

I am having trouble suppressing a PHP Location Header from inside an output buffer. It is my understanding that output buffers should suppress headers until they are flushed. I also thought that no headers should be sent with ob_end_clean().

However if you see the code below, if I uncomment the header line (second line) I always get redirected to google and never see 'finished'.

ob_start();
//header("Location: http://www.google.com");
$output = ob_get_contents();
ob_end_clean();

$headers_sent = headers_sent();
$headers_list = headers_list();

var_dump($headers_sent);
var_dump($headers_list);

die('finished');

I need to suppress any header redirects, ideally catching them in the output buffer so I know those conditions will produce a redirect. I know I can do this with curl (setting follow redirects to false), but as all the files I want to buffer are on my own server curl is proving very slow and tying up loads of db connections.

Does anyone have any suggestions or know of any way of catching/suppressing Location Headers?

Thanks, Tom

See if you can use header_remove function along with headers_list . This seemed to work on IIS/FastCGI and Apache:

<?php
ob_start();
header('Location: http://www.google.com');
$output = ob_get_contents();
ob_end_clean();
foreach(headers_list() as $header) {
    if(stripos($header, 'Location:') === 0){
        header_remove('Location');
        header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK'); // Normally you do this
        header('Status: 200 OK');                        // For FastCGI use this instead
        header('X-Removed-Location:' . substr($header, 9));
    }
}
die('finished');

// HTTP/1.1 200 OK
// Server: Microsoft-IIS/5.1
// Date: Wed, 25 May 2011 11:57:36 GMT
// X-Powered-By: ASP.NET, PHP/5.3.5
// X-Removed-Location: http://www.google.com
// Content-Type: text/html
// Content-Length: 8

PS: despite of what the ob_start documentation says, PHP will send headers when it is about to send the first byte of output (or when the script is terminates). Without output buffering, your code must manipulate headers before sending any output. With output buffering, you can interleave header manipulation and output anyway you like until you flush the buffer.

If you read the manual page for ob_start the first paragraph is:

This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers) , instead the output is stored in an internal buffer.

It is my understanding that output buffers should suppress headers until they are flushed

Nope:

While output buffering is active no output is sent from the script (other than headers)

Source: http://us.php.net/manual/en/function.ob-start.php

You can try flushing before sending headers though:

ob_start();
flush();
header("Location: http://www.google.com");
$output = ob_get_contents();
ob_end_clean();

$headers_sent = headers_sent();
$headers_list = headers_list();

var_dump($headers_sent);
var_dump($headers_list);

die('finished');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM