Mojolicious
view release on metacpan or search on metacpan
lib/Mojolicious/Guides/Cookbook.pod view on Meta::CPAN
$w = AE::timer 3, 0, sub {
$c->render(text => 'Delayed by 3 seconds!');
undef $w;
};
};
app->start;
=head1 USER AGENT
When we say L<Mojolicious> is a web framework we actually mean it, with L<Mojo::UserAgent> there's a full featured HTTP
and WebSocket user agent built right in.
=head2 REST web services
Requests can be performed very comfortably with methods like L<Mojo::UserAgent/"get">, and always result in a
L<Mojo::Transaction::HTTP> object, which has many useful attributes and methods. You can check for connection errors
with L<Mojo::Transaction/"result">, or access HTTP request and response information directly through
L<Mojo::Transaction/"req"> and L<Mojo::Transaction/"res">.
use Mojo::UserAgent;
# Request a resource and make sure there were no connection errors
my $ua = Mojo::UserAgent->new;
my $tx = $ua->get('https://docs.mojolicious.org/Mojo' => {Accept => 'text/plain'});
my $res = $tx->result;
# Decide what to do with its representation
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...' }
While methods like L<Mojo::Message::Response/"is_success"> and L<Mojo::Message::Response/"is_error"> serve as building
blocks for more sophisticated REST clients.
=head2 Web scraping
Scraping information from websites has never been this much fun before. The built-in HTML/XML parser L<Mojo::DOM> is
accessible through L<Mojo::Message/"dom"> and supports all CSS selectors that make sense for a standalone parser, it
can be a very powerful tool especially for testing web application.
use Mojo::UserAgent;
# Fetch website
my $ua = Mojo::UserAgent->new;
my $res = $ua->get('https://docs.mojolicious.org')->result;
# Extract title
say 'Title: ', $res->dom->at('head > title')->text;
# Extract headings
$res->dom('h1, h2, h3')->each(sub ($dom, $i) {
say 'Heading: ', $dom->all_text;
});
# Visit all nodes recursively to extract more than just text
for my $n ($res->dom->descendant_nodes->each) {
# Text or CDATA node
print $n->content if $n->type eq 'text' || $n->type eq 'cdata';
# Also include alternate text for images
print $n->{alt} if $n->type eq 'tag' && $n->tag eq 'img';
}
For a full list of available CSS selectors see L<Mojo::DOM::CSS/"SELECTORS">.
=head2 JSON web services
Most web services these days are based on the JSON data-interchange format. That's why L<Mojolicious> comes with the
possibly fastest pure-Perl implementation L<Mojo::JSON> built right in, which is accessible through
L<Mojo::Message/"json">.
use Mojo::UserAgent;
use Mojo::URL;
# Fresh user agent
my $ua = Mojo::UserAgent->new;
# Search MetaCPAN for "mojolicious" and list latest releases
my $url = Mojo::URL->new('http://fastapi.metacpan.org/v1/release/_search');
$url->query({q => 'mojolicious', sort => 'date:desc'});
for my $hit (@{$ua->get($url)->result->json->{hits}{hits}}) {
say "$hit->{_source}{name} ($hit->{_source}{author})";
}
=head2 Basic authentication
You can just add username and password to the URL, an C<Authorization> header will be automatically generated.
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
say $ua->get('https://sri:secret@example.com/hideout')->result->body;
If you're using L<Mojo::URL> to build the URL, be aware that the userinfo part will not be included if the object is
stringified. You'll have to pass the object itself to L<Mojo::UserAgent> or use L<Mojo::URL/"to_unsafe_string">.
use Mojo::UserAgent;
use Mojo::URL;
my $ua = Mojo::UserAgent->new;
my $url = Mojo::URL->new('https://example.com/hideout')->userinfo('sri:secret');
say $ua->get($url)->result->body;
=head2 Decorating follow-up requests
L<Mojo::UserAgent> can automatically follow redirects, the event L<Mojo::UserAgent/"start"> allows you direct access to
each transaction right after they have been initialized and before a connection gets associated with them.
use Mojo::UserAgent;
# User agent following up to 10 redirects
my $ua = Mojo::UserAgent->new(max_redirects => 10);
# Add a witty header to every request
$ua->on(start => sub ($ua, $tx) {
$tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
say 'Request: ', $tx->req->url->clone->to_abs;
});
( run in 1.350 second using v1.01-cache-2.11-cpan-5837b0d9d2c )