我正在尝试使用HTTP :: Request->解析方法解析HTTP请求字符串,
GET / HTTP/1.1
Host: www.google.com
Referer: www.google.com
Cookies: A=B
(最后还有另一个“\ r \ n”,但我不能在不破坏语法高亮的情况下追加它。)
当我使用nc www.google.com 80 < request
现在我尝试解析并通过LWP发送它:
use warnings;
use strict;
use File::Slurp qw/read_file/;
use HTTP::Request;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->parse (read_file ('/run/shm/request'));
print Dumper ($request);
my $r = $ua->request ($request);
if ($r->is_success)
{
print $r->decoded_content;
}
else
{
print $r->status_line;
}
我得到了:
$VAR1 = bless( {
'_headers' => bless( {}, 'HTTP::Headers' ),
'_content' => '',
'_protocol' => 'HTTP/1.1',
'_method' => 'GET',
'_uri' => bless( do{\(my $o = '/')}, 'URI::_generic' )
}, 'HTTP::Request' );
400 URL must be absolute
因此解析器无法正常工作,无法解析URI和Headers。
有什么想法吗?
答案 0 :(得分:2)
我真的不喜欢File::Slurp
。它主要是成语的替代品
my $contents = do {
open my $fh, '<', 'myfile' or die $!;
local $/;
<$fh>;
};
或者,如果您在命令行上传递文件名
my $contents = do {
local $/;
<>;
};
这远非难以使用,并且清楚地表明发生了什么。
这里,File::Slurp
是导致问题的原因,因为,当在列表上下文中调用(以及子例程调用的参数应用列表上下文)时,它会返回列的行。文件而不是整个文件的单个标量值。
由于HTTP::Request->parse
仅查看传递的第一个参数,因此它只会看到GET
行,并生成一个没有标题的请求。
您可以通过编写
来解决此问题my $request = read_file ('/run/shm/request');
$request = HTTP::Request->parse($request);
或者您可能更喜欢
my $request = HTTP::Request->parse(scalar read_file ('/run/shm/request'));
但我会写类似
的内容use autodie;
my $request = do {
open my $fh, '<', '/run/shm/request';
local $/;
my $contents = <$fh>;
HTTP::Request->parse($contents);
};
<强>更新强>
顺便说一下,查看HTTP::Message
的HTTP消息的更好方法是。为您构建的是使用print $message->as_string
。使用Data::Dumper
显示了对象内部使用的大量无关数据和上下文,并且无法知道它的哪些部分是相关的。
对于上述程序,使用
的更正版本print $request->as_string
导致此输出
GET / HTTP/1.1
Host: www.google.com
Referer: www.google.com
Cookies: A=B
这正是您的输入文件所包含的内容,并且希望是您所期望的。