Apache2 发送两个带有映射“nph-”CGI 的 HTTP 标头

Posted

技术标签:

【中文标题】Apache2 发送两个带有映射“nph-”CGI 的 HTTP 标头【英文标题】:Apache2 sends two HTTP headers with a mapped "nph-" CGI 【发布时间】:2014-04-24 08:45:41 【问题描述】:

总结

我正在尝试映射一些文件扩展名以由 nph(非解析头)CGI 可执行文件执行。

假设我想访问一个 URL http://server/file.ext 并将“ext”文件扩展名映射到“触发”我的 nph CGI (/var/www/cgi-bin/nph-test.sh) 的执行。

Apache 配置

为此,我使用了 mod_actions 和 mod_cgid,这是我的相关配置信息:

<VirtualHost *:80>
        DocumentRoot /var/www/htdocs
        ScriptAlias /cgi-bin /var/www/cgi-bin

        Action cgi-wrapper /cgi-bin/nph-test.sh

        AddHandler cgi-wrapper .ext
</VirtualHost>

NPH CGI 脚本

这是我的 nph-test.sh 外壳:

#!/bin/sh

echo "HTTP/1.0 200 OK"
echo "Server: Shell/1.0"
echo "Status: 200 \"OK\""
echo "Connection: close"
echo "Content-type: text/html"
echo ""
echo "<html><body><pre>"
echo "QUERY_STRING = "$QUERY_STRING
echo "PATH_TRANSLATED = "$PATH_TRANSLATED
echo "</pre></body></html>"

问题

当我使用此 URL http://localhost/cgi-bin/nph-test.sh?Hello 访问 nph-test.sh 时,我得到:

HTTP/1.0 200 OK
Server: Shell/1.0
Status: 200 "OK"
Connection: close
Content-type: text/html

<html><body><pre>
QUERY_STRING = Hello
PATH_TRANSLATED =
</pre></body></html>

使用此 URL http://localhost/file.ext 中的文件映射时出现问题我得到一个 double http 标头(它将 nph cgi 脚本视为 non nph cgi脚本):

HTTP/1.0 200 OK
Server: Shell/1.0
Status: 200 "OK"
Connection: close
Content-type: text/html

<html><body><pre>
QUERY_STRING =
PATH_TRANSLATED = /var/www/htdocs/file.ext
</pre></body></html>
HTTP/1.1 200 OK^M
Date: Tue, 18 Mar 2014 14:32:29 GMT^M
Server: Apache/2.4.6 (Ubuntu)^M
Content-Length: 0^M
Keep-Alive: timeout=5, max=100^M
Connection: Keep-Alive^M
Content-Type: text/x-sh^M
^M

我的发现

搜索了几个小时后,我只找到了这个2003 apache bug report。这也暗示了理论上尚未应用的补丁。

但是搜索当前mod_cgid source code可以看到代码已经改成能够捕获“nph-”cgi文件前缀(strrchr):

1372 if ((argv0 = strrchr(r->filename, '/')) != NULL) 
1373    argv0++;
1374 
1375 else 
1376    argv0 = r->filename;
1377 
1378    
1379 nph = !(strncmp(argv0, "nph-", 4));

问题

apache2 有没有办法将文件扩展名映射到 nph cgi? (不返回两个 http 标头)

还有其他方法可以做到这一点或任何解决方法吗?

Apache 和 OS 服务器信息

我在 Ubuntu 13.10 中使用默认的 apache2 服务器:

# apachectl -V
Server version: Apache/2.4.6 (Ubuntu)
Server built:   Dec  5 2013 18:32:22
Server's Module Magic Number: 20120211:23
Server loaded:  APR 1.4.8, APR-UTIL 1.5.2
Compiled using: APR 1.4.8, APR-UTIL 1.5.2
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

更新:解决方案

使用 mod_rewrite 模块解决问题的更改配置:

<VirtualHost *:80>
        DocumentRoot /var/www/htdocs
        ScriptAlias /cgi-bin /var/www/cgi-bin

        RewriteEngine on

        RewriteCond %QUERY_STRING ^$
        RewriteRule ^/?(.*\.ext)$ /cgi-bin/nph-test.sh?$1 [PT]

        RewriteRule ^/?(.*\.ext)$ /cgi-bin/nph-test.sh?$1&%QUERY_STRING [PT]
</VirtualHost>

【问题讨论】:

【参考方案1】:

我认为(直接)在 2.4.x 源代码上是不可能的。 正如您正确指出的那样,该错误当前位于reopened status。

提议的补丁包括两个主要修改:

    修复 nph- 检测(这部分目前在源代码树中) 摆脱所有剩余的输出过滤器(这部分在源代码树中缺失

我无法测试,但我认为可以使用 mod_rewrite 解决此错误: 查看 mod_rewrite 文档似乎与nph 一起工作得很好

您可以在documentation page 中找到完整的 nph- + mod_rewrite 示例

【讨论】:

非常感谢您的回复!我一定会尝试使用 mod_rewrite。我需要一些时间来测试它,因为我必须重新设置环境......然后我会将你的答案标记为正确的

以上是关于Apache2 发送两个带有映射“nph-”CGI 的 HTTP 标头的主要内容,如果未能解决你的问题,请参考以下文章

Apache2 CGI 配置

apache2执行cgi配置

编译安装apache2.4

ubuntu下apache2 安装 配置 卸载 CGI设置 SSL设置

将 JSON 发布到 Python CGI

sh Ubuntu - Apache2 - Php7.0与mbstring + pear + libapache2-mod + curl + cgi