Mojolicious Web Clients

Author: brian d foy
Publisher: Perl School
Pages: 255
Audience: Developers who want to write web clients in Perl
Rating: 5
Reviewer: Nikos Vaggalis

Mojolicious might be famous for its server side presence but that doesn't rule out excellence on the client side as well, as  this book demonstrates.

This book about writing post modern client application that can interact with web sites build with Mojolicious or otherwise. As on the server side, so on the client side there's a sheer amount of choices and depth of functionality that Mojo supports. JSON and XML parsing, DOM handling with CSS selectors and asynchronous requests amongst others. One namespace to rule them all.

brian d foy goes through most of the functionality, showcasing the automation of repetitive tasks and the collation of information from web sites.The approach taken in writing this book resembles that of Intermediate Perl (check our review of the 2nd Edition here), hence he won't take you by the hand as in Learning Perl and Programming Perl.

Banner

In other words, it requires to know your Perl beforehand. Despite that there's a chapter dedicated to get you up to speed with the modern Perl and its version features used in the book, 5.28. These should be taken for granted unless you've been living in a cave for the last couple of years. As such code like sub {ref $[0]} should not prompt inquiring eyebrow raising.

On the other hand however, the approach taken to teach the Web, HTTP and related topics such as request/response cycles, headers, cookies etc, is more beginner friendly and always through the eyes of Mojolicious client side.

 

It's important to understand that the book is a compact but otherwise good guide to get you started using Mojo for writing client side applications, even by using technologies that have found their way from the server side to the client side such as asynchronous processing with event loops. Also the distribution format chosen, that of a low cost compact updateable ebook available on Lean Pub rather than a printed edition, I think serves the kind of evolving and little domain specific subjects like this one much better.

So in Chapter 1 before going through the HTTP protocol and its request response cycle, verbs, resources, status codes and how they play along with Mojo, d foy first sets the rules of engagement by making sure to warn you that you should respect those found in robot.txt as well as those under the terms of use of the web site you are after.

For example the act of scraping web sites lies on the gray side of the law and there are tricks under which you can beat imposed artificial rate-limits through the use of proxies (there are even residential proxy packages).Lately there was also a US Court decision that perplexed the issue further by deciding that web scraping public sites does not violate the CFAA (Computer Fraud and Abuse Act).So there's hope after all.

The book here and there also contrasts Mojo with LWP by demonstrating how Mojo is an improvement over it, with all due respect to the venerable old timer, the same respect that CGI.pm should enjoy;no matter that it was superseded by the modern frameworks of Mojolicious or Dancer, while it served, it served well.

As already said Chapter 2 goes through some necessary Perl, mainly the modern day updates till version 5.28 used in the book.
That is, declaring the minimum version to automatically import new features, use feature qw(), use utf8 and import experimental features.Of course you can automatically import them all in one go under Mojo::Base:

use Mojo::Base -strict;

which turns on:

use strict;
use warnings;
use utf8;
use feature qw(:5.10);

while to also import Roles and Signatures (experimental):

use Mojo::Base -role, -signatures;

Of course the rundown wouldn't be complete without the new Postifx dereference.

Chapter 3 familiarizes us with the Mojo namespace and its utility modules.We've already seen Mojo::Base, but under the Mojo namespace and the notion of encapsulating disparate functionality found in many other third party modules, we find that Mojo::Util can also replace Data::Dumper to make for friendlier output:

use Mojo::Util qw(dumper);

my $hash_reference = {
robot => 'Bender',
pilot => 'Leela',
};

say dumper( $hash_reference );

The $VAR is gone and the indention is not as severe:

{
"pilot" => "Leela",
"robot" => "Bender"
}

There's Mojo::URL which knows how to put together and take apart addresses and work with paths, like

use Mojo::Base -strict;
use Mojo::URL;

my $url = Mojo::URL->new( 'http://www.example.com' );

$url->path( '/employee/fry' );

say $url; # http://www.example.com/employee/fry

There's Mojo::JSON which encodes Perl data structures to JSON objects and vice versa. This is followed by an example of why "use utf8" is turned on by default by Mojo::Base. Because you can use Unicode glyphs straight in your code and let Mojo handle the encoding/decoding when interacting with a web server :

use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my $url = 'http://www.example.com';
my $perl_data = {
'rainbow' => 'rainbow'; # U+1F308, 0xF09F8C88 in UTF8
};
my $tx = $ua->post( $url, json => $perl_data );
say $tx->req->to_string 

There's also Mojo::Collection which makes handling lists a more flexible and OOP approach and of course Mojo::EventEmitter which is structured around the Event loop which allows for something happening in one part of the code, for other parts of the code to find out about it and react.

Chapter 4 is about manipulating the DOM with Mojo::DOM which parses HTML and XML alike, and manipulates the Document.Again a replacement for other domain specific modules which would cover most and usual scenarios but of course if things get tough with say XML parsing you're better off with the specialized ones like XML::Twig.

use Mojo::DOM;
 my $html = <<~'HTML';
<ul>
 <li><a href="http://www.example.com/one">One</a></li>
<li><a href="http://www.example.com/two">Two</a></li>
<li><a href="http://www.example.com/three">Three</a></li>
</ul>
HTML
my $dom = Mojo::DOM->new( $html );
my $links = $dom->find( 'a' ); # a collection
say $links->join( "\n" );

 Mojo::DOM does not stop there though. Mimicking JQuery it can also pick nodes according to CSS classes or IDs attached to the elements.It supports  up to Selectors Level 3 with some experimental features from Selectors Level 4.

use Mojo::DOM;
my $data =<<~'HTML';
<div class="hidden"><p>Bender</p></div>
<div class="print"><p>Fry</p></div>
<div class="mobile"><p>Leela</p></div>
HTML
my $dom = Mojo::DOM->new( $data )->at( 'div.mobile' );
say $dom;

 This one selects only the div with the mobile tag:

<div class="mobile"><p>Leela</p></div>

Other selection criteria are by:

Starting text/Ending text

say $dom->find( 'img[alt^="Bender"]' )->join( "\n" );

Substring

say $dom->find( 'img[alt*="kin"]' )->join( "\n" );

Now you get two of the img tags. Each of these have kin somewhere in the alt attribute:

<img alt="Bender working" src="/working.png">
<img alt="Bender drinking" src="/drinking.png">

Selecting Multiple attributes,by Relative Position, Children, Descendants and more.

Really this chapter was a total how-to with lots of information.

The next, Chapter 6, Requests, is the main chapter of the book, since the Request is the start of the HTTP conversation.So here we find how to start a transaction object that encapsulates all necessary information to make the call and its auxiliary methods for adding Headers to it, Authentication (even OAth which Mojo makes it easy to perform through use OAuth::Cmdline::Mojo) and of course for sending data along the request

"Sending JSON data is so easy that you don't need to know how to construct it yourself or even understand what it is. Specify json when you construct the request and give it a Perl data structure. Mojo will convert that data structure to the correct data structure. 

use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my %hash = (
robot => 'Bender',
human => 'Fry',
mutant => 'Leela',
others => [ qw(Farnsworth Nibbler) ],
);
# httpbin will show the JSON you passed
my $url = 'http://www.httpbin.org/post';
 my $tx = $ua->build_tx( POST => $url, json => \%hash );
say $tx->req->to_string;"

Also we find how to go about sending Form data, uploading files and doing streaming uploads.

Chapter 7 on Cookies is really an expansion of the previous to add handling cookies too. Again brief but pretty much precise in giving away what you need to know.

Chapter 8 is about what you do with the Response of the server, and that is not just parsing the content but also handling timeouts, inspecting headers, redirection, caching and even displaying Progress bars while the response is downloading.

Also this chapter touches an important but easily overseen case, that of Pagination, which sets the prelude for Chapter 9 as 

"The particular way that you handle many requests depends on the task. You could do them concurrently (see Chapter 9) or serially. "

So Chapter 9, most interesting as it tackles asynchronous non-blocking requests. It first shows the old way of the callbacks and then goes through the new way of the Promises which instead of descending into the different levels of hell for each level of callback, you proceed in a mostly linear fashion thatÂ’'s easier to follow.Of course Mojo takes that a step further as it builds several concurrency interfaces on top of its Promises/A+ implementation.

The important takeaway from this chapter is that : 

"Mojo doesn't magically make all of your program non-blocking", there's still many place you can still trip up.

Chapter 10 deals with the fact that a request can send data and a message body contains those data while the headers describe it. You can do this yourself or use one of the content generators by building your own formatter.

There's already three built-in content generators (and these cover most of the situations you'll encounter with servers you don't control):

form
json
multipart

The first one, form, takes a Perl data structure and represents it as form data, but the real value of a generator is that it also takes care of the Content-Type and Content-Length and the information about the boundary when on multipart. 

The message body is divided into sections for each

chunk:
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new();
my @parts = qw(Bender Fry);
say $ua->build_tx(
'POST' => 'www.example.com/',
multipart => \@parts,
)->req->to_string;

If you control the server, you can also make your own custom generators for example to send a Perl data structure serialized with the Sereal module in a compact binary format.

The last chapter, Chapter 11 is about miscellaneous command line options which utilize the namespace's power for quick operations.

mojo version
mojo generate lite_app
mojo getetc

Concluding, if you are familiar with d foy's writing style you'll expect no surprises. As always clean, precise and structured writing makes this title one of those books that will make you want to put down your Javascript clients and start using the ones written in the language you love so much. As does Perl, Mojo goes steps beyond, adopting the succinctness, flexibility and the smart shortcuts you are accustomed to. How to do that you'll find inside this book.

To keep up with our coverage of books for programmers, follow @bookwatchiprog on Twitter or subscribe to I Programmer's Books RSS feed for each day's new addition to Book Watch and for new reviews.


Learn to Code by Solving Problems

Author: Dr. Daniel Zingaro
Publisher: No Starch Press
Date: June 2021
Pages: 335
ISBN: 978-1718501324
Print: 1718501323
Kindle: B08FH92YL8
Audience: People wanting to learn Python
Rating: 4
Reviewer: Mike James
Solving problems - sounds good?



T-SQL Fundamentals (Microsoft Press)

Author: Itzik Ben-Gan
Publisher: Microsoft Press
Pages: 608
ISBN: 978-0138102104
Print: 0138102104
Kindle: B0BTLBXF8V
Audience: T-SQL developers
Rating: 5
Reviewer: Kay Ewbank

Itzik Ben-Gan is a highly respected Microsoft Data Platform MVP, and the earlier editions of this book were already ver [ ... ]


More Reviews

<ASIN:B0826CX6G7>

<ASIN:1449393098>

<ASIN:1491954329>

<ASIN:0596004923>

Last Updated ( Saturday, 13 June 2020 )