NAME

Mojo::UserAgent - Non-blocking I/O HTTP and WebSocket user agent

SYNOPSIS

use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;

# Say hello to the Unicode snowman with "Do Not Track" header
say $ua->get('www.☃.net?hello=there' => {DNT => 1})->res->body;

# Form POST with exception handling
my $tx = $ua->post('https://metacpan.org/search' => form => {q => 'mojo'});
if (my $res = $tx->success) { say $res->body }
else {
  my ($err, $code) = $tx->error;
  say $code ? "$code response: $err" : "Connection error: $err";
}

# Quick JSON API request with Basic authentication
say $ua->get('https://sri:s3cret@example.com/search.json?q=perl')
  ->res->json('/results/0/title');

# Extract data from HTML and XML resources
say $ua->get('www.perl.org')->res->dom->html->head->title->text;

# Scrape the latest headlines from a news site
say $ua->get('perlnews.org')->res->dom('h2 > a')->pluck('text')->shuffle;

# IPv6 PUT request with content
my $tx
  = $ua->put('[::1]:3000' => {'Content-Type' => 'text/plain'} => 'Hello!');

# Grab the latest Mojolicious release :)
$ua->max_redirects(5)->get('latest.mojolicio.us')
  ->res->content->asset->move_to('/Users/sri/mojo.tar.gz');

# TLS certificate authentication and JSON POST
my $tx = $ua->cert('tls.crt')->key('tls.key')
  ->post('https://example.com' => json => {top => 'secret'});

# Blocking parallel requests (does not work inside a running event loop)
my $delay = Mojo::IOLoop->delay;
for my $url ('mojolicio.us', 'cpan.org') {
  my $end = $delay->begin(0);
  $ua->get($url => sub {
    my ($ua, $tx) = @_;
    $end->($tx->res->dom->at('title')->text);
  });
}
my @titles = $delay->wait;

# Non-blocking parallel requests (does work inside a running event loop)
my $delay = Mojo::IOLoop->delay(sub {
  my ($delay, @titles) = @_;
  ...
});
for my $url ('mojolicio.us', 'cpan.org') {
  my $end = $delay->begin(0);
  $ua->get($url => sub {
    my ($ua, $tx) = @_;
    $end->($tx->res->dom->at('title')->text);
  });
}
$delay->wait unless Mojo::IOLoop->is_running;

# Non-blocking WebSocket connection sending and receiving JSON messages
$ua->websocket('ws://example.com/echo.json' => sub {
  my ($ua, $tx) = @_;
  say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
  $tx->on(json => sub {
    my ($tx, $hash) = @_;
    say "WebSocket message via JSON: $hash->{msg}";
    $tx->finish;
  });
  $tx->send({json => {msg => 'Hello World!'}});
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

DESCRIPTION

Mojo::UserAgent is a full featured non-blocking I/O HTTP and WebSocket user agent, with IPv6, TLS, SNI, IDNA, Comet (long polling), keep-alive, connection pooling, timeout, cookie, multipart, proxy, gzip compression and multiple event loop support.

For better scalability (epoll, kqueue) and to provide IPv6 as well as TLS support, the optional modules EV (4.0+), IO::Socket::IP (0.16+) and IO::Socket::SSL (1.75+) will be used automatically by Mojo::IOLoop if they are installed. Individual features can also be disabled with the MOJO_NO_IPV6 and MOJO_NO_TLS environment variables.

See Mojolicious::Guides::Cookbook for more.

EVENTS

Mojo::UserAgent inherits all events from Mojo::EventEmitter and can emit the following new ones.

error

$ua->on(error => sub {
  my ($ua, $err) = @_;
  ...
});

Emitted if an error occurs that can't be associated with a transaction.

$ua->on(error => sub {
  my ($ua, $err) = @_;
  say "This looks bad: $err";
});

start

$ua->on(start => sub {
  my ($ua, $tx) = @_;
  ...
});

Emitted whenever a new transaction is about to start, this includes automatically prepared proxy CONNECT requests and followed redirects.

$ua->on(start => sub {
  my ($ua, $tx) = @_;
  $tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
});

ATTRIBUTES

Mojo::UserAgent implements the following attributes.

ca

my $ca = $ua->ca;
$ua    = $ua->ca('/etc/tls/ca.crt');

Path to TLS certificate authority file, defaults to the value of the MOJO_CA_FILE environment variable. Also activates hostname verification.

# Show certificate authorities for debugging
IO::Socket::SSL::set_defaults(
  SSL_verify_callback => sub { say "Authority: $_[2]" and return $_[0] });

cert

my $cert = $ua->cert;
$ua      = $ua->cert('/etc/tls/client.crt');

Path to TLS certificate file, defaults to the value of the MOJO_CERT_FILE environment variable.

connect_timeout

my $timeout = $ua->connect_timeout;
$ua         = $ua->connect_timeout(5);

Maximum amount of time in seconds establishing a connection may take before getting canceled, defaults to the value of the MOJO_CONNECT_TIMEOUT environment variable or 10.

my $cookie_jar = $ua->cookie_jar;
$ua            = $ua->cookie_jar(Mojo::UserAgent::CookieJar->new);

Cookie jar to use for this user agents requests, defaults to a Mojo::UserAgent::CookieJar object.

# Disable cookie jar
$ua->cookie_jar(0);

http_proxy

my $proxy = $ua->http_proxy;
$ua       = $ua->http_proxy('http://sri:secret@127.0.0.1:8080');

Proxy server to use for HTTP and WebSocket requests.

https_proxy

my $proxy = $ua->https_proxy;
$ua       = $ua->https_proxy('http://sri:secret@127.0.0.1:8080');

Proxy server to use for HTTPS and WebSocket requests.

inactivity_timeout

my $timeout = $ua->inactivity_timeout;
$ua         = $ua->inactivity_timeout(15);

Maximum amount of time in seconds a connection can be inactive before getting closed, defaults to the value of the MOJO_INACTIVITY_TIMEOUT environment variable or 20. Setting the value to 0 will allow connections to be inactive indefinitely.

ioloop

my $loop = $ua->ioloop;
$ua      = $ua->ioloop(Mojo::IOLoop->new);

Event loop object to use for blocking I/O operations, defaults to a Mojo::IOLoop object.

key

my $key = $ua->key;
$ua     = $ua->key('/etc/tls/client.crt');

Path to TLS key file, defaults to the value of the MOJO_KEY_FILE environment variable.

local_address

my $address = $ua->local_address;
$ua         = $ua->local_address('127.0.0.1');

Local address to bind to.

max_connections

my $max = $ua->max_connections;
$ua     = $ua->max_connections(5);

Maximum number of keep-alive connections that the user agent will retain before it starts closing the oldest cached ones, defaults to 5.

max_redirects

my $max = $ua->max_redirects;
$ua     = $ua->max_redirects(3);

Maximum number of redirects the user agent will follow before it fails, defaults to the value of the MOJO_MAX_REDIRECTS environment variable or 0.

name

my $name = $ua->name;
$ua      = $ua->name('Mojolicious');

Value for User-Agent request header, defaults to Mojolicious (Perl).

no_proxy

my $no_proxy = $ua->no_proxy;
$ua          = $ua->no_proxy([qw(localhost intranet.mojolicio.us)]);

Domains that don't require a proxy server to be used.

request_timeout

my $timeout = $ua->request_timeout;
$ua         = $ua->request_timeout(5);

Maximum amount of time in seconds establishing a connection, sending the request and receiving a whole response may take before getting canceled, defaults to the value of the MOJO_REQUEST_TIMEOUT environment variable or 0. Setting the value to 0 will allow the user agent to wait indefinitely. The timeout will reset for every followed redirect.

# Total limit of 5 seconds, of which 3 seconds may be spent connecting
$ua->max_redirects(0)->connect_timeout(3)->request_timeout(5);

transactor

my $t = $ua->transactor;
$ua   = $ua->transactor(Mojo::UserAgent::Transactor->new);

Transaction builder, defaults to a Mojo::UserAgent::Transactor object.

METHODS

Mojo::UserAgent inherits all methods from Mojo::EventEmitter and implements the following new ones.

app

my $app = Mojo::UserAgent->app;
          Mojo::UserAgent->app(MyApp->new);
my $app = $ua->app;
$ua     = $ua->app(MyApp->new);

Application relative URLs will be processed with, instance specific applications override the global default.

# Introspect
say $ua->app->secret;

# Change log level
$ua->app->log->level('fatal');

# Change application behavior
$ua->app->defaults(testing => 'oh yea!');

app_url

my $url = $ua->app_url;
my $url = $ua->app_url('http');
my $url = $ua->app_url('https');

Get absolute Mojo::URL object for app and switch protocol if necessary.

# Port currently used for processing relative URLs
say $ua->app_url->port;

build_tx

my $tx = $ua->build_tx(GET => 'example.com');
my $tx = $ua->build_tx(PUT => 'http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->build_tx(
  PUT => 'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->build_tx(
  PUT => 'http://example.com' => {DNT => 1} => json => {a => 'b'});

Generate Mojo::Transaction::HTTP object with "tx" in Mojo::UserAgent::Transactor.

# Request with cookie
my $tx = $ua->build_tx(GET => 'example.com');
$tx->req->cookies({name => 'foo', value => 'bar'});
$ua->start($tx);

build_websocket_tx

my $tx = $ua->build_websocket_tx('ws://example.com');
my $tx =
  $ua->build_websocket_tx('ws://example.com' => {DNT => 1} => ['v1.proto']);

Generate Mojo::Transaction::HTTP object with "websocket" in Mojo::UserAgent::Transactor.

delete

my $tx = $ua->delete('example.com');
my $tx = $ua->delete('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->delete(
  'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->delete(
  'http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking DELETE request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->delete('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

detect_proxy

$ua = $ua->detect_proxy;

Check environment variables HTTP_PROXY, http_proxy, HTTPS_PROXY, https_proxy, NO_PROXY and no_proxy for proxy information. Automatic proxy detection can be enabled with the MOJO_PROXY environment variable.

get

my $tx = $ua->get('example.com');
my $tx = $ua->get('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->get('http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->get('http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking GET request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->get('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
my $tx = $ua->head('example.com');
my $tx = $ua->head('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->head(
  'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->head(
  'http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking HEAD request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->head('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

need_proxy

my $success = $ua->need_proxy('intranet.example.com');

Check if request for domain would use a proxy server.

options

my $tx = $ua->options('example.com');
my $tx = $ua->options('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->options(
  'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->options(
  'http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking OPTIONS request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->options('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

patch

my $tx = $ua->patch('example.com');
my $tx = $ua->patch('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->patch(
  'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->patch(
  'http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking PATCH request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->patch('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

post

my $tx = $ua->post('example.com');
my $tx = $ua->post('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->post(
  'http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->post(
  'http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking POST request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->post('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

put

my $tx = $ua->put('example.com');
my $tx = $ua->put('http://example.com' => {DNT => 1} => 'Hi!');
my $tx = $ua->put('http://example.com' => {DNT => 1} => form => {a => 'b'});
my $tx = $ua->put('http://example.com' => {DNT => 1} => json => {a => 'b'});

Perform blocking PUT request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->put('http://example.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

start

my $tx = $ua->start(Mojo::Transaction::HTTP->new);

Perform blocking request. You can also append a callback to perform requests non-blocking.

my $tx = $ua->build_tx(GET => 'http://example.com');
$ua->start($tx => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

websocket

$ua->websocket('ws://example.com' => sub {...});
$ua->websocket(
  'ws://example.com' => {DNT => 1} => ['v1.proto'] => sub {...});

Open a non-blocking WebSocket connection with transparent handshake, takes the same arguments as "websocket" in Mojo::UserAgent::Transactor. The callback will receive either a Mojo::Transaction::WebSocket or Mojo::Transaction::HTTP object.

$ua->websocket('ws://example.com/echo' => sub {
  my ($ua, $tx) = @_;
  say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
  $tx->on(finish => sub {
    my ($tx, $code, $reason) = @_;
    say "WebSocket closed with status $code.";
  });
  $tx->on(message => sub {
    my ($tx, $msg) = @_;
    say "WebSocket message: $msg";
    $tx->finish;
  });
  $tx->send('Hi!');
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

DEBUGGING

You can set the MOJO_USERAGENT_DEBUG environment variable to get some advanced diagnostics information printed to STDERR.

MOJO_USERAGENT_DEBUG=1

SEE ALSO

Mojolicious, Mojolicious::Guides, http://mojolicio.us.