HTTP :: Request->解析不能按预期工作

时间:2014-02-06 02:26:42

标签: perl lwp

我正在尝试使用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。

有什么想法吗?

1 个答案:

答案 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

这正是您的输入文件所包含的内容,并且希望是您所期望的。