gpt4 book ai didi

perl - IO::Socket 服务器和 POST 数据的小问题

转载 作者:可可西里 更新时间:2023-11-01 17:02:37 25 4
gpt4 key购买 nike

由于某些原因,我只能使用 IO::Socket 来构建我的小型 http 服务器(而不是其他专用于此的模块)。

EDIT1:我编辑了我的问题,我想知道我可以用什么代替注释行“#last ...”

这是我的脚本:

use strict;
use IO::Socket;

my $server = IO::Socket::INET->new(LocalPort => 6800,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10) or die "$@\n";
my $client ;

while ( $client = $server->accept()) {

my $client_info;
while(<$client>) {
#last if /^\r\n$/;
print "received: '" . $_ . "'\n";
$client_info .= $_;
}

print $client "HTTP/1.0 200 OK\r\n";
print $client "Content-type: text/html\r\n\r\n";

print $client '<H1>Hello World(!), from a perl web server</H1>';
print $client '<br><br>you sent:<br><pre>' . $client_info . '</pre>';

close($client);
}

现在,当我发送 POST 请求时,它(脚本)没有考虑最后一行(POST 数据):

wget -qO- --post-data='hello=ok' http://127.0.0.1:6800
<H1>Hello World(!), from a perl web server</H1><br><br>you sent:<br><pre>POST / HTTP/1.1
User-Agent: Wget/1.14 (linux-gnu)
Accept: */*
Host: 127.0.0.1:6800
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
</pre>

脚本输出为:

perl server.pl 
received: 'POST / HTTP/1.1
'
received: 'User-Agent: Wget/1.14 (linux-gnu)
'
received: 'Accept: */*
'
received: 'Host: 127.0.0.1:6800
'
received: 'Connection: Keep-Alive
'
received: 'Content-Type: application/x-www-form-urlencoded
'
received: 'Content-Length: 8
'

最佳答案

这是意料之中的。一个 POST 请求看起来像

POST / HTTP/1.1
Header: Value

Data=Value

您在 header 结束后终止处理,但数据在正文中!

如果您真的想编写自己的 HTTP 服务器,那么您应该从 header 中提取 HTTP 方法。如果是 POST,您可以查看 Content-length header 中的值,并读取该字节数:

read $client, my $post_data, $content_length;

WRT 更新的问题:

如果你想构建一个生产 HTTP 服务器,你会遇到麻烦。这东西很难。请通读perlipc其中涵盖了 TCP 服务器的主题。然后,您可以在此基础上实现 HTTP 的子集。

同时通读 CPAN 上实现服务器的模块。即使您不能在您的系统上编译模块,您也可以使用纯 Perl 模块,或者可以找到您可以重用的部分代码。 CPAN 的大部分内容都可以在 GPL 许可下使用。

如果你想这样做,就把它做好。为自己编写一个解析 HTTP 请求的子例程。这是一个不处理编码字段等的草图:

use strict; use warnings; use autodie;

BEGIN { die "Untested code" }

package Local::HTTP::Request {
sub new {
my ($class, $method, $path, $version, $header_fields, $content) = @_;
...;
}
...; # accessors
sub new_from_fh {
my ($class, $fh) = @_;
local $/ = "\015\102"; # CRLF line endings
chomp(my $first_line = <$fh>);
my ($method, $path, $version) = ...; # parse the $first_line

# this cute little sub parses a single field incl. continuation
# and returns the next line as well.
my $parse_a_field = sub {
chomp(my $line = shift);
my ($name, $value) = split /:\s+/, $line, 2;
while(defined(my $nextline = <$fh>)) {
# handle line continuation
if ($nextline =~ s/^[ \t]//) {
chomp $nextline;
$value .= $nextline;
} else {
return $name, $value, $nextline;
}
}
};

my %fields;
my $line = <$fh>;
until ($line eq $/) {
(my $name, my $value, $line) = $parse_a_field->($line);
$fields{lc $name} = $value;
}

read $fh, my $content, $fields{"content-length"} // 0;

return $class->new( ... );
}
}

然后在你的 accept 循环中:

 my $request = Local::HTTP::Request->new_from_fh($client);

print $client "HTTP/1.0 200 OK", "\015\012";
print $client "Content-type: text/plain", "\015\012";
print $client "\015\012";
print $client "Request body:\n";
print $client $request->content;

关于perl - IO::Socket 服务器和 POST 数据的小问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18083340/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com