PHP头位置即使在输出缓冲区内也会被发送


PHP Header Location gets sent even inside an output buffer?

我在从输出缓冲区中抑制PHP位置标头时遇到问题。我的理解是,输出缓冲区应该抑制头,直到它们被刷新。我还认为不应该使用ob_end_clean()发送任何标头。

然而,如果你看到下面的代码,如果我取消注释标题行(第二行),我总是被重定向到谷歌,永远看不到"完成"。

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');

我需要抑制任何标头重定向,最好是在输出缓冲区中捕获它们,这样我就知道这些条件会产生重定向。我知道我可以用curl(将follow重定向设置为false)做到这一点,但由于我想要缓冲的所有文件都在我自己的服务器上,curl速度非常慢,占用了大量的数据库连接。

是否有人对捕捉/抑制位置标头有任何建议或了解?

谢谢,Tom

查看是否可以将header_remove函数与headers_list一起使用。这似乎适用于IIS/FastCGI和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:不管ob_start文档怎么说,PHP都会在即将发送输出的第一个字节时(或者在脚本终止时)发送头。在没有输出缓冲的情况下,代码在发送任何输出之前必须操作标头。使用输出缓冲,您可以随心所欲地交错头操作和输出,直到刷新缓冲区为止。

如果您阅读ob_start的手册页面,第一段是:

此功能将转动输出缓冲打开。而输出缓冲处于活动状态,没有从发送输出脚本(而不是标头)输出存储在内部缓冲器

我的理解是缓冲区应抑制标头,直到它们被冲洗

否:

当输出缓冲处于活动状态时从脚本发送输出(其他比标题)

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

不过,您可以在发送标头之前尝试刷新:

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');