PHP中重定向标头之后的所有代码都会被执行吗?

Posted

技术标签:

【中文标题】PHP中重定向标头之后的所有代码都会被执行吗?【英文标题】:Will all code after redirect header in PHP always get executed? 【发布时间】:2011-11-06 23:31:58 【问题描述】:

所以我知道一般的经验法则是在 php 中进行标头重定向之后,您应该调用 exit() 以避免运行额外的代码,但我想知道您是否将代码放在重定向标头之后,如果它会总是跑步?

我正在对 Google Analytics 中跟踪推荐的各种方法进行一些研究,并发现了这篇文章:Google Analytics Tips & Tricks – Tracking 301 Redirects in Google Analytics

建议这样做:

<?
Header( “HTTP/1.1 301 Moved Permanently” );
Header( “Location: http://www.new-url.com” );
?>

<script type=”text/javascript”>
var gaJsHost = ((“https:” == document.location.protocol) ? “https://ssl.” : “http://www.”);
document.write(unescape(“%3Cscript src=’” + gaJsHost + “google-analytics.com/ga.js’ type=’text/javascript’%3E%3C/script%3E”));
</script>
<script type=”text/javascript”>
try 
var pageTracker = _gat._getTracker(“UA-YOURPROFILE-ID”);
pageTracker._trackPageview();
 catch(err) </script>

从我一直理解 header() 函数的方式来看,它取决于浏览器,它可以随时运行重定向。因此,无法保证 JavaScript 会在重定向发生之前实际开始或完成执行。

PHP's documentation for the header() function 表示重定向后退出的原因是“确保我们重定向时不会执行下面的代码”。这听起来不像他们保证所有以下代码都会运行,只是它可能会发生。

不管怎样,我找到了一种不同的方法来实际管理跟踪,但我想看看我是否可以找出 header() 在这种情况下究竟是如何工作的..

感谢您的帮助。

【问题讨论】:

我正在研究跟踪重定向页面的相同问题;你能分享你的“其他方式”吗?谢谢。 自从我设置它已经有几年了,真的不记得我做了什么,甚至不记得这是什么项目。也就是说,我会想象解决方案涉及事件跟踪。 developers.google.com/analytics/devguides/collection/gajs/… 如果你重定向到new-url.com/?from301 那么你可以在看到相应的URL参数时触发相应的事件。就像我说的那样,我没有具体的细节,但我想我就是这样做的。 【参考方案1】:

在 PHP 中使用 header 函数只会添加到服务器返回的响应的 headers。它不会立即发送任何数据,也不会立即终止连接。 header 调用之后的任何代码都会被执行。

特别是,即使在执行 301 重定向之后添加响应正文也是一个好主意,这样不支持重定向的客户端也可以获得一些描述性响应。事实上,根据HTTP 1.1 specification Section 10.3.2 -

除非请求方法是 HEAD,否则响应的实体应该 包含一个简短的超文本注释,其中包含指向新 URI 的超链接。如果 收到 301 状态代码以响应请求,而不是 GET 或 HEAD,用户代理不能自动重定向 请求,除非它可以被用户确认,因为这可能 更改发出请求的条件。

【讨论】:

您有任何文件支持吗? 当然,看看HTTP 1.1 spec Section 10.3.2 - "除非请求方法是 HEAD,否则响应的实体应该包含一个简短的超文本注释,其中包含指向新 URI 的超链接。如果 301收到状态码是为了响应 GET 或 HEAD 以外的请求,除非用户可以确认,否则用户代理不得自动重定向请求,因为这可能会改变发出请求的条件。”【参考方案2】:

这是一个竞争条件。一旦重定向标头发送到浏览器,浏览器将关闭当前连接并为重定向 URL 打开一个新连接。在关闭原始连接并且 Apache 关闭脚本之前,您的代码将继续像以前一样执行。

理论上,如果客户端/服务器之间有足够快的连接,并且管道中的任何地方都没有缓冲,则发出标头会导致脚本立即终止。实际上,启动关闭的时间可能介于“现在”和“从不”之间。

【讨论】:

这是不正确的。发送标头不会关闭连接。事实上,发送带有重定向的响应正文是规范而不是异常。 我没这么说。我说浏览器将在收到标头后关闭连接 - 它应该会过去 ---> 那里,因此加载更多将被丢弃的文档是没有意义的。 这也是不正确的。如果不下载完整的响应正文,浏览器也不会关闭连接。 问题不在于下载响应。这是关于执行它。这又是一个竞争条件 - 浏览器将打开新位置,这可能在它开始加载/执行响应正文中的任何 JS 之前发生。 我们可以为此争论一整天,这听起来并不有趣。因此,为了尽可能清楚 - 问题询问是否始终执行 PHP 代码,即使在标头(“位置...”)之后也是如此。答案是。任何其他答案都是错误的。【参考方案3】:

Location 行后面的 html 不在 PHP 中运行;它会在浏览器中运行。是否执行您在该页面上包含的 Javascript 取决于浏览器; PHP与它无关。

对我来说,PHP 文档暗示当您发送重定向时,header() 以下的任何 PHP 都将继续运行。但它在 PHP 解释器中“运行”,将 JS 转储到浏览器。它在 PHP 文档中所说的内容与 JS 是否由浏览器运行之间没有关系。

【讨论】:

【参考方案4】:

编辑

好吧,正如 Anupam Jain 指出的那样,看起来浏览器不会在没有获取响应正文的情况下终止连接,这听起来很明智。所以我重新考虑了我的答案

这听起来不像他们保证所有以下代码都会运行

完全正确 如果有一些不应该执行的合理代码,这很可能是一个警告。以私人页面内容为例。因此,除了发送标头之外,您还必须确保没有发送敏感内容,并且退出看起来是非常强大的解决方案。因此,我将其表述为“确保在我们重定向时不会执行下面的 sensible 代码。”

因此无法保证 JavaScript 会在重定向发生之前实际开始或完成执行。

正是 看来这与脚本执行无关,而是与浏览器在获得 3xx 响应后执行任何操作的意愿有关。我想我会测试它,但你也可以测试它。

【讨论】:

您的假设不正确。浏览器不会在没有获得响应正文的情况下终止连接。浏览器有正当理由不自动重定向。以Firefox addon 为例。【参考方案5】:

我注意到代码仍然会执行,并且基于 if 语句的多个标头可能会导致“重定向循环错误”。我养成了现在在每次标头重定向后添加die("Redirecting..."); 的习惯,并且没有看到问题仍然存在。

【讨论】:

以上是关于PHP中重定向标头之后的所有代码都会被执行吗?的主要内容,如果未能解决你的问题,请参考以下文章

标头重定向后会执行 PHP 脚本吗?

如何在PHP中重定向到同一页面

在 PHP 中重定向而不使用 header 方法

在另一个页面中重定向时php会话不起作用[重复]

Grails:防止在控制器的基类中重定向或转发后进一步执行代码

PHP中重定向网页跳转页面的方法(共三种)