考虑以下代码;它基本上是一个表单,通过HTTP POST发送一些数据。当POST数据到达时,发送Refresh HTTP报头。
<?php
if (!empty($_POST))
{
header("Refresh: 5; URL=http://$_SERVER[SERVER_NAME]$_SERVER[REQUEST_URI]");
}
?>
<!doctype html>
<form method=post>
<input type=hidden name=foo value=bar>
<input type=submit>
</form>
<?php
echo "The location was requested using the HTTP $_SERVER[REQUEST_METHOD] method; $_POST = ".var_export($_POST, 1);
?>
现在,这样做:
- 在Firefox浏览器中打开(我在这里创建了一个演示;我在Debian上使用6.0.1)。
- 提交表单显然,浏览器执行了一个HTTP POST请求。请注意,
Refresh
HTTP头与响应一起出现。 - 等待5秒。现在
Refresh
标头正在被应用,位置将被重定向到自身。 - Firefox执行GET请求。这绝对是GET,因为Firebug和PHP的
$_SERVER['REQUEST_METHOD']
都这么说。 - 按
F5
键。由于最后一个执行的HTTP请求是一个GET请求,因此可能会丢失以前请求的所有POST数据。但是,出现一个对话框,要求我重新发送POST数据:
要显示此页面,Iceweasel必须发送重复先前执行的任何操作(如搜索或订单确认)的信息。
所以,我的问题是-为什么POST数据还在这里?这是一个错误还是故意的行为?请注意,使用以下任何一种都会导致POST数据的丢失(预期的行为):
-
Location
标头代替Refresh
-
Refresh
头的URL=
参数值不同(用户将被重定向到另一个位置)。 - 另一个浏览器(我测试过Internet Explorer 9.0.2和Chromium 6.0)。
这既不是bug,也不是预期的行为。这样做的原因是没有任何HTTP rfc定义的名为Refresh:
的头(最明显的是RFC1945和RFC2616没有提到它)。这意味着,虽然大多数浏览器确实实现了Refresh
标头,就好像它是一个元刷新,但没有预期的行为,可以假设在所有浏览器中是相同的。
环顾StackOverflow和互联网,似乎Refresh:
标头(像许多东西一样)是网景在互联网早期发明的,并被所有人采用。虽然许多Netscape的任意设计(如Javascript)后来被采用为行业标准,但Refresh:
标头并没有,因为HTTP已经用3xx
响应码提供了这个功能。
总而言之,不同的浏览器处理它的方式不同,这并不奇怪,因为没有标准告诉浏览器的开发人员确切地如何处理它。关于在应用程序中使用标题-不要。简单明了。使用3xx重定向。这就是它们的作用。如果您使用它是因为您需要在超时后刷新页面,请使用<meta>
刷新-虽然这现在已被正式弃用,但它应该以相同的方式处理。