【问题标题】:302 Redirect from CGI script stopped working in Apache 2.4302 从 CGI 脚本重定向在 Apache 2.4 中停止工作
【发布时间】:2016-08-12 01:51:47
【问题描述】:

我继承了自己编写的 CGI 应用程序的维护,但没有 文档,从未见过原作者。应用程序 在 Debian 8 中停止工作,但在 Debian 7 和 CentOS 5 中工作。 主要变化是从 Apache 2.2 升级(由 Debian 7 和 CentOS 5) 到 Apache 2.4(由 Debian 8 使用)以及从 perl 升级 5.8(在 CentOS 5 中)分别从 perl 5.14(在 Debian 7 中)到 perl 5.20。 有问题的部分归结为以下脚本(a 302-重定向):

#!/usr/bin/perl
$|=1; # activate auto-flushing of stdout
use strict;
use warnings;
my $CRLF = "\015\012";
print STDOUT "Status: 302 Moved Temporarily$CRLF" .
             "Location: /does_not_matter$CRLF" .
             "URI: /does_not_matter$CRLF" .
             "Connection: close$CRLF" .
             "Content-type: text/html; charset=UTF-8$CRLF$CRLF";
close STDOUT;
while(1) {
        sleep 1;
}

观察到的行为是 重定向永远不会到达客户端 只要脚本在与 Apache 2.4 一起使用时仍在运行,但 Apache 的 error.log 中没有错误消息。我换了客户端 (Firefox, Chromium, wget), Apache 模块 (mod_cgid & mod_cgi), 发送了额外的标题,删除了close STDOUT,删除了 $|=1,将$CRLF 替换为\n 并制作了脚本 fork 并退出父进程(这样 Apache 就不再是 父进程),一切都无济于事。唯一有效的方法:使用 Apache 2.2,将脚本转换为 NPH-CGI 脚本(必须发送 Apache 不会以任何方式修改的完整 HTTP 标头,即使 它们包含错误),使脚本退出而不是输入 无限循环。我通过 tcpdump 确认了带有 在脚本被杀死之前,重定向确实永远不会离开服务器。 并从响应中的日期线和最终的时间 到达我收集到 Apache 立即收到我的输出(& 立即将日期行添加到标题中),但不发送 回复客户。

不用回答了,我自己已经想好了解决办法 并将写一个答案。我只是想让解决方案可用 给其他可能遇到同样问题的人。

【问题讨论】:

    标签: cgi http-redirect apache2.4


    【解决方案1】:

    问题在于缺少邮件正文。 302 重定向可能包含 消息体(参见 RFC 2616,第 4.3 节(消息体):“所有其他 响应确实包含消息正文,尽管它可能为零 长度”),但 Content-Length-line 是可选的(RFC 的第 4.4 节 2616 表示消息体长度可以通过关闭 如果缺少 Content-Length-line 则连接)。由于 Apache 可以 不知道是否要发送消息体,它必须等待 直到我关闭连接或实际发送消息正文 (Apache 2.2 显然在这里表现错误,没有等待 消息正文 - 或者 close STDOUT; 在 perl 中不起作用 5.20 它在旧的 perl 版本中所做的)。正确的脚本应该 因此看起来像这样(经过验证可以在 Apache 2.2 和 Apache 2.4) - 唯一的区别是额外的$CRLF 终止长度为零的消息体:

    #!/usr/bin/perl
    $|=1; # activate auto-flushing of stdout
    use strict;
    use warnings;
    my $CRLF = "\015\012";
    print STDOUT "Status: 302 Moved Temporarily$CRLF" .
                 "Location: /doesNotMatter$CRLF" .
                 "URI: /doesNotMatter$CRLF" .
                 "Connection: close$CRLF" .
                 "Content-type: text/html; charset=UTF-8$CRLF$CRLF$CRLF";
    close STDOUT;
    while(1) {
            sleep 1;
    }
    

    https://stackoverflow.com/a/8062277/2845840 为我指明了正确的方向。

    【讨论】:

      猜你喜欢
      • 2020-05-27
      • 2020-05-31
      • 2020-09-13
      • 1970-01-01
      • 2013-03-06
      • 2013-10-09
      • 2015-12-28
      • 2014-04-21
      • 1970-01-01
      相关资源
      最近更新 更多