AnyEvent-HTTP-LWP-UserAgent
view release on metacpan or search on metacpan
lib/AnyEvent/HTTP/LWP/UserAgent.pm view on Meta::CPAN
}
$headers->header($header => $value);
}
# special AnyEvent::HTTP codes
if ($code >= 590 && $code <= 599) {
# make LWP-compatible error in the case of timeout
if ($message =~ /timed/ && $code == 599) {
$d = '500 read timeout';
$code = 500;
} elsif (!defined($d) || $d =~ /^\s*$/) {
$d = $message;
}
}
$out_req = HTTP::Response->new($code, $message, $headers, $d);
$self->run_handlers(response_header => $out_req);
return 1;
};
$args->{on_header} = sub {
my ($h) = @_;
$header_init->(undef, $h);
};
http_request $method => $$uri_ref, %$args, sub {
my ($d, $h) = @_;
$d = $content if $content ne '';
$header_init->($d, $h) if ! defined $out_req;
$out_req->content($d) if defined $d;
close($fh) or $cv->croak("Can't write to '$arg': $!") if defined ($fh);
if(defined($d) && length($d)) {
# from LWP::Protocol
my %skip_h;
for my $h ($self->handlers('response_data', $out_req)) {
next if $skip_h{$h};
unless ($h->{callback}->($out_req, $self, $h, $d)) {
# XXX remove from $response->{handlers}{response_data} if present
$skip_h{$h}++;
}
}
}
$out_req->request($in_req);
# cookie_jar will be set by the handler
$self->run_handlers(response_done => $out_req);
$cv->send($out_req);
};
return $cv;
}
sub simple_request {
return shift->simple_request_async(@_)->recv;
}
sub get_async {
require HTTP::Request::Common;
my($self, @parameters) = @_;
my @suff = $self->_process_colonic_headers(\@parameters,1);
return $self->request_async( HTTP::Request::Common::GET( @parameters ), @suff );
}
sub post_async {
require HTTP::Request::Common;
my($self, @parameters) = @_;
my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1));
return $self->request_async( HTTP::Request::Common::POST( @parameters ), @suff );
}
sub head_async {
require HTTP::Request::Common;
my($self, @parameters) = @_;
my @suff = $self->_process_colonic_headers(\@parameters,1);
return $self->request_async( HTTP::Request::Common::HEAD( @parameters ), @suff );
}
sub put_async {
require HTTP::Request::Common;
my($self, @parameters) = @_;
my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1));
return $self->request_async( HTTP::Request::Common::PUT( @parameters ), @suff );
}
sub delete_async {
require HTTP::Request::Common;
my($self, @parameters) = @_;
my @suff = $self->_process_colonic_headers(\@parameters,1);
return $self->request_async( HTTP::Request::Common::DELETE( @parameters ), @suff );
}
sub get {
return shift->get_async(@_)->recv;
}
sub post {
return shift->post_async(@_)->recv;
}
sub head {
return shift->head_async(@_)->recv;
}
sub put {
return shift->put_async(@_)->recv;
}
sub delete {
return shift->delete_async(@_)->recv;
}
sub lwp_request2anyevent_request {
my ($self, $in_req) = @_;
my $method = $in_req->method;
my $uri = $in_req->uri->as_string;
if ($self->cookie_jar) {
$self->cookie_jar->add_cookie_header($in_req);
}
my $in_headers = $in_req->headers;
my $out_headers = {};
$in_headers->scan( sub {
my ($header, $value) = @_;
$out_headers->{$header} = $value;
} );
# if we will use some code like
# local $AnyEvent::HTTP::USERAGENT = $useragent;
# in simple_request, it will not work properly in redirects
$out_headers->{'User-Agent'} = $self->agent;
my $body;
if(ref($in_req->content) eq 'CODE') {
# Minimum coderef support
# TODO: Add chunked transfer but maybe necessary to modify AnyEvent::HTTP itself
$body = '';
while(my $ret = $in_req->content->()) {
$body .= $ret;
last if $ret eq '';
}
} else {
$body = $in_req->content;
}
my %args = (
headers => $out_headers,
body => $body,
lib/AnyEvent/HTTP/LWP/UserAgent.pm view on Meta::CPAN
{
return shift->request_async(@_)->recv;
}
1;
__END__
=pod
=head1 NAME
AnyEvent::HTTP::LWP::UserAgent - LWP::UserAgent interface but works using AnyEvent::HTTP
=head1 VERSION
version 0.10
=head1 SYNOPSIS
use AnyEvent::HTTP::LWP::UserAgent;
use Coro;
my $ua = AnyEvent::HTTP::LWP::UserAgent->new;
my @urls = (...);
my @coro = map {
my $url = $_;
async {
my $r = $ua->get($url);
print "url $url, content " . $r->content . "\n";
}
} @urls;
$_->join for @coro;
# Or without Coro
use AnyEvent::HTTP::LWP::UserAgent;
use AnyEvent;
my $ua = AnyEvent::HTTP::LWP::UserAgent->new;
my @urls = (...);
my $cv = AE::cv;
$cv->begin;
foreach my $url (@urls) {
$cv->begin;
$ua->get_async($url)->cb(sub {
my $r = shift->recv;
print "url $url, content " . $r->content . "\n";
$cv->end;
});
}
$cv->end;
$cv->recv;
=head1 DESCRIPTION
When you use Coro you have a choice: you can use L<Coro::LWP> or L<AnyEvent::HTTP>
(if you want to make asynchronous HTTP requests).
If you use Coro::LWP, some modules may work incorrectly (for example Cache::Memcached)
because of global change of IO::Socket behavior.
AnyEvent::HTTP uses different programming interface, so you must change more of your
old code with LWP::UserAgent (and HTTP::Request and so on), if you want to make
asynchronous code.
AnyEvent::HTTP::LWP::UserAgent uses AnyEvent::HTTP inside but have an interface of
LWP::UserAgent.
You can safely use this module in Coro environment (and possibly in AnyEvent too).
In plain AnyEvent, you may use _async methods.
They don't make blocking wait but return condition variable.
So, you can avoid recursive blocking wait error.
=head1 SOME METHODS
=over
=item $ua->conn_cache
=item $ua->conn_cache($cache_obj)
New versions of C<AnyEvent::HTTP> supports HTTP(S)/1.1 persistent connection, so
you can control it in C<AnyEvent::HTTP::LWP::UserAgent> using C<conn_cache> method.
If you set C<conn_cache> (as C<LWP::ConnCache> object) then
C<Anyevent::HTTP::LWP::UserAgent> makes two things. In first it sets global variable
C<$AnyEvent::HTTP::ACTIVE> as you setted C<total_capacity> for C<conn_cache> (be careful:
this have a global consequences, not local). And in the second C<AnyEvent::HTTP::LWP::UserAgent>
will create persistent connections if your C<$ua> have C<conn_cache> (local propery of C<$ua>).
But you can't use remainder methods of your C<conn_cache>, all connections will
contains in C<AnyEvent::HTTP>. C<$AnyEvent::HTTP::ACTIVE> sets only when you set
C<conn_cache> for C<$ua>. If you just change C<total_capacity> of old C<conn_cache>
it will not change anything.
=back
=head1 ASYNC METHODS
The following methods are async version of corresponding methods w/o _async suffix.
Parameters are identical as originals.
However, return value becomes condition variable.
You can use it in a synchronous way by blocking wait
$ua->simple_request_async(@args)->recv
or in an asynchronous way, also.
$ua->simple_request_async(@args)->cb(sub { ... });
=over 4
=item simple_request_async
=item request_async
=item get_async
=item post_async
=item head_async
=item put_async
( run in 0.831 second using v1.01-cache-2.11-cpan-39bf76dae61 )