Почему не устанавливается agent() при использовании LWP::Parallel::UserAgent?

При взгляде на UserAgent.pm он кажется неопределенным. По крайней мере, насколько я знаю, не определено, когда подпрограмма доберется до этой части, хотя я явно устанавливаю это с помощью $pua->agent(). Это ошибка? Еще есть init_header(), но когда я попробовал $pua->request->init_header(), он тоже не установился.

#!/bin/perl

use LWP::Parallel::UserAgent;

my $ua_string =
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36";

my $url  = "http://www.example1.com";
my $url2 = "http://www.example2.com";

my $reqs = [
    HTTP::Request->new( 'GET', $url ),
    HTTP::Request->new( 'GET', $url2 )
];

my ( $req, $res );

my $pua = LWP::Parallel::UserAgent->new();

$pua->agent($ua_string);

foreach $req ( @$reqs ) {
    $pua->register( $req );
}

my $entries = $pua->wait();
foreach ( keys %$entries ) {
    $res = $entries->{$_}->response;
    my $r = $res;
    my @redirects;
    while ( $r ) {
        $res = $r;
        $r   = $r->previous;
        push( @redirects, $res ) if $r;
    }
}

person Lukas Nelson    schedule 25.12.2016    source источник
comment
Этот код работает нормально. Не могли бы вы опубликовать сообщение об ошибке, которое вы получаете? Также какие версии LWP и LWP::Parallel::UserAgent вы используете.   -  person Schwern    schedule 26.12.2016
comment
Последняя версия. Он не устанавливает для меня строку User-Agent. Он работает нормально, но не устанавливает значение.   -  person Lukas Nelson    schedule 26.12.2016
comment
Если вы нажмете print "The user-agent is: ".$pua->agent сразу после установки, что вы получите?   -  person Schwern    schedule 26.12.2016
comment
Я просматриваю свои лог-файлы. Его нет в моем лог-файле. Если я войду и вручную отредактирую Perl-модуль UserAgent.pm и установлю там переменную агента, он сработает и появится в моем журнале. Но не при использовании $pua-›agent().   -  person Lukas Nelson    schedule 26.12.2016
comment
Когда вы говорите, что этого нет в моем файле журнала, вы имеете в виду, что получаете The user-agent is: или просто ничего не получаете? Если вы ничего не получите, то эта линия просто никогда не будет запущена. Опять же, поскольку вы не используете strict и warnings, я подозреваю, что на самом деле у вас опечатка и вы передаете undef. Попробуйте напечатать $ua_string. Также включите строгое и предупреждения. Или вы используете чью-то взломанную версию LWP::UserAgent (поскольку вы, скорее всего, редактируете модуль). Попробуйте сравнить его со свежей загрузкой.   -  person Schwern    schedule 26.12.2016
comment
Установленная версия не взломана и не модифицирована. Я добавил строгость и отсутствие ошибок или предупреждений в коде, который я разместил. Он не устанавливается в моем журнале Apache.   -  person Lukas Nelson    schedule 26.12.2016


Ответы (1)


Извините за путаницу, $pua->agent установлен, но LWP::Parallel::UserAgent его не использует. Это давняя ошибка в LWP::Parallel::UserAgent.

LWP::Parallel::UserAgent является подклассом LWP::UserAgent, но плохо себя ведет. Вместо использования методов доступа он захватывает внутренние поля и предполагает, что агент будет храниться в $self->{agent}. Может когда-то и было, но уже нет.

Ваша конкретная проблема заключается в LWP::Parallel::UserAgent::init_request(), начиная со строки 1506. .

# Extract fields that will be used below
my ($agent, $from, $timeout, $cookie_jar,
    $use_eval, $parse_head, $max_size, $nonblock) =
  @{$self}{qw(agent from timeout cookie_jar
              use_eval parse_head max_size nonblock)};

Это предполагает, что пользовательский агент хранится в $self->{agent}. Это не так. Вместо этого следует сделать что-то подобное для вызова каждого метода доступа по очереди.

my %fields;
my @fields = qw(agent from timeout cookie_jar parse_head max_size);
for my $field (@fields) {
    $fields{$field} = $self->$field();
}

Или просто используйте аксессоры напрямую. Это будет использовать задокументированный интерфейс для LWP.

nonblock и use_eval являются особыми случаями. Это не поля LWP::UserAgent, они были добавлены LWP::Parallel. Для use_eval нет метода доступа. Есть LWP::Parallel::UserAgent::nonblock(), но это всего лишь сеттер. Я не думаю, что это сделано намеренно.

Поскольку он не определяет аксессор для use_eval и должен его добавить. И вы можете исправить nonblock, чтобы всегда возвращать свое значение.

sub nonblock {
    my $self = shift;
    $self->{'nonblock'} = $_[0] if defined $_[0];
    return $self->{nonblock};
}

LWP::Parallel::UserAgent активно поддерживается, вы должны отправить отчет об ошибке и, возможно, патч.

person Schwern    schedule 25.12.2016
comment
Я получаю libwww-perl/6.13, когда добавляю строку. Это также должно отображаться в моих журналах Apache. Это не так, это просто -. Я установил LWP::Parallel::UserAgent из исходников, он не изменен. Он не подберет строку agent(). - person Lukas Nelson; 26.12.2016
comment
Я установил libwww-perl-6.15 и ParallelUserAgent-2.62 из исходников, и никаких изменений. $pua-›agent() не отправляется при установлении соединения. Задается в программе, но не отправляется при подключении. - person Lukas Nelson; 26.12.2016
comment
Вы не показываете нам настоящий код, возможно, у вас опечатка. Включите строгость и предупреждения, устраните все проблемы, а потом посмотрите, что будет. - person Schwern; 26.12.2016
comment
Вот и вся программа. Я запускаю именно то, что я опубликовал. - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Обратите внимание, что Perl, который вы запускаете в командной строке, и Perl, который работает в Apache, особенно если это mod_perl, не обязательно одно и то же. Если это так, они не обязательно видят одни и те же модули. Попробуйте print $INC{"LWP/Parallel/UserAgent.pm"} и print $INC{"LWP/UserAgent.pm"} и посмотрите, что вы на самом деле загружаете. - person Schwern; 26.12.2016
comment
Я запускаю командную строку perl, а не apache mod-perl, которая не установлена. У меня строгие предупреждения поставили. Нет ни одного с кодом, который я разместил. Этот код НЕ отправляет строку User-Agent при подключении к ЛЮБОМУ веб-серверу. Пробовал два разных хоста. Код работает отлично без каких-либо ошибок, поэтому мне интересно, связана ли проблема с самим модулем. - person Lukas Nelson; 26.12.2016
comment
@LukasNelson У меня те же версии, и все работает нормально. Это что-то на вашей стороне. - person Schwern; 26.12.2016
comment
Это не с моей стороны. Переменная $agent в модуле UserAgent.pm не определена. Если я добавлю значение, такое же значение, как в моей программе, то оно работает. Где-то есть обрыв связи. - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Если $agent не определено в LWP::UserAgent::new() (т.е. вы его не передали), он использует $class->_agent, который равен sub _agent { "libwww-perl/$LWP::VERSION" }. См. строку 112. $self->agent(defined($agent) ? $agent : $class->_agent) if defined($agent) || !$def_headers || !$def_headers->header("User-Agent"); - person Schwern; 26.12.2016
comment
Я использую LWP::Parallel::UserAgent::new(), а не LWP::UserAgent::new(). - person Lukas Nelson; 26.12.2016
comment
@LukasNelson LWP::Parallel::UserAgent является подклассом LWP::UserAgent, хотя и требует некоторых вольностей. Вы когда-нибудь пробовали print $pua->agent? - person Schwern; 26.12.2016
comment
И если он не определен, он должен использовать значение по умолчанию, которое будет libwww-perl-6.15 в качестве пользовательского агента или любой другой установленной версии. Однако даже значение по умолчанию не определяется. Где-то что-то сломано. Я не думаю, что это код, я думаю, что это модуль. Это, или я не устанавливаю это должным образом. И если я не устанавливаю его правильно, альтернативой является установка ваших собственных заголовков. Тем не менее, не сработает ли $pua-›request-›init_header('New-Header: New Header')? - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Вы когда-нибудь пробовали print $pua->agent? Я предполагаю, что это работает, но заголовок на самом деле не устанавливается. Верно? - person Schwern; 26.12.2016
comment
Да, печатает версию, если она не определена из программы. Я полностью удалил строку, так что $pua-›agent() не устанавливается. Затем он должен использовать значение по умолчанию. Этого тоже не происходит. По умолчанию в моем файле журнала должен отображаться libwww-perl-6.15, но он показывает -. - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Я нашел проблему. Это ошибка в LWP::Parallel::UserAgent. - person Schwern; 26.12.2016
comment
Я думал, что это может быть ошибка. - person Lukas Nelson; 26.12.2016
comment
Спасибо, что нашли первопричину. Похоже, что кто-то отправил отчет об ошибке 2 года назад. Поскольку проблема осталась нерешенной, я думаю, что она находится в списке TODO с низким приоритетом. - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Я думаю, что если указать основную причину, автору будет намного проще ее исправить. - person Schwern; 26.12.2016
comment
В начале файла есть запись Parallel::UserAgent my %fields = ( ... ). Я добавил туда агента. Это должно исправить $pua-›agent(). Верно? Однако его нужно вытащить и куда-то присвоить. Поэтому я добавил субагента { my $self = shift; $self-›{'agent'} = $_[0], если определено $_[0]; вернуть $self-›{агент}; }. И это работает. УРА!!!!!!! - person Lukas Nelson; 26.12.2016
comment
@LukasNelson Тот %fields, который вы нашли, управляет автоматической генерацией средств доступа. Это может сработать, но я боюсь, что вы переопределяете существующий метод доступа LWP::UserAgent::agent() и то, где он хранит свои данные. Это, вероятно, приведет к другим тонким ошибкам. Реальное решение состоит в том, чтобы изменить LWP::Parallel::UserAgent, чтобы не делать предположений о внутреннем устройстве объекта LWP::UserAgent. - person Schwern; 26.12.2016