App-Pod
view release on metacpan or search on metacpan
t/cpan/Mojo2/UserAgent.pm view on Meta::CPAN
# Corrupted connection
return $self->_remove( $id ) unless my $tx = $self->{connections}{$id}{tx};
warn term_escape "-- Client <<< Server (@{[_url($tx)]})\n$chunk\n" if DEBUG;
$tx->client_read( $chunk );
$self->_finish( $id ) if $tx->is_finished;
}
sub _redirect {
my ( $self, $c, $old ) = @_;
return undef unless my $new = $self->transactor->redirect( $old );
return undef unless @{ $old->redirects } < $self->max_redirects;
return $self->_start( $c->{ioloop}, $new, delete $c->{cb} );
}
sub _remove {
my ( $self, $id ) = @_;
my $c = delete $self->{connections}{$id};
$self->_dequeue( $c->{ioloop}, $id );
$c->{ioloop}->remove( $id );
}
sub _reuse {
my ( $self, $id, $close ) = @_;
# Connection close
my $c = $self->{connections}{$id};
my $tx = delete $c->{tx};
my $max = $self->max_connections;
return $self->_remove( $id )
if $close || !$tx || !$max || !$tx->keep_alive || $tx->error;
# Keep connection alive
my $queue = $self->{queue}{ $c->{ioloop} } //= [];
$self->_remove( shift( @$queue )->[1] ) while @$queue && @$queue >= $max;
push @$queue, [ join( ':', $self->transactor->endpoint( $tx ) ), $id ];
}
sub _start {
my ( $self, $loop, $tx, $cb ) = @_;
# Application server
$self->emit( prepare => $tx );
my $url = $tx->req->url;
if ( !$url->is_abs && ( my $server = $self->server ) ) {
my $base = $loop == $self->ioloop ? $server->url : $server->nb_url;
$url->scheme( $base->scheme )->host( $base->host )->port( $base->port );
}
$_->prepare( $tx ) for $self->proxy, $self->cookie_jar;
my $max = $self->max_response_size;
$tx->res->max_message_size( $max ) if defined $max;
$self->emit( start => $tx );
# Allow test servers sharing the same event loop to clean up connections
!$loop->next_tick( sub { } ) and $loop->one_tick unless $loop->is_running;
return undef unless my $id = $self->_connection( $loop, $tx, $cb );
if ( my $t = $self->request_timeout ) {
weaken $self;
$self->{connections}{$id}{timeout} ||=
$loop->timer( $t => sub { $self->_error( $id, 'Request timeout' ) } );
}
return $id;
}
sub _url { shift->req->url->to_abs }
sub _write {
my ( $self, $id ) = @_;
# Protect from resume event recursion
my $c = $self->{connections}{$id};
return if !( my $tx = $c->{tx} ) || $c->{writing};
local $c->{writing} = 1;
my $chunk = $tx->client_write;
warn term_escape "-- Client >>> Server (@{[_url($tx)]})\n$chunk\n" if DEBUG;
return unless length $chunk;
weaken $self;
$c->{ioloop}->stream( $id )
->write( $chunk => sub { $self && $self->_write( $id ) } );
}
1;
=encoding utf8
=head1 NAME
Mojo::UserAgent - Non-blocking I/O HTTP and WebSocket user agent
=head1 SYNOPSIS
use Mojo::UserAgent;
# Fine grained response handling (dies on connection errors)
my $ua = Mojo::UserAgent->new;
my $res = $ua->get('docs.mojolicious.org')->result;
if ($res->is_success) { say $res->body }
elsif ($res->is_error) { say $res->message }
elsif ($res->code == 301) { say $res->headers->location }
else { say 'Whatever...' }
# Say hello to the Unicode snowman and include an Accept header
say $ua->get('www.â.net?hello=there' => {Accept => '*/*'})->result->body;
# Extract data from HTML and XML resources with CSS selectors
say $ua->get('www.perl.org')->result->dom->at('title')->text;
# Scrape the latest headlines from a news site
say $ua->get('blogs.perl.org')->result->dom->find('h2 > a')->map('text')->join("\n");
# IPv6 PUT request with Content-Type header and content
my $tx = $ua->put('[::1]:3000' => {'Content-Type' => 'text/plain'} => 'Hi!');
# Quick JSON API request with Basic authentication
my $url = Mojo::URL->new('https://example.com/test.json')->userinfo('sri:â');
my $value = $ua->get($url)->result->json;
# JSON POST (application/json) with TLS certificate authentication
( run in 1.206 second using v1.01-cache-2.11-cpan-39bf76dae61 )