2011-09-03 96 views
0

请考虑以下代码;它基本上是一种通过HTTP POST发送一些数据的表单。 POST数据到来时,会发送刷新HTTP标头。POST请求发送刷新标头的位置会使Firefox创建GET请求,但仍然保留POST数据

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

现在,这样做:

  1. 打开它在Firefox浏览器(我已经创建了一个演示here;我在Debian使用6.0.1)。
  2. 提交表单。显然,浏览器执行了HTTP POST请求。请注意,Refresh HTTP标头附带了响应。
  3. 等待5秒钟。现在Refresh标题正在被应用,并且该位置将被重定向到它自己。
  4. Firefox执行GET请求。这绝对是GET,因为Firebug和PHP的$_SERVER['REQUEST_METHOD']都这么说。
  5. F5键。由于上次执行的HTTP请求是GET请求,因此可能会希望以前请求中的所有POST数据都将丢失。然而,出现一个对话框,并要求我重新发送POST数据:

要显示此页面,Iceweasel必须发送早些时候进行,将重复任何操作(如搜索或订单确认)信息。

所以,我的问题是 - 为什么POST数据仍然在这里?这是一个错误还是有意的行为? 注意,使用以下任何会引起POST数据的丢失(预期的行为):

  • Location头代替Refresh
  • Refresh报头的 URL=参数的
  • 不同值(用户将被重定向到另一个地点)。
  • 另一个浏览器(我测试过Internet Explorer 9.0.2和Chromium 6.0)。

回答

3

这既不是一个错误,也不是预期的行为。原因是没有任何标头叫Refresh:由任何HTTP RFC定义(最值得注意的是RFC1945RFC2616没有提到它)。这意味着,尽管大多数浏览器确实实现了Refresh标题,就好像它是元刷新一样,但不存在预期的行为,可以假设在所有浏览器中都是相同的。

环顾StackOverflowthe internet in general似乎Refresh:标题是(像很多东西)由Netscape在互联网的早期发明,并由大家采用。尽管许多这些随意的Netscape设计(such as Javascript)后来被采纳为行业标准,但Refresh:标头却没有,因为HTTP已通过3xx响应代码为此功能做了规定。

不足之处在于,不同的浏览器以不同的方式处理它并不奇怪,因为没有标准可以告诉浏览器的开发人员如何处理它。关于在你的应用程序中使用头文件 - 不要。干净利落。使用3xx重定向。这就是他们的目的。如果您正在使用它,因为您需要在超时后刷新页面,请使用<meta> refresh - while this is now officially deprecated它应该在任何地方以相同方式处理。

+0

如果需要设置cookie并使用刷新标题或元刷新标记,该怎么办? –