我正在我的服务器上运行 nph-script.cgi。
服务器不断添加
HTTP/1.1 200 OK 日期:2009 年 11 月 5 日星期四 02:28:53 GMT 服务器:Apache/2.2.8 (Ubuntu) PHP/5.2.8-1hardy~ppa1 带有 Suhosin-Patch mod_perl/2.0.3 Perl/v5.8.8 内容长度:0 保持活动:超时=15,最大=100 连接:保持活动 内容类型:纯文本 X-Pad:避免浏览器错误
在每个通过 .cgi 脚本加载的页面底部。为什么会出现这种情况?如何删除附加到所有页面的这个烦人的消息?
答案1
我们发现一个类似的问题与一个 nph 文件有关,它充当 Intersystems Caché(数据库和 Web 应用程序服务器)的网关。只要我们不使用 URL 重写,它就可以正常工作。任何通过 URL 重写处理的请求都会产生上述虚假标头(在响应内容的底部或附近)。
我们尝试使用一个小的 Perl nph 脚本来隔离该错误,但遇到了同样的问题。在不同的服务器上进行了测试:Ubuntu 9.04 上的 Apache/2.2.11、Debian 5.0 上的 Apache/2.2.9 和 Red Hat EL 4 上的 Apache/2.0.52。
脚本nph-测试.cgi在常规 cgi-bin 目录中:
#!/usr/bin/perl -wT
use strict;
print "$ENV{SERVER_PROTOCOL} 200 OK\n";
print "Server: $ENV{SERVER_SOFTWARE}\n";
print "Content-Type: text/plain\n\n";
# Tell Perl not to buffer our output
$| = 1;
print "OK.";
URL 重写
RewriteEngine On
RewriteRule ^test/([0-9]+)$ /cgi-bin/nph-test.cgi
(在 Apache .conf 文件中,在 下Directory /var/www/
)
回复
OK.
HTTP/1.1 200 OK
Date: Mon, 07 Dec 2009 09:44:40 GMT
Server: Apache/2.2.11 (Ubuntu) PHP/5.2.6-3ubuntu4.2 with Suhosin-Patch
Content-Length: 0
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/plain
描述相同或类似问题的其他来源:
- www.webmasterworld.com/perl/3575036.htm
- www.webmasterworld.com/forum13/3590.htm
- https://issues.apache.org/bugzilla/show_bug.cgi?id=22898
对于测试脚本来说,使用 Content-Length 是可行的,但不能解决我们的问题,因为我们显然无法更改 Intersystems Caché 附带的 nph-cgi 可执行文件。
正如您所说,这可能应该提交给 Apache,但 httpd.apache.org/bug_report.html 上列出的规则相当令人生畏。(我对 Apache 的了解有限。)
答案2
您确定服务器设置正确吗?考虑到消息声称内容类型是 text/plain 而不是 text/html 或其他内容,我认为您的 CGI 或 .cgi 脚本设置有问题。
答案3
这是我在我们自己的 WAMP 服务器以及 LAMP 托管环境中偶尔看到的一个问题。Apache 1.3 和 2.0 的后续版本似乎限制了这个问题,但它经常出现在 2.2 中。
当 NPH 脚本与重写结合使用时,这个问题尤其突出。如果您处理自己的 gzip 压缩,这个问题会进一步加剧,这在使用 NPH 脚本时几乎是必需的。如果您不使用 URL 重写,问题几乎就会消失。
任何地方都没有记录这个问题,我不得不自己确定可能的原因和解决方案。我能够(大部分)通过以下方式解决该问题:添加 Content-Length 标头。这仅在您在发送到客户端之前累积页面输出时才有效,这样您就可以计算标头的字节大小。
例如,在构建页面时,如果您使用 Perl,则可以将它们累积到一个变量中,例如,$HTML
然后在处理完所有页面处理后,将其发送到处理最终输出的子程序。我还会根据需要在最终输出之前将标题单独累积到一个变量中,这有效地节省了我多次处理输出的麻烦,这对调试很有帮助。
以下是不支持 gzip 输出的代码片段:
子完成{ 我的($STATUS,$HEADER,$TYPE,$HTML,$ISNPH)= @_; 我的 $HTTP_PROTOCOL = $ENV{'SERVER_PROTOCOL'} 如果 ($ENV{'SERVER_PROTOCOL'} && $ENV{'SERVER_PROTOCOL'} =~ m/^HTTP\/\d\.\d\$/); $HTTP_PROTOCOL ||= 'HTTP/1.1'; $状态||= 200; $TYPE ||='文本/html'; 如果 ($STATUS =~ m/^30[123]$/) { $HEADER .= "内容长度: 0\n"; 打印“$HTTP_PROTOCOL $STATUS\n”; 打印$HEADER; 打印“内容类型:$TYPE \n”; 打印“位置:$HTML\n\n”; 出口; } 如果 ($ISNPH),则打印“$HTTP_PROTOCOL $STATUS\n”; 打印$HEADER; 打印“内容类型:$TYPE \n”; 打印'Content-Length:'.length($HTML)。“\n”如果($ISNPH); 打印“\n”; 打印$HTML; 出口; }
它可以被这样调用:
&finish('200', $HEADER, 'text/html', $HTML, 1);
如果您在使脚本支持 NPH 之前对其进行测试,只需将 a0
作为最后一个参数传递即可。只需在此函数调用之前完全不打印到客户端,然后将标题构建到$HEADER
HTML 中即可$HTML
。
如果您要进行重定向,请在参数中传递要重定向到的 URL $HTML
。在重定向场景中不需要实际的 HTML 输出。
如果仍然遇到问题,请进一步解决问题,并使用输出缓冲on
&测试您的脚本off
。
在某些情况下,这可能无法解决问题,我还没有找到解决方案,应该将其提交给 Apache 组。我只懂 CGI 编程,所以我没有能力研究 Apache 源代码或提交补丁,但希望有人能解决这个问题。
〜杰伊