SlideShare a Scribd company logo
1 of 44
Download to read offline
Mojolicious
Marcos Rebelo (oleber@gmail.com)
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).
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.
Marcos Rebelo
● 10 years Perl Developer
● Test-driven development fan
● Mojolicious experience:
  ○ I'm not a Mojolicious developer.
  ○ A group of JSON Back-ends
  ○ Short effort on the Front-end
Any intelligent fool can make things bigger,
more complex, and more violent. It takes a
touch of genius -- and a lot of courage -- to
move in the opposite direction.
Albert Einstein
Installation




$ sudo cpan Mojolicious
Hello World
use 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!
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.
Mojolicious::Lite
#!/usr/bin/env perl
use Mojolicious::Lite;

# Documentation browser under "/perldoc"
plugin 'PODRenderer';

get '/welcome' => sub {
   my $self = shift;
   $self->render('index');
};

app->start;
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>
Routes
get '/welcome' => sub { … };

post '/user' => sub { … };

any '/baz' => sub { … };

any ['get', 'post', 'delete'] =>
  '/bye' => sub { … };
GET/POST parameters
# /foo?user=Peter
get '/foo' => sub {
   my $self = shift;
   my $user = $self->param('user');
   $self->render(
     text => "Hello $user.");
};
Placeholders
# /foo/peter
get '/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.
Under
under sub {
   # Global logic shared by all routes
   my $self = shift;
   return 1 if
     $self->req->headers->header('X-Bender');
   $self->render(text=>"You're not Bender.");
   return;
};

# GET /welcome
get '/welcome' => { text => 'Hi Bender.' };
Under
group {
   # 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' };
};
Sessions
get '/counter' => sub {
   my $self = shift;
   $self->session->{counter}++;
};

__DATA__

@@ counter.html.ep
Counter: <%= session 'counter' %>

● Signed cookie based sessions just work out
  of the box as soon as you start using them.
Flash
get '/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.
Stash
# /bar
get '/bar' => sub {
   my $self = shift;
   $self->stash(one => 23);
   $self->render('baz', two => 24);
};

__DATA__
@@ baz.html.ep
Magic numbers: <%= $one %> and <%= $two %>.

● The stash is used to pass data to templates.
Log
my $log = $self->app->log;

$log->debug("Why isn't 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.
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);
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]});
Rendering templates
get '/bar' => sub {
   my $self = shift;
   $self->render(template => 'bar');
};

__DATA__
@@ bar.html.ep
Hi <%= param('name') %>

● The templates shall in the __DATA__
  session or in the templates directory with the
  file name name.format.handler.
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 don't even need it. If there is no rendering done,
      Mojolicious will do it by default.
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
Examples
<% my $count = 10; %>
<ul>
     <% for my $index (1 .. $count) { %>
         <li>
              <%= $index %>
         </li>
     <% } %>
</ul>
Examples
% my $count = 10;
<ul>
     % for my $index (1 .. $count) {
         <li>
              %= $index
         </li>
     % }
</ul>
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>
  <head><title><%= $title %></title></head>
  <body><%= content %></body>
</html>

● Most of the time you want to wrap your
  generated content in a HTML skeleton.
Helpers
get '/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.
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.
Creating a Helper
helper '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.ep
value: <%= prefix( $str, 5 ) %>
Growing
Generator




$ mojo generate app MyApp
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
my_app/lib/MyApp.pm
package MyApp;
use Mojo::Base 'Mojolicious';

# This method will run once at server start
sub 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;
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');
Route Bridge
# POST /auth/user/123
my $r_auth = $r->bridge('/auth')
  ->to( cb => sub { ... } );
$r_auth->post('/user/:user_id')
  ->to('example#hdl_post_user');
Controller: lib/MyApp/Example.pm
package MyApp::Example;
use Mojo::Base 'Mojolicious::Controller';

# This action will render a template
sub welcome {
  my $self = shift;

    # Render "example/welcome.html.ep"
    $self->render( message => 'Welcome!');
}

1;
Testing
use 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);
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/);
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/);
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/);
Testing
● JSON
 $t->json_content_is([1, 2, 3]);
 $t->json_is('/foo' => {bar => [1, 3]});
 $t->json_has('/minibar');
 $t->json_hasnt('/minibar');
Questions
  and
Answers

More Related Content

What's hot

Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 
YAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービス
Yusuke Wada
 
Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5
Yusuke Wada
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
Jeremy Kendall
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Jeremy Kendall
 
PerlでWeb API入門
PerlでWeb API入門PerlでWeb API入門
PerlでWeb API入門
Yusuke Wada
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
benalman
 

What's hot (20)

Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
YAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービス
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!
 
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
 
Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and Knockout
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
PerlでWeb API入門
PerlでWeb API入門PerlでWeb API入門
PerlでWeb API入門
 
Plugin jQuery, Design Patterns
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design Patterns
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST API
 

Similar to Mojolicious

Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web framework
taggg
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware
 
HackU PHP and Node.js
HackU PHP and Node.jsHackU PHP and Node.js
HackU PHP and Node.js
souridatta
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
Kar Juan
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
Michelangelo van Dam
 

Similar to Mojolicious (20)

PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
 
Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web framework
 
Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfast
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
HackU PHP and Node.js
HackU PHP and Node.jsHackU PHP and Node.js
HackU PHP and Node.js
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase framework
 
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, GermanyLet's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 

Recently uploaded

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

Mojolicious

  • 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. 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. Marcos Rebelo ● 10 years Perl Developer ● Test-driven development fan ● Mojolicious experience: ○ I'm not a Mojolicious developer. ○ A group of JSON Back-ends ○ Short effort on the Front-end
  • 5. Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction. Albert Einstein
  • 7. Hello World use 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. 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. Mojolicious::Lite #!/usr/bin/env perl use Mojolicious::Lite; # Documentation browser under "/perldoc" plugin 'PODRenderer'; get '/welcome' => sub { my $self = shift; $self->render('index'); }; app->start;
  • 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. Routes get '/welcome' => sub { … }; post '/user' => sub { … }; any '/baz' => sub { … }; any ['get', 'post', 'delete'] => '/bye' => sub { … };
  • 12. GET/POST parameters # /foo?user=Peter get '/foo' => sub { my $self = shift; my $user = $self->param('user'); $self->render( text => "Hello $user."); };
  • 13. Placeholders # /foo/peter get '/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. Under under sub { # Global logic shared by all routes my $self = shift; return 1 if $self->req->headers->header('X-Bender'); $self->render(text=>"You're not Bender."); return; }; # GET /welcome get '/welcome' => { text => 'Hi Bender.' };
  • 15. Under group { # 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. Sessions get '/counter' => sub { my $self = shift; $self->session->{counter}++; }; __DATA__ @@ counter.html.ep Counter: <%= session 'counter' %> ● Signed cookie based sessions just work out of the box as soon as you start using them.
  • 17. Flash get '/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. Stash # /bar get '/bar' => sub { my $self = shift; $self->stash(one => 23); $self->render('baz', two => 24); }; __DATA__ @@ baz.html.ep Magic numbers: <%= $one %> and <%= $two %>. ● The stash is used to pass data to templates.
  • 19. Log my $log = $self->app->log; $log->debug("Why isn't 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. 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. 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. Rendering templates get '/bar' => sub { my $self = shift; $self->render(template => 'bar'); }; __DATA__ @@ bar.html.ep Hi <%= param('name') %> ● The templates shall in the __DATA__ session or in the templates directory with the file name name.format.handler.
  • 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 don't even need it. If there is no rendering done, Mojolicious will do it by default.
  • 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. Examples <% my $count = 10; %> <ul> <% for my $index (1 .. $count) { %> <li> <%= $index %> </li> <% } %> </ul>
  • 26. Examples % my $count = 10; <ul> % for my $index (1 .. $count) { <li> %= $index </li> % } </ul>
  • 27. Examples <%= 'lalala' %> <%# XML escaped %> <%== '<p>test</p>' %> <%# not escaped %>
  • 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. Helpers get '/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. 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. Creating a Helper helper '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.ep value: <%= prefix( $str, 5 ) %>
  • 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. my_app/lib/MyApp.pm package MyApp; use Mojo::Base 'Mojolicious'; # This method will run once at server start sub 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. 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. Route Bridge # POST /auth/user/123 my $r_auth = $r->bridge('/auth') ->to( cb => sub { ... } ); $r_auth->post('/user/:user_id') ->to('example#hdl_post_user');
  • 38. Controller: lib/MyApp/Example.pm package MyApp::Example; use Mojo::Base 'Mojolicious::Controller'; # This action will render a template sub welcome { my $self = shift; # Render "example/welcome.html.ep" $self->render( message => 'Welcome!'); } 1;
  • 39. Testing use 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. 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. 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. 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. Testing ● JSON $t->json_content_is([1, 2, 3]); $t->json_is('/foo' => {bar => [1, 3]}); $t->json_has('/minibar'); $t->json_hasnt('/minibar');