【问题标题】:Odd PHP header() behavior from POST to php_self - inconsistent across environments从 POST 到 php_self 的奇怪 PHP header() 行为 - 跨环境不一致
【发布时间】:2011-05-10 09:56:42
【问题描述】:

我在将标头(位置:) 作为 HTML 表单 POST 的响应发送回 PHP_SELF 时遇到问题。

用例的基本部分:

  • 我在主页内包含一个 包含所有表单的页面 UI 响起。此表单发布到 本身 ($_SERVER['PHP_SELF'])。
  • 此表单包含“文件”字段和 传递一些文本(登录名、密码、 等)到自己进行 FTP 上传。
  • 如果上传成功,我输出 header() 其中位置是主要的 页面(连同一些参数 它告诉包含页面 打印上传成功消息)。
  • 主页(收到 header) 应该显示包含 随着形式再次回响 下次上传。
  • 一切正常 Dev,但在 Prod 中,我从来没有得到我的表格 回来 - 就像标题不是 正在发送。

让这件事如此神秘的三件事:

  • 我有两个环境,dev 是 windows/apache 1.3.37/php 5.2.11 快速 cgi,产品是 linux/apache (2.2.16)/php 5.2.14 快速 cgi 和 我已经配置了尽可能多的 相关的 PHP 参数相同 跨越开发和生产。在开发中, 上述用例有效 伟大的。在 Prod 中,文件确实 上传,但好像是标题 没有被退回。块 包含的内容应该在哪里 完全是空的。
  • 如果我将包含分开,以便 表单内容(UI 的东西)是 包含中唯一的东西,以及 形成 POST 到一个单独的文件 包含 FTP 上传逻辑, 完成时发回的标头 成功的上传确实适用于两者 dev 和 prod...文件上传, 标头被发回,主页 刷新,和的内容 包括显示。
  • 在 Dev 中,通过 Fiddler,我可以看到 POST 到 PHP_SELF 与所有 表单内容,我清楚地看到 标头返回。在 Prod 中,我可以 查看 POST 到 PHP_SELF,一切 看起来不错,但从来没有 返回的标头返回。 但是,在调试中,headers_sent 告诉我标头被发送到 正确的位置。 Echo'ing headers_sent 显示在我的主页中。

额外琐事:

  • 一开始我以为 .htaccess 是 碍事,但又一次, 如果我分开,一切正常 UI 和 FTP 上传内容,以及 .htaccess 在这种环境下非常 基本的。
  • 我也想过,也许输出 缓冲会改变行为 - 我尝试了各种 ob_start 合乎逻辑的地方,行为从不 改变了。
  • 最后,我尝试了一个数字选项 标头位置 - 在某些情况下,只是 指向http://www.google.com - 仍然好像没有标题 正在发送。

我没有想法 - 有人可以提供一些方向吗??

这是一个简化的测试用例——有趣的是,它在 dev 和 prod 中的行为相同,所以至少现在是一致的。

  • Test.php 包含在一个名为“upload.php”的页面中,并呈现了几个按钮。
  • “尝试”POST 到 PHP_SELF 和 test.php 的渲染内容从不 当 header('Location: ./upload.php') 是 称为...包含中的空间 页面为空白。
  • 但是,“Try2”发布到 test2.php 它调用 header('Location: ./upload.php') 并重新渲染 包含的 test.php 页面的按钮 没问题。

这是一个test.php:

<?php
if($_POST['submit']) {
Header('Location: ./upload.php');
} else {
echo
'<form name="test" action="'.htmlentities($_SERVER['PHP_SELF']).'" method="POST">
<input type=submit value=try name=submit>
</form>
<form name="test2" action="test2.php" method="POST">
<input type=submit value=try2 name=submit>
</form>';
}
?>

这里是 test.php...非常简单。

<?php
Header('Location: ./upload.php');
?>

这是一个来自 upload.php 的 sn-p:

<!--    <div id="flashcontent"></div> -->
</fieldset><?php require_once('test.php'); ?></div></div>
</body>
</html>

今天的更新——其实,简单测试用例的表现并不像我最初想的那样。我已经在简单的测试用例包含上面包含了真实文件,我认为这会导致经典的 headers-already-sent 问题。一旦我注释掉了现实生活中的文件,简单测试用例的行为现在与本文开头概述的原始用例相匹配。因此,如果从表单提交的包含中调用简单的测试用例,则加载标题,如果从包含文件发布到的另一个页面调用,则加载标题......没问题。但是,在生产中,只有在从发布到的页面调用时才会实现标头调用的结果,而不是在发布到 php_self 时调用。

<div class="panel_wrapper">
<div id="general_panel" class="panel currentmod">
<fieldset>
<legend><?php echo TB_UPLOADFILES; ?></legend>
<?php
//define('upload_opt',TRUE);
//require_once('upload_opt.php');
?>
<!--    <div id="flashcontent"></div> -->
</fieldset><?php require_once('test.php'); ?></div></div>
</body>
</html>

【问题讨论】:

  • 奇怪的是,我在日志记录(Apache 或 PHP)中没有发现任何有用或相关的东西 - 现在我有一个在两种环境中表现相同的测试用例,这让我认为它是从编码的角度来看最好避免的东西?即:不要从包含的页面调用包含页面的 header()?
  • 根据 HTTP 1.1 规范,Location 标头应使用绝对 URI(包括域和协议)
  • 是的,即使使用“位置:google.com”进行测试,结果也一样...

标签: php post header include


【解决方案1】:

可能是在错误后发送标头。尝试在生产服务器上关闭错误。

还要检查在标题之前没有输出空格。

Linux 中的文件名区分大小写,因此请确保您的大小写也正确。如果它找不到新位置,那可能会成功(尽管我对此表示怀疑,因为 google.com 不起作用。)

尝试在标头声明后添加“exit()”。

如果资源是外部的,请确保您的标头具有正确的语法并且是绝对的。

header("Location: http://www.google.com");
exit();

试着在你的生产服务器上做一个简单的例子来测试。完全删除帖子并确保标题重定向正常工作。如果您使用的是共享主机并且无法控制 PHP.ini 文件,则它可能是一个受限功能。

如果这些都不起作用,那么看看你的标头代码的 sn-p 会很有趣。

【讨论】:

  • 谢谢詹姆斯 - 我给了 exit() 一个机会,还是不行。区分大小写 - 检查并仔细检查。简单的用例......应该从一开始就这样做。我的编辑显示了简单用例的结果——有趣的是,现在 dev 和 prod 中的行为是相同的。我开始认为我的方法有缺陷 - 从包含的页面调用包含页面的标题 - 这可能是有问题的几乎是合乎逻辑的......有人确定吗?
【解决方案2】:

不知何故,这一切都与输出顺序、缓冲和标题有关,最终解决使用输出缓冲(ob_start / ob_end_flush)。尽管在两种环境中输出缓冲设置相同(output_buffering:4096),但出于某种原因,我似乎很享受我不在 Prod 中的 Dev 中的缓冲。通过将包含页面包装在 ob_start() 和 ob_end_flush() 中,行为现在在两种环境中都是一致的。

我对此并不感到兴奋,因为它似乎是一种解决方法,而且我仍然不知道为什么这两种环境的行为不同。似乎更确定的解决方案不是 POST 到 PHP_SELF 来调用 header(Location),而是 POST 到另一个调用 header(Location) 的文件。某处可能写到这是最佳实践,不要尝试从内部调用 header(Location),并避免使用输出缓冲。

如果有人想真正深入了解这个谜团,请随时contact me offline,因为我已经设法解决了症状,但我仍然不知道问题出在哪里。

【讨论】:

    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 2022-11-30
    • 2018-11-09
    相关资源
    最近更新 更多