【问题标题】:FCGI+Perl+lighttpd: POST request is emptyFCGI+Perl+lighttpd:POST 请求为空
【发布时间】:2012-09-26 11:05:38
【问题描述】:

我在 perl 上有带有 fastcgi 的 lighttpd 服务器。 Lighttpd 配置:

server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
        "mod_rewrite",
        "mod_accesslog",
)

server.document-root        = "/var/www"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"

server.max-keep-alive-requests = 10
server.max-keep-alive-idle = 5
#server.max-fds = 10240
server.max-connections = 8192

index-file.names            = ( "index.php", "index.html",
                                "index.htm", "default.htm",
                                "index.lighttpd.html" )

url.access-deny             = ( "~", ".inc" )

static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

dir-listing.encoding        = "utf-8"
server.dir-listing          = "disable"

compress.cache-dir          = "/var/cache/lighttpd/compress/"
compress.filetype           = ( "application/x-javascript", "text/css", "text/html", "text/plain" )

include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

$HTTP["host"] =~ "(^|\.)hostname\.net$" {
    server.document-root = "/var/www/hostname.net"
    url.rewrite-once = (     
        "^/index.php" => "/index.pl",
    )
}

启用快速 CGI。这里配置fcgi.server:

fastcgi.server += ( ".pl" =>
        ((
                "socket" => "/tmp/perl.socket" + var.PID,
                "bin-path" => "/usr/bin/dispatch.fcgi",
                "docroot" => "/var/www/hostname.net",
                "check-local"     => "disable",
        ))
)

dispatch.fcgi:

use strict;
use CGI::Fast;
use Embed::Persistent; {
    my $p = Embed::Persistent->new();
    while (new CGI::Fast) {

        my $filename = $ENV{SCRIPT_FILENAME};
        my $package  = $p->valid_package_name($filename);
        my $mtime;

        if ($p->cached($filename, $package, \$mtime)) {

            eval {$package->handler;};
        }
        else {

            $p->eval_file($ENV{SCRIPT_FILENAME});
        }
    }
}

这是我的脚本(编辑后):

use strict;
use warnings;

use CGI;
my $q = new CGI;

open my $fh, '>', "/var/www/hostname.net/payload.body" or die "Can't open payload.body: $!";
{
 local $/;
 print $fh $q->param('arg1');
}
close $fh;

print $q->header;
print $q->param('arg1');

发送请求:

wget --post-data="arg1=dfsdfasf&arg2=sdfasfdsdf" http://hostname.net/test.pl --save-headers --quiet -O -

payload.body 为空(但更改时间更新)并且转储为:

HTTP/1.0 200 OK
Content-Type: text/html; charset=ISO-8859-1
Content-Length: 0
Connection: keep-alive
Date: Fri, 05 Oct 2012 12:23:07 GMT
Server: lighttpd/1.4.28

就是这样。

我尝试通过这种方式获取 POST 参数,但查询为空。我就是这样尝试的:

use Data::Dumper;
my $request;
use FCGI;
my $env;
my $q = FCGI::Request();
$env = $q->GetEnvironment();
my $buffer = "data\n";

if ( $ENV{'REQUEST_METHOD'} eq "POST" ){

    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else {

    print ("some error");
};

print("Content-type: text/plain\r\n\r\n", Dumper($buffer),"\n");

我需要从请求中获取 POST 参数(二进制发布数据)。

你能帮帮我吗?也许我以错误的方式获取 post 参数?

非常感谢!

【问题讨论】:

  • 你能分享完整的输出转储吗?它不能只有 $VAR1 = ''
  • 我从第一个脚本添加了转储:只有空字符串和标题

标签: perl post request lighttpd fastcgi


【解决方案1】:

open 解释

这就是您的第一个脚本无法运行的原因:

open FH, "<payload.body";
#         ^---

perl 从 Bourne Shell 借用 open 语法。

&lt;  表示读取
&gt;  表示写入
&gt;&gt; 表示追加
+&lt; 表示读取和写入

如果我们遵循一些最佳做法,您的 open 声明将是:

open my $fh, '>', "payload.body" or die "Can't open payload.body: $!";

让 Perl 帮助你

事实上,您试图print 到一个只读的文件句柄。但是,Perl 可以警告您这个问题以及您可能遇到的许多其他问题。只是use strictuse warnings 在脚本顶部(实际上是所有 脚本)。您可以使用Carp 模块发出更好的错误消息。请注意,在服务器上,这些警告通常会记录在日志中,但您发现的内容值得一试。

Dumper 是什么

Data::Dumper 模块采用 Perl 数据结构并将它们转换为可执行的 Perl 代码。这非常适合调试,有时也可以用于序列化,但仅打印出字符串或标量就不好。所有包含的数据都将被引用,以便成为有效的 Perl,这不是您想要的。

其他零碎

read 从头开始​​填充目标变量(索引 0)。指定一个偏移量作为第四个参数(例如-1)以附加您正在读取的数据。

binmode 没有第二个参数只在 Windows 上有用。 在 Windows 上,\n 可以是逻辑换行符(例如“\r\n”)。在网络中使用字节值\015\012

在第二个示例中,您使用来自STDIN$ENV{CONTENT_LENGTH} 字符覆盖$buffer。出于调试目的,您可能还想打印此内容长度。

FCGI::Request() 返回一个请求对象。 documentation 声明您必须 Accept 每个请求,可能在一个循环中。 Accept 方法在成功的情况下返回一个值 &gt;= 0

【讨论】:

  • 谢谢。我修正了错别字并相应地编辑了我的问题。但是输出仍然是空的:(我还没有更正第二个脚本。
猜你喜欢
  • 1970-01-01
  • 2014-09-30
  • 2014-03-13
  • 1970-01-01
  • 2020-07-16
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多