使用header()函数发送标头时显示错误页面

时间:2012-02-12 01:42:59

标签: php header response

我想将一些响应代码(还有什么?)发送到各种条件。

正在发送标题 - 我使用header()跳过了你可以犯的各种错误,例如在之前的调用之前输出。我想出了那些问题,例如,我现在在header()函数调用之前使用ob_start()和ob_clean()。

现在我需要了解为什么我的浏览器/服务器/其他什么都没有显示错误页面。

这是我用于测试的HTML页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
<?php
     error_reporting(E_ALL);
     ini_set('display_errors', '1');
     ob_start();
     ob_clean();
     header("HTTP/1.1 403 - Forbidden", true, 403); // I get the same results with or without "true, 403"
     ob_flush();
?>

这是访问日志中的标题:

127.0.0.1 - - [11/Feb/2012:19:14:35 -0600] "POST /commentprocessing.php HTTP/1.1" 403 266 "http://127.0.0.1/submitcomments.php" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24 ( .NET CLR 3.5.30729; .NET4.0C)"

以下是HTML源代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
</body></html>

如果我从测试页中删除了PHP代码,那正是我所得到的。

有没有办法让#34;错误&#34;页面根据标题中的返回码自动显示?

我在本地运行Abyss服务器进行此类测试。我在Abyss中为403错误定义了一个自定义错误页面,并且我已检查它是否在Abyss设置中拼写正确并且页面实际存在。

没有为包含403响应代码的标题显示该页面 - 这似乎是在访问日志中显示的正确发送。

这可能是我在本地使用Abyss而不是托管公司服务器的问题吗?

有什么建议吗?

编辑*的 * *

tftd,

如果您说的是真的,服务器忽略了我的代码,为什么它会使用我指定的代码记录在访问日志中?

而且,如果您所说的无法更改响应代码,为什么甚至有header()语句或为什么文档没有明确指出诸如使用ob_start()和ob_clean()这样的事情赢得&# 39;解决它。

我在不止一个地方看到,使用ob_start()和ob_clean()来删除生成的输出,以便header()调用可以正常工作。

heera,

谢谢,至少告诉我材料可以放在doctype语句之上并且仍然有效。我不会想到那会起作用。所以,谢谢你。

但是,如果您删除所有PHP并且只有HTML,那么您的示例只会输出准确输出的内容。

我已移除您的onload调用,以消除未定义的&#39;功能&#39;由于您没有包含包含引用函数的脚本,因此会发生错误。

以下内容将产生与您的示例相同的输出:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>

这是你的例子,它产生与上面的直接HTML相同的输出。

<?php ob_start();?>
<!DOCTYPE html>
<html>   <head></head>>
<body>
This is some text
</body>></html>
<?php
$ob=ob_get_clean();
echo $ob;
ob_end_flush(); ?>

你需要经历一次错综复杂的旅程。

另外,为什么要获取缓冲区的内容并转身并将其回显?除了调用ob_get_clean()之外,它还会显示缓冲区的内容,删除它,并且与ob_clean()不同,删除缓冲区,如果要发送刚删除的输出,则必须使用ob_get_clean(并保存,然后使用echo写出来。

在调用一个干净的函数之前,如果你想输出,那么只是证明你最好做些什么来保存缓冲区的内容?

并且ob_end_flush()记录在我遇到它的任何地方,因为自动调用脚本/页面完成。为什么要演示一些自动发生的事情,除非你用我们没有一种类型或另一种类型的刷新调用显示,导致相同的输出,只要在刷新调用后没有创建额外的输出。

好像你的ob_end_clean()调用似乎没有展示任何内容,嗯,或者它是什么?

那么,为什么要生成输出,从缓冲区中获取,擦除和删除缓冲区,然后输出您保存的内容?究竟是什么,这表明了什么?如何以一种错综复杂的奇怪方式做一些简单的事情?

现在,如果你想展示ob_start()在输出上的位置和ob_clean()删除先前输出的区别,为什么不从这样的例子开始:

<?php ob_start();?> 
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

唯一的输出是

It was the best of times, it was the worst of times.

如果您注释掉ob_clean()调用:

<?php ob_start();?>
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
//ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

输出现在是:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
This is some textIt was the best of times, it was the worst of times.

如果您采用我的原始示例并将ob_start()向下移动到第二部分PHP代码中,如下所示:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_start();
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

输出结果为:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
This is some text
</body>
</html>
This is some text It was the best of times, it was the worst of times.

这些是我提供的示例,用于显示ob_start()和ob_clean()调用的放置效果。

再次,您的示例确实完成了HTML所不能用的PHP。

如果你说你必须使用ob_start,ob_get_clean(),echo和ob_end_flush()来产生输出 - 好吧,我希望这个程序员只知道ob_get_clean()和ob_end_flush()。

我希望那些程序员出于某种原因认为他或她必须负责将输出交给用户;他们必须获取缓冲区内容并使用echo将其发送给用户。

我只是不明白为什么你写这个例子就像你做的那样,或者除了放置ob_start()之外,你试图证明这一点。

至于现实世界&#34; - 在现实世界中,程序员应该了解他们使用的语言功能以及它们的任何替代方案。他们应该理解概念 - 例如PHP自动发送任何生成的输出,而程序员不必调用函数将其传递给用户。

你称我使用缓冲错误。嗯,关于ob_sat()调用的位置,但其他一切都很好。

如果您在某种问题上发布了您的示例,我的回复将是 -

完全没有必要使用PHP来实现你要做的事情。取出PHP并使用直接HTML - 输出将是相同的。

对不起,但是这个例子,除了ob_start展示位置之外,只展示了一种奇怪且简洁的方式来向用户提供HTML。

也许你没有花时间考虑最好的例子,之后,首先要确定示例的内容。

如果我们忽略了这样一个事实,即该示例没有做任何直接HTML所做的事情,并且它以复杂的方式输出缓冲区,那么你所做的所有例子都让我直截了当 - 你可以在doctype之前放一些东西它将被处理。我感谢你指出这一点。

mc_kennedy,

我阅读了您指向的页面,但我不认为这适用,因为第一行输出不会以HTTP /开头,如页面指定的那样。

我的基础是我在浏览器的源视图窗口中看到的内容。第一行是doctype或a

一般来说每个人 -

有些人似乎在说,你必须在文件的最顶部调用header(),这样才能正确发送响应代码。

好吧,我试过了,最顶层的PHP,然后是标准的HTML,我没有看到任何区别。

我错了认为服务器会对200做出不同的反应,而不是对403?

我是否完全错误以及我所期待的 - 让服务器以某种方式对403或500错误做出反应 - 只是不存在的事情?

如果我使用的方法会导致header()调用被忽略,为什么日志显示我发送的代码?

我现在明白我应该自己生成错误页面,我怀疑(好吧,比怀疑的更多,更像是想要的那样。)

但我希望服务器以不同的方式对不同的响应代码作出反应,这根本不会发生吗?

鲍勃

4 个答案:

答案 0 :(得分:0)

header()函数仅更改Web服务器发送的现有标头。

在您的情况下,您无法改变状态。打开http://localhost/index.php即可向Abyss发送请求,该请求会搜索index.php。如果找到该文件 - 它会打开/执行它。并且因为您的文件实际存在,如果您发送状态:200,Abyss / Apache / Nginx将会执行。

即使您发送header('Status: 403');,服务器也不会尊重它。 我不确定是否可以选择以您希望的方式覆盖服务器的响应,但是使用apache,nginx您无法做到这一点。

编辑: 正如@Alex Lunix所说 - 您可以通过
将用户重定向到错误页面 header("Location: path/to/your/error/page");

答案 1 :(得分:0)

您可能想要检查Abyss服务器如何处理您的PHP脚本。由于日志条目表明您正在发送403响应,因此服务器可能将脚本视为NPH脚本,因此将输出(包括的头)直接发送到浏览器而不执行其他操作(例如检查是否应该转到配置的403页面)。有关详细信息,请参阅http://www.aprelium.com/data/doc/2/abyssws-win-doc-html/cgiinternals.html

答案 2 :(得分:0)

除了其他答案之外,您对对象缓冲的使用是错误的,这是一个简单的例子

<?php ob_start();?>
  <!DOCTYPE html>
  <html>
  <head></head>
  <body onload="initialize()">
     This is some text
  </body>
 </html>
<?php 
  $ob=ob_get_clean(); 
  echo $ob; 
  ob_end_flush();
?>

在现实世界中,你必须以不同的方式使用它,这只是一个例子。

答案 3 :(得分:-1)

在PHP中发送响应代码不应该将它们转发到错误页面。 使用标题(“位置:/ error / page / url”);将它们转发到页面,如果您的错误页面已经发送了响应代码,则在转发它们之前不需要发送它。

标题已经发送的问题是由于已经发送了内容,标题需要在所有其他内容之前发送。所以将它置于html之上会解决这个问题。

<?php
     if(Condition for 403){
         header("HTTP/1.1 403 - Forbidden", true, 403);//Tell the user that this page is forbidden (not necessary if /error/file/ sends response)
         header("Location: /error/file/"); //Forward user to your error page
         exit; //Used to prevent php from executing further in the script
     }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>

编辑:

将它置于顶部的原因是它们在任何输出之前发送(这是输出缓冲将执行的操作,但这会添加不必要的代码)。发送响应代码会告诉用户页面的性质,如果您正在编写404错误页面,那么您将发送404响应。如果在此页面上您想要403,则需要使用位置标题将它们转发到403页面。