简体   繁体   English

PHP Header 即使在 output 缓冲区内也能发送位置?

[英]PHP Header Location gets sent even inside an output buffer?

I am having trouble suppressing a PHP Location Header from inside an output buffer.我无法从 output 缓冲区内抑制 PHP 位置 Header。 It is my understanding that output buffers should suppress headers until they are flushed.据我了解,output 缓冲区应该抑制标头,直到它们被刷新。 I also thought that no headers should be sent with ob_end_clean().我还认为不应使用 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'.但是,如果您看到下面的代码,如果我取消注释 header 行(第二行),我总是会被重定向到谷歌并且永远不会看到“完成”。

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.我需要抑制任何 header 重定向,最好在 output 缓冲区中捕获它们,所以我知道这些条件会产生重定向。 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.我知道我可以用 curl 来做到这一点(将跟随重定向设置为 false),但由于我想要缓冲的所有文件都在我自己的服务器上 curl 被证明非常慢并且占用了大量的数据库连接。

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 .看看你是否可以使用header_remove function 和headers_list This seemed to work on IIS/FastCGI and Apache:这似乎适用于 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: 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). PS:尽管 ob_start 文档说了什么,PHP 将在即将发送 output 的第一个字节时(或脚本终止时)发送标头。 Without output buffering, your code must manipulate headers before sending any output.如果没有 output 缓冲,您的代码必须在发送任何 output 之前操作标头。 With output buffering, you can interleave header manipulation and output anyway you like until you flush the buffer.使用 output 缓冲,您可以随意交错 header 操作和 output 直到您刷新缓冲区。

If you read the manual page for ob_start the first paragraph is:如果您阅读ob_start的手册页,第一段是:

This function will turn output buffering on.这个 function 将打开 output 缓冲。 While output buffering is active no output is sent from the script (other than headers) , instead the output is stored in an internal buffer.虽然 output 缓冲处于活动状态,但不会从脚本发送 output (标题除外) ,而是将 output 存储在内部缓冲区中。

It is my understanding that output buffers should suppress headers until they are flushed据我了解,output 缓冲区应该抑制标头,直到它们被刷新

Nope:没有:

While output buffering is active no output is sent from the script (other than headers)虽然 output 缓冲处于活动状态,但不会从脚本发送 output(标题除外)

Source: http://us.php.net/manual/en/function.ob-start.php来源: 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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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