Mojolicious 
Perl Framework for the Real-Time Web 
Dotan Dimet 
@dotandimet
But that was 
a while back 
Most People Moved on
Perl People 
• But some came 
back 
• And brought back 
cool ideas
Mojolicious
Mojolicious
Real Time Web 
• Non-blocking I/O 
• Event-driven code 
• Asynchronous APIs 
– Not mandatory 
– Sometimes necessary
Features
Morbo error page
Hypnotoad error page
Example use Mojolicious::Lite; 
use 5.20.0; 
use experimental 'signatures'; 
get '/' => {template => 'index'}; 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
app->start; 
__DATA__ 
@@ index.html.ep 
% my $url = url_for 'title'; 
<script> 
var ws = new WebSocket('<%= $url->to_abs %>'); 
ws.onmessage = function (event) { document.body.innerHTML += event.data }; 
ws.onopen = function (event) { ws.send('http://mojolicio.us') }; 
</script>
First Route: 
render a template 
get '/' => {template => 'index'};
use Mojolicious::Lite; 
use 5.20.0; 
use experimental 'signatures'; 
get '/' => {template => 'index'}; 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
app->start; 
__DATA__ 
@@ index.html.ep 
% my $url = url_for 'title'; 
<script> 
var ws = new WebSocket('<%= $url->to_abs %>'); 
ws.onmessage = function (event) { document.body.innerHTML += event.data }; 
ws.onopen = function (event) { ws.send('http://mojolicio.us') }; 
</script>
Template (embedded Perl) 
% my $url = url_for 'title'; 
<script> 
var ws = new WebSocket('<%= $url->to_abs %>'); 
ws.onmessage = function (event) { 
document.body.innerHTML += event.data }; 
ws.onopen = function (event) { 
ws.send('http://mojolicio.us') }; 
</script>
Websocket Message Event 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
Event driven – subscribe to message event, 
triggered when complete message arrives
Websocket Message Event 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
• Send response when done
Built-in Web Client 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
Get a web page, parse into DOM, return the title 
text.
Web Client 
• Mojo::UserAgent 
– Blocking and non-blocking HTTP requests 
• Mojo::DOM 
– Supports most CSS selectors like jQuery
Web Client 2 
• Get Haaretz.co.il full article text: 
self->ua->get( $url, 
{ 'User-Agent' => 'Googlebot/2.1; 
+http://www.google.com/bot.html)' } 
)->res->dom->find('#article-box p')->join("n");
But this is blocking code! 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
When we trigger the message event, we block 
the event loop until we get a response from the 
web page
Sometimes blocking is OK 
• Traditional Database connection 
• Small apps, querying fast remote sites
But we don’t have to block 
$c->ua->get($url, sub { ... }); 
The Mojo::UserAgent calls can take a callback to 
make non-blocking requests
Sometimes we can’t block 
$c->ua->get($c->url_for(‘index’)->to_abs) 
• For example, when demoing without internet, 
we want to fetch a web page we are serving 
from the same process...
More 
• http://mojolicio.us 
• http://mojocasts.com 
– Glen Hinkle @tempire 
• (I stole the nice slides from him) 
• irc irc://irc.perl.org/#mojo 
• mailing list mojolicious@googlegroups.com
use Mojolicious::Lite; 
use 5.20.0; 
use experimental 'signatures'; 
get '/' => {template => 'index'}; 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
app->start; 
__DATA__ 
@@ index.html.ep 
% my $url = url_for 'title'; 
<script> 
var ws = new WebSocket('<%= $url->to_abs %>'); 
ws.onmessage = function (event) { document.body.innerHTML += event.data }; 
ws.onopen = function (event) { ws.send('http://mojolicio.us') }; 
</script>
Signatures use Mojolicious::Lite; 
Use 5.20.0; 
Use experimental 'signatures'; 
get '/' => {template => 'index'}; 
websocket '/title' => sub ($c) { 
$c->on(message => sub ($c, $msg) { 
my $title = $c->ua->get($msg)->res->dom->at('title')->text; 
$c->send($title); 
}); 
}; 
app->start; 
__DATA__ 
@@ index.html.ep 
% my $url = url_for 'title'; 
<script> 
var ws = new WebSocket('<%= $url->to_abs %>'); 
ws.onmessage = function (event) { document.body.innerHTML += event.data }; 
ws.onopen = function (event) { ws.send('http://mojolicio.us') }; 
</script>

Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)

  • 1.
    Mojolicious Perl Frameworkfor the Real-Time Web Dotan Dimet @dotandimet
  • 3.
    But that was a while back Most People Moved on
  • 4.
    Perl People •But some came back • And brought back cool ideas
  • 6.
  • 7.
  • 10.
    Real Time Web • Non-blocking I/O • Event-driven code • Asynchronous APIs – Not mandatory – Sometimes necessary
  • 11.
  • 13.
  • 14.
  • 15.
    Example use Mojolicious::Lite; use 5.20.0; use experimental 'signatures'; get '/' => {template => 'index'}; websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; app->start; __DATA__ @@ index.html.ep % my $url = url_for 'title'; <script> var ws = new WebSocket('<%= $url->to_abs %>'); ws.onmessage = function (event) { document.body.innerHTML += event.data }; ws.onopen = function (event) { ws.send('http://mojolicio.us') }; </script>
  • 17.
    First Route: rendera template get '/' => {template => 'index'};
  • 18.
    use Mojolicious::Lite; use5.20.0; use experimental 'signatures'; get '/' => {template => 'index'}; websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; app->start; __DATA__ @@ index.html.ep % my $url = url_for 'title'; <script> var ws = new WebSocket('<%= $url->to_abs %>'); ws.onmessage = function (event) { document.body.innerHTML += event.data }; ws.onopen = function (event) { ws.send('http://mojolicio.us') }; </script>
  • 19.
    Template (embedded Perl) % my $url = url_for 'title'; <script> var ws = new WebSocket('<%= $url->to_abs %>'); ws.onmessage = function (event) { document.body.innerHTML += event.data }; ws.onopen = function (event) { ws.send('http://mojolicio.us') }; </script>
  • 20.
    Websocket Message Event websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; Event driven – subscribe to message event, triggered when complete message arrives
  • 21.
    Websocket Message Event websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; • Send response when done
  • 22.
    Built-in Web Client websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; Get a web page, parse into DOM, return the title text.
  • 23.
    Web Client •Mojo::UserAgent – Blocking and non-blocking HTTP requests • Mojo::DOM – Supports most CSS selectors like jQuery
  • 24.
    Web Client 2 • Get Haaretz.co.il full article text: self->ua->get( $url, { 'User-Agent' => 'Googlebot/2.1; +http://www.google.com/bot.html)' } )->res->dom->find('#article-box p')->join("n");
  • 25.
    But this isblocking code! $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); When we trigger the message event, we block the event loop until we get a response from the web page
  • 26.
    Sometimes blocking isOK • Traditional Database connection • Small apps, querying fast remote sites
  • 27.
    But we don’thave to block $c->ua->get($url, sub { ... }); The Mojo::UserAgent calls can take a callback to make non-blocking requests
  • 28.
    Sometimes we can’tblock $c->ua->get($c->url_for(‘index’)->to_abs) • For example, when demoing without internet, we want to fetch a web page we are serving from the same process...
  • 30.
    More • http://mojolicio.us • http://mojocasts.com – Glen Hinkle @tempire • (I stole the nice slides from him) • irc irc://irc.perl.org/#mojo • mailing list mojolicious@googlegroups.com
  • 31.
    use Mojolicious::Lite; use5.20.0; use experimental 'signatures'; get '/' => {template => 'index'}; websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; app->start; __DATA__ @@ index.html.ep % my $url = url_for 'title'; <script> var ws = new WebSocket('<%= $url->to_abs %>'); ws.onmessage = function (event) { document.body.innerHTML += event.data }; ws.onopen = function (event) { ws.send('http://mojolicio.us') }; </script>
  • 32.
    Signatures use Mojolicious::Lite; Use 5.20.0; Use experimental 'signatures'; get '/' => {template => 'index'}; websocket '/title' => sub ($c) { $c->on(message => sub ($c, $msg) { my $title = $c->ua->get($msg)->res->dom->at('title')->text; $c->send($title); }); }; app->start; __DATA__ @@ index.html.ep % my $url = url_for 'title'; <script> var ws = new WebSocket('<%= $url->to_abs %>'); ws.onmessage = function (event) { document.body.innerHTML += event.data }; ws.onopen = function (event) { ws.send('http://mojolicio.us') }; </script>

Editor's Notes

  • #2 Hello, my name is Dotan Dimet, and this is Mojolicious, a Perl framework for the real time web.
  • #3 Perl used to rule the web
  • #4 But that was a back in the nineties, when Superman had a mullet Most folks moved on since then
  • #5 . But some came back And brought cool idea picked up when programming other languages
  • #6 One them is Sebastian Riedel, who created the Perl web framework Catalyst then went off to work with Ruby on Rails and Node.
  • #7 He came back to Perl to give us Mojolicious.
  • #8 There are plenty of cool things about mojolicious
  • #10 But I want to mention just 2 The first is
  • #11 The 2nd is the focus on non-blocking i/O. Mojolicious runs an event loop behind the scenes Most modules work non-blocking but have a blocking API So you can mixing blocking with non-blocking calls. Except when you can’t.
  • #12 that it’s Pretty, with nice APIs inspired by Ruby on Rails, Sinatra and jQuery. The code is clean, idiomatic Perl with minimal magic and sugar. There’s an attention to detail in the presentation of everything from the documentation to the default error pages.
  • #13 For Example, Mojolicious has two built-in web servers, Morbo for development and hypnotoad for production
  • #14 This is the default development error page
  • #15 And this is the default error page for the production web server: The failraptor. Because Perl is a dinosaur, a dinosaur unicorn barfing rainbows.
  • #16 I’m going to show you a terrifying screen of code now, it’s the 2nd example from the mojolicious web site.
  • #17 Here’s how it looks on the website. Notice we’ve got a default route that renders a template, and a websocket service. Javascript in the template calls the websocket service
  • #18 So our basic route render a template,
  • #19 The template is in the DATA section of the same file, that’s just a perl trick to put our templates in the same file as the code.
  • #20 Most of our template is just a chunk of HTML – actually, a chunk of javascript, Only the blue text is actually server code, it’s just perl inside template markers. We use it to pass the URL of our websocket service e to the javascript.
  • #21 In our websocket service we don’t respond to the request in the route, we subscribe to an event. – in this case, the event triggered when the websocket transaction receives a complete message This means the outer block of code is non-blocking – we exit immediately and can handle other requests.
  • #22 When done, we use the low-level send method to send our response
  • #23 But I want to focus on this line. Here we get a web client object, use it to get a web page, parse the DOM from the response, use a CSS selector to the get the title element, and return it’s text contents.
  • #24 Behind the scenes we’ve got a web client, a DOM parser, and CSS-selector based queries. You can also extract JSON
  • #25 This is a pretty awesome tool here’s another example where I pretend to be googlebot and get all the paragraphs in an element with the ID article-box
  • #26 But notice that this is blocking code. The web client runs in the same process as our server When we trigger the message event, we block the response until we get a response from that web page.
  • #27 Sometimes blocking is OK, and mojolicious lets you mix blocking and non-blocking calls.
  • #28 But most mojolicious APIs aren’t blocking. The user agent methods in Mojolicious can all take callbacks as arguments to act nonblocking.
  • #29 And we need this, because sometimes we can’t block. For example, when demoing without internet. I tried to fetch a web page served from the same process instead of from the remote site. Non-blocking APIs allow this.
  • #30 There are a ton of features in Mojolicious
  • #31 You can learn more on the mojolicious web site, on Glen Hinkle’s excellent mojocasts.com site, on our IRC channel or mailing list. Hope to see you there.
  • #32 If you’re familiar with Perl, you might notice something unusual about these examples -
  • #33 I’m using function signatures! Finally they arrived in Perl 5.20. Maybe some day we’ll get classes, or proper garbage collection to make our code slower.