2014-02-06 4 views
1

Я пытаюсь разобрать строку запроса HTTP с HTTP :: request-> синтаксический метод,HTTP :: request-> синтаксический анализ не работает, как ожидалось

GET/HTTP/1.1 
Host: www.google.com 
Referer: www.google.com 
Cookies: A=B 

(Там другая «\ г \ п "в конце, но я не могу добавить его, не нарушая подсветку синтаксиса ..)

выше строка работает, когда я посылаю его с 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 и заголовки.

Любые идеи?

+1

Пожалуйста, всегда * 'использовать строгие' и 'использовать предупреждения' в верхней части * каждой программы Perl, особенно когда вы просите о помощи. – Borodin

+0

@Borodin Я сделал, просто удалил его в пасте и да, не жалуюсь на Perl ;-) – daisy

+1

Лучше всего, если вы публикуете свой * полный * код или сокращенную версию, демонстрирующую такое же неправильное поведение. Эта конкретная проблема вряд ли была вызвана тем, что были бы раскрыты «строгими» или «предупреждениями», но чаще всего было бы лишнее и ненужное предложение, предлагающее добавить их и показать результаты. – Borodin

ответ

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); 
}; 

 


Update

Кстати, лучший способ просмотра сообщения HTTP, который HTTP::Message в соавт. построил для вас использовать 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 

который является именно то, что содержит ваш входной файл, и мы надеемся, что вы бы ожидать.