MojoliciousMarcos Rebelo (oleber@gmail.com)
Mojolicious● An amazing real-time web framework  supporting a simplified single file mode  through Mojolicious::Lite.● Ver...
Mojolicious● Full stack HTTP 1.1 and WebSocket  client/server implementation with IPv6, TLS,  Bonjour, IDNA, Comet (long p...
Marcos Rebelo● 10 years Perl Developer● Test-driven development fan● Mojolicious experience:  ○ Im not a Mojolicious devel...
Any intelligent fool can make things bigger,more complex, and more violent. It takes atouch of genius -- and a lot of cour...
Installation$ sudo cpan Mojolicious
Hello Worlduse Mojolicious::Lite;get / => sub {    shift->render(text => Hello World!)};app->start;● $ hello.pl daemon    ...
Generator● There is a helper command to generate a  small example application. You may  generate multiple things, but two ...
Mojolicious::Lite#!/usr/bin/env perluse Mojolicious::Lite;# Documentation browser under "/perldoc"plugin PODRenderer;get /...
Mojolicious::Lite__DATA__@@ index.html.ep% layout default;% title Welcome;Welcome to Mojolicious!@@ layouts/default.html.e...
Routesget /welcome => sub { … };post /user => sub { … };any /baz => sub { … };any [get, post, delete] =>  /bye => sub { … };
GET/POST parameters# /foo?user=Peterget /foo => sub {   my $self = shift;   my $user = $self->param(user);   $self->render...
Placeholders# /foo/peterget /foo/:user => sub {   my $self = shift;   my $user = $self->param(user);   $self->render(     ...
Underunder sub {   # Global logic shared by all routes   my $self = shift;   return 1 if     $self->req->headers->header(X...
Undergroup {   # shared only by routes in this group   under /admin => sub {      my $self = shift;      return 1 if login...
Sessionsget /counter => sub {   my $self = shift;   $self->session->{counter}++;};__DATA__@@ counter.html.epCounter: <%= s...
Flashget /save => sub {  my $self = shift;  $self->flash(success => 1);  $c->redirect_to(/show_user);};● Data storage pers...
Stash# /barget /bar => sub {   my $self = shift;   $self->stash(one => 23);   $self->render(baz, two => 24);};__DATA__@@ b...
Logmy $log = $self->app->log;$log->debug("Why isnt this working?");$log->info("FYI: it happened again");$log->warn("This m...
Render● Rendering text: Perl characters can be  rendered with the text stash value, the given  content will be automatical...
Render● Rendering JSON: The json stash value  allows you to pass Perl structures to the  renderer which get directly encod...
Rendering templatesget /bar => sub {   my $self = shift;   $self->render(template => bar);};__DATA__@@ bar.html.epHi <%= p...
Rendering templates● The renderer does some magic to find the  templates.● Since we are processing /bar, all this are  sim...
Embedded Perl<% Perl code %><%= Perl expression, replaced with XML escaped result %><%== Perl expression, replaced with re...
Examples<% my $count = 10; %><ul>     <% for my $index (1 .. $count) { %>         <li>              <%= $index %>         ...
Examples% my $count = 10;<ul>     % for my $index (1 .. $count) {         <li>              %= $index         </li>     % ...
Examples<%= lalala %>         <%# XML escaped %><%== <p>test</p> %>   <%# not escaped %>
Layouts@@ foo/bar.html.ep% layout mylayout, title => Hi there;Hello World!@@ layouts/mylayout.html.ep<!DOCTYPE html><html>...
Helpersget /bar => sub {   my $self = shift;   $self->app->log->debug(     $self->dumper( [1,2,3] ) );};__DATA__@@ bar.htm...
Helpers examples● dumper: Dump a Perl data structure using  Data::Dumper● app: Alias for "app" in Mojolicious::Controller●...
Creating a Helperhelper prefix => sub {   my ( $self, $text, $length ) = @_;   return length( $text ) > $length - 3     ? ...
Growing
Generator$ mojo generate app MyApp
my_app                        #   Application directory  |- script                   #   Script directory  | `- my_app    ...
my_app/lib/MyApp.pmpackage MyApp;use Mojo::Base Mojolicious;# This method will run once at server startsub startup {  my $...
Routing# GET /user/123$r->get(/user/:user_id)  ->to(cb => sub { ... });# POST /user/123$r->post(/user/:user_id)->to(  cont...
Route Bridge# POST /auth/user/123my $r_auth = $r->bridge(/auth)  ->to( cb => sub { ... } );$r_auth->post(/user/:user_id)  ...
Controller: lib/MyApp/Example.pmpackage MyApp::Example;use Mojo::Base Mojolicious::Controller;# This action will render a ...
Testinguse Mojo::Base -strict;use Test::More tests => 4;use Test::Mojo;use_ok MyApp;my $t = Test::Mojo->new(MyApp);$t->get...
Testing● Request:  $t->delete_ok(/foo);  $t->get_ok(/foo);  $t->head_ok(/foo);  $t->post_ok(/foo);  $t->post_form_ok(     ...
Testing● Status  $t->status_is(200);  $t->status_isnt(200);● Content Type  $t->content_type_is(text/html);  $t->content_ty...
Testing● Response content:  $t->content_is(working!);  $t->content_isnt(working!);  $t->content_like(qr/working!/);  $t->c...
Testing● JSON $t->json_content_is([1, 2, 3]); $t->json_is(/foo => {bar => [1, 3]}); $t->json_has(/minibar); $t->json_hasnt...
Questions  andAnswers
Upcoming SlideShare
Loading in...5
×

Mojolicious

5,087

Published on

Published in: Technology
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,087
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
43
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

Mojolicious

  1. 1. MojoliciousMarcos Rebelo (oleber@gmail.com)
  2. 2. Mojolicious● An amazing real-time web framework supporting a simplified single file mode through Mojolicious::Lite.● Very clean, portable and Object Oriented pure Perl API without any hidden magic and no requirements besides Perl 5.10.1 (although 5.12+ is recommended, and optional CPAN modules will be used to provide advanced functionality if they are installed).
  3. 3. Mojolicious● Full stack HTTP 1.1 and WebSocket client/server implementation with IPv6, TLS, Bonjour, IDNA, Comet (long polling), chunking and multipart support.● Built-in non-blocking I/O web server supporting libev and hot deployment, perfect for embedding.● Automatic CGI and PSGI detection.● JSON and HTML5/XML parser with CSS3 selector support.
  4. 4. Marcos Rebelo● 10 years Perl Developer● Test-driven development fan● Mojolicious experience: ○ Im not a Mojolicious developer. ○ A group of JSON Back-ends ○ Short effort on the Front-end
  5. 5. Any intelligent fool can make things bigger,more complex, and more violent. It takes atouch of genius -- and a lot of courage -- tomove in the opposite direction.Albert Einstein
  6. 6. Installation$ sudo cpan Mojolicious
  7. 7. Hello Worlduse Mojolicious::Lite;get / => sub { shift->render(text => Hello World!)};app->start;● $ hello.pl daemon Server available at http://127.0.0.1: 3000.● $ curl http://127.0.0.1:3000/ Hello World!
  8. 8. Generator● There is a helper command to generate a small example application. You may generate multiple things, but two are very interesting.● $ mojo generate app Generate Mojolicious application directory structure.● $ mojo generate lite_app Generate Mojolicious::Lite application.
  9. 9. Mojolicious::Lite#!/usr/bin/env perluse Mojolicious::Lite;# Documentation browser under "/perldoc"plugin PODRenderer;get /welcome => sub { my $self = shift; $self->render(index);};app->start;
  10. 10. Mojolicious::Lite__DATA__@@ index.html.ep% layout default;% title Welcome;Welcome to Mojolicious!@@ layouts/default.html.ep<!doctype html><html> <head><title><%= title %></title></head> <body><%= content %></body></html>
  11. 11. Routesget /welcome => sub { … };post /user => sub { … };any /baz => sub { … };any [get, post, delete] => /bye => sub { … };
  12. 12. GET/POST parameters# /foo?user=Peterget /foo => sub { my $self = shift; my $user = $self->param(user); $self->render( text => "Hello $user.");};
  13. 13. Placeholders# /foo/peterget /foo/:user => sub { my $self = shift; my $user = $self->param(user); $self->render( text => "Hello $user.");};● Much more can be told about Placeholders, see the documentation.
  14. 14. Underunder sub { # Global logic shared by all routes my $self = shift; return 1 if $self->req->headers->header(X-Bender); $self->render(text=>"Youre not Bender."); return;};# GET /welcomeget /welcome => { text => Hi Bender. };
  15. 15. Undergroup { # shared only by routes in this group under /admin => sub { my $self = shift; return 1 if login_ok( $self ); $self->redirect_to(/login_page); return }; # GET /admin/dashboard get /dashboard => { text => logged };};
  16. 16. Sessionsget /counter => sub { my $self = shift; $self->session->{counter}++;};__DATA__@@ counter.html.epCounter: <%= session counter %>● Signed cookie based sessions just work out of the box as soon as you start using them.
  17. 17. Flashget /save => sub { my $self = shift; $self->flash(success => 1); $c->redirect_to(/show_user);};● Data storage persistent only for the next request, stored in the session.
  18. 18. Stash# /barget /bar => sub { my $self = shift; $self->stash(one => 23); $self->render(baz, two => 24);};__DATA__@@ baz.html.epMagic numbers: <%= $one %> and <%= $two %>.● The stash is used to pass data to templates.
  19. 19. Logmy $log = $self->app->log;$log->debug("Why isnt this working?");$log->info("FYI: it happened again");$log->warn("This might be a problem");$log->error("Garden variety error");$log->fatal("Boom!");● Messages will be automatically written to STDERR or a $mode.log file if a log directory exists.
  20. 20. Render● Rendering text: Perl characters can be rendered with the text stash value, the given content will be automatically encoded to bytes. $self->render(text => Hello World!);● Rendering data: Raw bytes can be rendered, no encoding will be performed. $self->render(data => $octets);
  21. 21. Render● Rendering JSON: The json stash value allows you to pass Perl structures to the renderer which get directly encoded to JSON.$self->render( json => {foo => [1, 2, 3]});
  22. 22. Rendering templatesget /bar => sub { my $self = shift; $self->render(template => bar);};__DATA__@@ bar.html.epHi <%= param(name) %>● The templates shall in the __DATA__ session or in the templates directory with the file name name.format.handler.
  23. 23. Rendering templates● The renderer does some magic to find the templates.● Since we are processing /bar, all this are similar: ○ $self->render(template => bar); ○ $self->render(bar); ○ $self->render(); ○ You dont even need it. If there is no rendering done, Mojolicious will do it by default.
  24. 24. Embedded Perl<% Perl code %><%= Perl expression, replaced with XML escaped result %><%== Perl expression, replaced with result %><%# Comment, useful for debugging %><%% Replaced with "<%", useful for generating templates %>% Perl code line, treated as "<% line =%>"%= Perl expression line, treated as "<%= line %>"%== Perl expression line, treated as "<%== line %>"%# Comment line, treated as "<%# line =%>"%% Replaced with "%", useful for generating templates
  25. 25. Examples<% my $count = 10; %><ul> <% for my $index (1 .. $count) { %> <li> <%= $index %> </li> <% } %></ul>
  26. 26. Examples% my $count = 10;<ul> % for my $index (1 .. $count) { <li> %= $index </li> % }</ul>
  27. 27. Examples<%= lalala %> <%# XML escaped %><%== <p>test</p> %> <%# not escaped %>
  28. 28. Layouts@@ foo/bar.html.ep% layout mylayout, title => Hi there;Hello World!@@ layouts/mylayout.html.ep<!DOCTYPE html><html> <head><title><%= $title %></title></head> <body><%= content %></body></html>● Most of the time you want to wrap your generated content in a HTML skeleton.
  29. 29. Helpersget /bar => sub { my $self = shift; $self->app->log->debug( $self->dumper( [1,2,3] ) );};__DATA__@@ bar.html.ep<%= dumper( { a => b } ) %>● Helpers are little functions you can use in templates and controller code.
  30. 30. Helpers examples● dumper: Dump a Perl data structure using Data::Dumper● app: Alias for "app" in Mojolicious::Controller● param: Alias for "param".● session: Alias for "session".● stash: Alias for "stash".● layout: Render this template with a layout.● content: Insert content into a layout template.
  31. 31. Creating a Helperhelper prefix => sub { my ( $self, $text, $length ) = @_; return length( $text ) > $length - 3 ? substr($text, 0, $length) . ... : $text;};get /bar => sub { shift->stash(str => 123456789);};__DATA__@@ bar.html.epvalue: <%= prefix( $str, 5 ) %>
  32. 32. Growing
  33. 33. Generator$ mojo generate app MyApp
  34. 34. my_app # Application directory |- script # Script directory | `- my_app # Application script |- lib # Library directory | |- MyApp.pm # Application class | `- MyApp # Application namespace | `- Example.pm # Controller class |- t # Test directory | `- basic.t # Random test |- log # Log directory | `- development.log # Development mode log file |- public # Static file directory | `- index.html # Static HTML file `- templates # Template directory |- layouts # Template directory for layouts | `- default.html.ep # Layout template `- example # Tmpl dir for "Example"controller `- welcome.html.ep # Template for "welcome" action
  35. 35. my_app/lib/MyApp.pmpackage MyApp;use Mojo::Base Mojolicious;# This method will run once at server startsub startup { my $self = shift; # Documentation browser under "/perldoc" $self->plugin(PODRenderer); # Routes my $r = $self->routes; # Normal route to controller $r->route(/welcome)->to(example#welcome);}1;
  36. 36. Routing# GET /user/123$r->get(/user/:user_id) ->to(cb => sub { ... });# POST /user/123$r->post(/user/:user_id)->to( controller => example, action => post_user); # Will call: MyApp::Example::post_user$r->post(/user/:user_id)->to( example#post_user);
  37. 37. Route Bridge# POST /auth/user/123my $r_auth = $r->bridge(/auth) ->to( cb => sub { ... } );$r_auth->post(/user/:user_id) ->to(example#hdl_post_user);
  38. 38. Controller: lib/MyApp/Example.pmpackage MyApp::Example;use Mojo::Base Mojolicious::Controller;# This action will render a templatesub welcome { my $self = shift; # Render "example/welcome.html.ep" $self->render( message => Welcome!);}1;
  39. 39. Testinguse Mojo::Base -strict;use Test::More tests => 4;use Test::Mojo;use_ok MyApp;my $t = Test::Mojo->new(MyApp);$t->get_ok(/welcome) ->status_is(200) ->content_like(qr/Welcome/i);
  40. 40. Testing● Request: $t->delete_ok(/foo); $t->get_ok(/foo); $t->head_ok(/foo); $t->post_ok(/foo); $t->post_form_ok( /foo => {test => 123}); $t->put_ok(/foo);● Header $t->header_is(Expect => fun); $t->header_isnt(Expect => fun); $t->header_like(Expect => qr/fun/); $t->header_unlike(Expect => qr/fun/);
  41. 41. Testing● Status $t->status_is(200); $t->status_isnt(200);● Content Type $t->content_type_is(text/html); $t->content_type_isnt(text/html); $t->content_type_like(qr/text/); $t->content_type_unlike(qr/text/);
  42. 42. Testing● Response content: $t->content_is(working!); $t->content_isnt(working!); $t->content_like(qr/working!/); $t->content_unlike(qr/working!/);● CSS3 selectors $t->element_exists(div.foo[x=y]); $t->element_exists_not(div.foo[x=y]); $t->text_is(div.foo[x=y] => Hello!); $t->text_isnt(div.foo[x=y] => Hello!); $t->text_like(div.foo[x=y] => qr/Hello/); $t->text_unlike(div.foo[x=y] => qr/Hello/);
  43. 43. Testing● JSON $t->json_content_is([1, 2, 3]); $t->json_is(/foo => {bar => [1, 3]}); $t->json_has(/minibar); $t->json_hasnt(/minibar);
  44. 44. Questions andAnswers
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×