IO-Lambda
view release on metacpan or search on metacpan
lib/IO/Lambda/HTTP/Client.pm view on Meta::CPAN
package IO::Lambda::HTTP::Client;
use vars qw(@ISA @EXPORT_OK $DEBUG);
@ISA = qw(Exporter);
@EXPORT_OK = qw(http_request);
our $DEBUG = $IO::Lambda::DEBUG{http} || 0;
use strict;
use warnings;
use Socket;
use Errno;
use Exporter;
use IO::Socket;
use HTTP::Response;
use IO::Lambda qw(:lambda :stream);
use IO::Lambda::Socket qw(connect);
use Time::HiRes qw(time);
sub http_request(&)
{
__PACKAGE__-> new(context)->
condition(shift, \&http_request, 'http_request')
}
sub new
{
my ( $class, $req, %options) = @_;
my $self = bless {}, $class;
$self-> {deadline} = $options{timeout} + time if defined $options{timeout};
$self-> {deadline} = $options{deadline} if defined $options{deadline};
$self-> {max_redirect} = defined($options{max_redirect}) ? $options{max_redirect} : 7;
delete @options{qw(deadline timeout max_redirect)};
$self-> {$_} = $options{$_} for keys %options;
my %headers;
$headers{'User-Agent'} = "perl/IO-Lambda-HTTP v$IO::Lambda::VERSION";
if ( $self-> {keep_alive}) {
unless ( $self-> {conn_cache}) {
require LWP::ConnCache;
$self-> {conn_cache} = LWP::ConnCache-> new;
}
unless ( $req-> protocol) {
$req-> protocol('HTTP/1.1');
}
$headers{Host} = $req-> uri-> host;
$headers{Connection} = 'Keep-Alive';
$headers{'Keep-Alive'} = 300;
}
require IO::Lambda::DNS if $self-> {async_dns};
my $h = $req-> headers;
while ( my ($k, $v) = each %headers) {
$h-> header($k, $v) unless defined $h-> header($k);
}
if ( $options{cookie_jar} //= {} ) {
if ( ref($options{cookie_jar}) eq 'HASH') {
require HTTP::Cookies;
$options{cookie_jar} = HTTP::Cookies->new(%{$options{cookie_jar}});
}
$self->{cookie_jar} = $options{cookie_jar};
}
return $self-> handle_redirect( $req);
}
# HTTP::Response features methods base() and request() that we need to set as well
sub finalize_response
{
my ( $self, $req, $response) = @_;
return $response;
}
sub redirect
{
my ( $self, $location, $req) = @_;
return URI-> new_abs( $location, $req-> uri);
}
# reissue the request, if necessary, because of 30X or 401 errors
sub handle_redirect
{
my ( $self, $req) = @_;
my $was_redirected = 0;
my $was_failed_auth = 0;
my $auth = $self-> {auth};
lambda {
my $method;
if ( $auth) {
# create fake response for protocol initiation, -- but just once
my $x = HTTP::Response-> new;
$x-> headers-> header('WWW-Authenticate', split(',', $auth));
$method = $self-> get_authenticator( $req, $x);
lib/IO/Lambda/HTTP/Client.pm view on Meta::CPAN
=head1 API
=over
=item http_request $HTTP::Request -> $HTTP::Response
C<http_request> is a lambda condition that accepts C<HTTP::Request> object in
the context. Returns either a C<HTTP::Response> object on success, or error
string otherwise.
=item new $HTTP::Request :: () -> $HTTP::Response
Stores C<HTTP::Request> object and returns a new lambda that will finish when
the associated request completes. The lambda will return either a
C<HTTP::Response> object on success, or an error string otherwise.
=back
=head1 OPTIONS
=over
=item async_dns BOOLEAN
If set, hostname will be resolved with L<IO::Lambda::DNS> using asynchronous
capabilities of L<Net::DNS>. Note that this method won't be able to account for
non-DNS (/etc/hosts, NIS) host names.
If unset (default), hostnames will be resolved in a blocking manner.
=item auth $AUTH
Normally, a request is sent without any authentication. If the request returns
error 401, then all available methods of authentication are tried. If the type
of authentication that shall be accepted by the remote is known in advance, the
non-authenticated request stage can be skipped altogether by explicitly setting
the C<auth> option:
username => 'user',
password => 'pass',
auth => 'Basic',
=item conn_cache $LWP::ConnCache = undef
The requestor can optionally use a C<LWP::ConnCache> object to reuse
connections on per-host per-port basis. Desired for HTTP/1.1. Required for the
NTLM/Negotiate authentication. See L<LWP::ConnCache> for details.
=item cookie_jar $HTTP::Cookies = {}
The requestor can optionally use a shared C<HTTP::Cookies> object to support cookies.
If not set, a local cookie jar is created an used fo reventual redirects. To disable that,
set C<cookie_jar> to 0. See L<HTTP::Cookies> for details.
=item deadline SECONDS = undef
Aborts a request and returns C<'timeout'> string as an error if the request is
not finished before the deadline (in epoch seconds). If undef, timeout never
occurs.
=item keep_alive BOOLEAN
If set, all incoming request objects are silently converted use HTTP/1.1, and
connections are automatically reused. Same as combination of the following:
$req-> protocol('HTTP/1.1');
$req-> headers-> header( Host => $req-> uri-> host);
new( $req, conn_cache => LWP::ConnCache-> new);
=item max_redirect NUM = 7
Maximum allowed redirects. If 0, no redirection attemps are made.
=item preferred_auth $AUTH|%AUTH
Sets list of preferred authentication methods, that is used in selection of the
authentication method when the remote server supports several. When the value
is a string, then the given method is tried first, and only then all other
available methods. When it is a hash, the hash values are treated as weight
factors, such as, the method with the greatest weight is tried first. Negative
values prevent the corresponding methods from being tried.
# try basic and whatever else
preferred_auth => 'Basic',
# try basic and never ntlm
preferred_auth => {
Basic => 1,
NTLM => -1,
},
Note that the current implementation does not provide re-trying of
authentication if a method, or combination of username and password fails.
When at least one method is declared by the remote as supported, and was tried,
and subsequently failed, no further authentication retries are made, and the
request is reported as failed.
=item proxy HOSTNAME | [ HOSTNAME, PORT ]
If set, HOSTNAME (or HOSTNAME and PORT tuple) is used as HTTP proxy.
If set to undef, proxy is not used.
If unset, the proxy is set automatically after content of environment variables
C<all_proxy>, C<http_proxy>, C<https_proxy>, C<no_proxy>.
=item timeout SECONDS = undef
Maximum allowed time the request can take. If undef, no timeouts occur.
=back
=head1 BUGS
Non-blocking connects, and hence the module, don't work on win32 on perl5.8.X
due to under-implementation in ext/IO.xs. They do work on 5.10 however.
=head1 SEE ALSO
L<IO::Lambda>, L<HTTP::Request>, L<HTTP::Response>
=head1 AUTHOR
( run in 1.528 second using v1.01-cache-2.11-cpan-39bf76dae61 )