【发布时间】: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”进行测试,结果也一样...