Reputation: 23501
I'm trying to parse a HTTP request string with HTTP::Request->parse method,
GET / HTTP/1.1
Host: www.google.com
Referer: www.google.com
Cookies: A=B
(There's another "\r\n" at the end of it, but I can't append it without breaking the syntax highlighter ..)
The above string works when I send it with nc www.google.com 80 < request
Now I try to parse and send it throught 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;
}
And I get:
$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
So the parser is not working, it fails to parse both URI and Headers.
Any ideas?
Upvotes: 1
Views: 992
Reputation: 126722
I really don't like File::Slurp
. It's mostly a replacement for the idiom
my $contents = do {
open my $fh, '<', 'myfile' or die $!;
local $/;
<$fh>;
};
or, if you pass the filename on the command line
my $contents = do {
local $/;
<>;
};
which is far from difficult to use, and makes it clear what is happening.
Here, File::Slurp
is the cause of your problems because, when called in list context (and the parameters of a subroutine call apply list context) it returns a list of lines from the file instead of the whole file in a single scalar value.
Because HTTP::Request->parse
looks only at the first parameter passed, it sees only the GET
line, and produces a request with no headers.
You can fix it by writing
my $request = read_file ('/run/shm/request');
$request = HTTP::Request->parse($request);
or you may prefer
my $request = HTTP::Request->parse(scalar read_file ('/run/shm/request'));
But I would write something like
use autodie;
my $request = do {
open my $fh, '<', '/run/shm/request';
local $/;
my $contents = <$fh>;
HTTP::Request->parse($contents);
};
Update
By the way, a better way of viewing the HTTP message that HTTP::Message
at al. has built for you is to use print $message->as_string
. Using Data::Dumper
shows a lot of irrelevant data and context that is used internally by the object, and there is no way of knowing what parts of it are relevant.
In the case of your program above, a corrected version that uses
print $request->as_string
results in this output
GET / HTTP/1.1
Host: www.google.com
Referer: www.google.com
Cookies: A=B
which is exactly what your input file contains, and is hopefully what you would expect.
Upvotes: 2