Заставьте тайм-аут работать для LWP :: UserAgent HTTPS - PullRequest
3 голосов
/ 22 февраля 2012

Решение

Как сообщил @limulus в ответе, который я принял, это была ошибка в Net::HTTPS версии 6.00.Всегда будьте осторожны со свежими .0 релизами.Вот соответствующая разница между ошибочной и фиксированной версией этого модуля:

D:\Opt\Perl512.32 :: diff lib\Net\HTTPS.pm site\lib\Net\HTTPS.pm
6c6
< $VERSION = "6.00";
---
> $VERSION = "6.02";
75,78c75,80
< # The underlying SSLeay classes fails to work if the socket is
< # placed in non-blocking mode.  This override of the blocking
< # method makes sure it stays the way it was created.
< sub blocking { }  # noop
---
> if ($SSL_SOCKET_CLASS eq "Net::SSL") {
>     # The underlying SSLeay classes fails to work if the socket is
>     # placed in non-blocking mode.  This override of the blocking
>     # method makes sure it stays the way it was created.
>     *blocking = sub { };
> }

Исходный вопрос

Релевантность: досадно видеть ваш клиентский блок HTTPS бесконечно, поскольку конечная точка соединения ненадежна.

Этот эксперимент легко настроить и воспроизвести дома.Вам просто нужны две вещи: тарпит для перехвата входящего клиента и скрипт на Perl.Тарпит можно настроить с помощью netcat:

nc -k -l localhost 9999 # on Linux, for multiple requests
nc -l -p 9999 localhost # on Cygwin, for one request only

Затем укажите сценарий на этот тарпит:

use strict;
use LWP::UserAgent;
use HTTP::Request::Common;

print 'LWP::UserAgent::VERSION  ', $LWP::UserAgent::VERSION, "\n";
print 'IO::Socket::SSL::VERSION ', $IO::Socket::SSL::VERSION, "\n";

my $ua = LWP::UserAgent->new( timeout => 5, keep_alive => 1 );
$ua->ssl_opts( timeout => 5, Timeout => 5 ); # Yes - see note below!
my $rsp = $ua->request( GET 'https://localhost:9999' );
if ( $rsp->is_success ) {
  print $rsp->as_string;
} else {
  die $rsp->status_line;
}

Что это будет делать?Хорошо, подключитесь к порту, открытому NetCat, а затем ... зависайте.Бесконечно.По крайней мере, с точки зрения времени разработчика.Я имею в виду, что это может истечь через десять минут или два часа, но я не проверял;указанное время ожидания не вступает в силу, не в Linux и не в Windows (Win32, не проверял Cygwin).

Используемые версии:

LWP::UserAgent::VERSION  6.02
IO::Socket::SSL::VERSION 1.44
# on Linux

LWP::UserAgent::VERSION  6.02
IO::Socket::SSL::VERSION 1.44
# on Win32

Теперь для timeout и Timeout параметры.Первый - это имя параметра для LWP :: UA , второй - имя для IO :: Socket :: SSL , используемого через LWP :: Protocol:: HTTPS .(Кстати, почему metacpan HTTPS? Ну, по крайней мере, это не тарпит.) Я как-то надеюсь передать эти параметры:)

Просто чтобы вы знали, keep_alive не имеет ничего дляделать с таймаутом не работает, я проверял это эмпирически.:)

В любом случае, прежде чем копать глубже, кто-нибудь знает, что здесь происходит и как заставить тайм-аут работать с HTTPS?Трудно поверить, что я первый, кто столкнулся с этим.

Ответы [ 3 ]

4 голосов
/ 20 апреля 2012

Это результат того, что модуль Net::HTTPS переопределяет метод blocking для IO::Socket с помощью noop.Обновление до последнего Net::HTTP пакета должно исправить это.

2 голосов
/ 22 февраля 2012

Параметры timeoutTimeout) применяются только к соединению - сколько секунд LWP::UserAgent будет ждать при подключении - они не предназначены для установки таймаута всей транзакции.

Вы захотите использовать Perl alarm с обработчиком $SIG{ALRM} для тайм-аута всей транзакции. См. perldoc -f alarm или perlipc.

local $SIG{ALRM} = sub { die "SSL timeout\n" };
my $ua = LWP::UserAgent->new( timeout => 5, keep_alive => 1 );
$ua->ssl_opts( timeout => 5, Timeout => 5 );

eval {
    alarm(10);
    my $rsp = $ua->request( GET 'https://localhost:9999' );
    if ( $rsp->is_success ) {
      print $rsp->as_string;
    } else {
      die $rsp->status_line;
    }
 };
 alarm(0);
 if ($@) {
     if ($@ =~ /SSL timeout/) {
         warn "request timed out";
     } else {
         die "error in request: $@";
     }
 }

(протестировано в Linux. Аварийные сигналы могут быть немного более опасными в Windows / Cygwin )

0 голосов
/ 26 марта 2012

Я задал этот вопрос на PerlMonks , и получил ответ о том, что:

Базовый IO :: Socket :: INET не поддерживает неблокирующие сокеты на Win32, поэтому неблокирующая IO :: Socket :: SSL не поддерживается на Win32, что также означает, что таймауты не работают (потому что они основаны на без блокировки). Смотри также http://www.perlmonks.org/?node_id=378675

http://cpansearch.perl.org/src/SULLR/IO-Socket-SSL-1.60/README.Win32

Сообщение PerlMonks, на которое указывалось, относится к 2004 году. Не уверен, что информация все еще применима; в конце концов, я видел тайм-аут работает в Windows, но не через SSL.

...