测试

测试

我正在运行Debian 6.0.3( squeeze)、nginx-0.7.67fcgiwrap-1.0-1+squeeze1。以下是测试脚本:

#!/usr/bin/perl
use 5.010;
use warnings;
use strict;

use Data::Dumper;

print "Content-Type: text/html\n\n";
say Dumper {map {$_ => $ENV{$_}} 'SCRIPT_NAME', 'DOCUMENT_ROOT', 'WHATEVER'};
say "$<, $>, $(, $)";

配置如下nginx

server {
    server_name   domain.com;
    root   /home/yuri/6;
    access_log   /var/log/nginx/domain.com-access.log;
    error_log   /var/log/nginx/domain.com-error.log;

    location /cgi-bin/ {
        fastcgi_pass   unix:/var/run/fcgiwrap.socket;
        fastcgi_param   DOCUMENT_ROOT   $document_root;
        fastcgi_param   DOCUMENT_ROOT   /home/yuri/7/;
        fastcgi_param   SCRIPT_NAME   $fastcgi_script_name;
        fastcgi_param   WHATEVER   1;
        fastcgi_param   WHATEVER   2;
    }

    location /1.php {
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_param   PHP_ADMIN_VALUE   cgi.fix_pathinfo=1;
        fastcgi_param   REQUEST_METHOD    $request_method;
        fastcgi_param   SCRIPT_FILENAME   whatever;
        fastcgi_param   SCRIPT_FILENAME   $document_root$fastcgi_script_name;
    }
}

以下是我访问网址时在浏览器中获得的结果http://domain.com/cgi-bin/1.pl

$VAR1 = { 'SCRIPT_NAME' => '/cgi-bin/1.pl', 'DOCUMENT_ROOT' => '/home/yuri/7/', 'WHATEVER' => '2' };

看起来,它fcgiwrap使用第一个DOCUMENT_ROOT来查找脚本,但脚本获取参数的最后一个值。如果您更改DOCUMENT_ROOT指令的顺序,Web 服务器将返回403。问题是...为什么会这样?

php尽管按预期工作:第二个SCRIPT_FILENAME覆盖了第一个。

答案1

fastcgi 库只是将给定的任何参数传递给指针environ。as getenv()used byfcgiwrap使用最先出现的任何环境变量(优化?)。PHP FPM 可能将此环境视为数组数据类型,任何后一个键都会覆盖第一个键。

您不应该依赖顺序,并确保只有一个键。我没有看过 FastCGI 规范,不知道是否记录了正确的行为。

至于为什么你得到 403,我猜是没有/home/yuri/7/1.pl文件。(记住,第一个参数与 fcgiwrap 匹配)。由于它不可执行,fcgiwrap 返回 403。

测试

以下补丁打印出给定的环境FCGI_Accept()

diff --git a/fcgiwrap.c b/fcgiwrap.c
index e86ff9d..0dff2e6 100644
--- a/fcgiwrap.c
+++ b/fcgiwrap.c
@@ -470,6 +470,11 @@ static void inherit_environment(void)
    char * const * p;
    char *q;

+   for (p = environ; *p; p++)
+       fprintf(stderr, "ENV: %s\n", *p);
+
+   fprintf(stderr, "ENV[FOO] = %s\n", getenv("FOO"));
+
    for (p = inherited_environ; *p; p++) {
        q = strchr(*p, '=');
        if (!q) {

测试所用的nginx配置:

events {
    worker_connections 768;
}

pid pid;
error_log error_log;
http {
    server {
        access_log off;
        listen 5555;
        location / {
            fastcgi_param FOO BAR;
            fastcgi_param FOO BARRED;
            fastcgi_pass unix:/tmp/sock;
        }
    }
}

启动服务器的命令(假设nginx.conf在当前目录中):

$ nginx -p . -c nginx.conf
$ env -i ./fcgiwrap -p /dev/null -s unix:/tmp/sock

现在,运行curl http://localhost:5555/并且 stderr 将打印:

ENV: FCGI_ROLE=RESPONDER
ENV: FOO=BAR
ENV: FOO=BARRED
ENV: HTTP_USER_AGENT=curl/7.30.0
ENV: HTTP_HOST=localhost:5555
ENV: HTTP_ACCEPT=*/*
ENV[FOO] = BAR
Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?

另外,这是一个开发版本。当前稳定版本 (1.1.0) 不包含-p上述参数。对于结果来说,这并不重要,您也可以将其删除并收到未SCRIPT_NAME给出任何错误之类的错误。

相关内容