Web 3.5 & Perl

Features that a modern
web framework must have

  • Object Oriented API
  • HTTP 1.1 and WebSocket client/server implementation
  • RESTful features
  • Internationalization
  • Multiplatform and multiserver easy deployment
  • Builtin asynchronous IO
  • Advanced testing capabilities
  • Features like routes, plugins, templates, sessions etc
  • Playable out of the box but configurable for advanced projects
  • 3rd party extensions
  • Examples

Is there a modern Perl web framework?

YES
Mojolicious

Object Oriented API

MVC paradigm
# Controller
package MyApp::Example;
use base 'Mojolicious::Controller';

# Model
use MyModel;

sub welcome {
    my $self = shift;

    my $model = MyModel->new;

    my $stuff = $model->get_stuff_by_id($self->param('id'));

    # View
    $self->render_json($stuff->to_hash);
}

HTTP 1.1 and WebSocket client/server implementation

We are ready for the future

  • IPv6
  • TLS 1.2 (SSL accessor)
  • IDNA (Internationalized domain name)
  • WebSockets (bi-directional, full-duplex communications channels over a single TCP socket)
    $self->receive_message(sub {
        my ($self, $message) = @_;
    
        $self->send_message($message);
    });
  • Pipelining, chunking and multipart (not new, but advanced)

RESTful features

Writing web services friendly apps is easy

  • RESTful routes (map request methods to different controllers)
        $routes->route('/')->via('GET')->over(agent => qr/Firefox/)->to('example#welcome');
    
  • Builtin JSON encoder/decoder
        my $json_string = Mojo::JSON->new->encode({foo => {bar => 'baz'}});
    
  • Rendering data in multiple types based on url (html, txt, pod, json)
        page.html.ep -> NAME.FORMAT.TEMPLATE
    
  • Sessions done via signed cookies

Internationalization

Internet is a multilingual and multicultural environment

  • Builtin I18N support for strings translation
    package MyTestApp::I18N::de;
    use base 'MyTestApp::I18N';
    our %Lexicon = (hello => 'hallo');
    ...
    $self->plugin('i18n');
    ...
    <%=l 'hello' %> # hallo
    
  • First class Unicode support
    • UTF-8
    • UTF-32LE
    • UTF-32BE
    • UTF-16BE
    • UTF-16LE

Multiplatform and multiserver deployment

Get out of the deployment hell

  • No dependencies except Perl 5.8.7 that is already there
  • CGI, FastCGI, PSGI
  • Apache, nginx, lighttpd, IIS and more
  • Hot deployment and UNIX domain socket sharing
  • Development standalone and prefork servers
./my_app daemon --listen 'http://*:1234'
./my_app daemon_prefork
./my_app cgi
./my_app fastcgi
./my_app psgi

Builtin asynchronous IO and prefork web server

Event-driven programming is here

  • Builtin IO event loop for asynchronous tcp connections
  • Multiple event loops including epoll and kqueue
  • Asynchrounous client with parallel downloads and streaming support

Echo server example

my $buffer = '';

my $loop = Mojo::IOLoop->singleton;

my $server = $loop->connect(
  address => $host,
  port  => $port,
  cb    => sub {
    warn "Connected to $host:$port";

    $loop->writing($_[1])
      if length $buffer;
  }
);


$loop->read_cb(
  $server => sub {
    $buffer = $_[2];
    $loop->writing($server);
  }
);

$loop->write_cb(
  $server => sub {
    $loop->not_writing($server);
    return $buffer;
  }
);

$loop->start;
            

Parallel downloads

  my $client = Mojo::Client->new;

  $client->get('http://examples.com/1');
  $client->get('http://examples.com/2');
  $client->get('http://examples.com/3');
  $client->get('http://examples.com/4');

  $client->process;
            

Asynchrounous subrequest

sub welcome {
    my $self = shift;

    # Pause
    $self->pause;

    $self->client->async->get('http://example.com' => sub {
        my $self = shift;

        # Resume
        $self->finish;
    })->process;
}

mp3 streaming client example

  open(HANDLER, "|mpg123 -") or die "Cannot pipe input: $!\n";

  my $tx = Mojo::Transaction::HTTP->new;
  $tx->req->method('GET');
  $tx->req->url->parse($url);
  $tx->res->body(
    sub {
      my ($res, $chunk) = @_;
      print HANDLER $chunk;
    }
  );

  Mojo::Client->new->process($tx);

  close HANDLER;
            

Advanced testing capabilities

It's not a feature without a test

  • Heavy testing of existing code
    Files=41, Tests=2272 # May 2010
    
  • Infrastructure for testing website's links and forms
    use Test::Mojo;
    my $t = Test::Mojo->new(app => 'MyApp');
    
    $t->get_ok('/welcome')->status_is(200)
      ->content_like(qr/Hello!/, 'welcome message!');
    
    $t->post_form_ok('/search', {title => 'Perl', author => 'taro'})->status_is(200)
      ->content_like(qr/Perl.+taro/);
    
  • Testing live against the real tcp server
  • Development servers with a static file serving ability

Most needable web framework features

It is already there

  • Routes
        $routes->route('/')->via('GET')->over(agent => qr/Firefox/)->to('example#welcome');
    
  • Plugins
        $self->plugin('i18n');
    
  • Sessions
        $self->session(user => 'vti');
    

Embedded templates

%# Layouts
% layout 'wrapper';

%# Expressions
<% $foo++ %>
<%= $foo %>

%# Blocks
% for (1 .. 10) {
    * Hello 10 times
% }

%# Automatic xml escaping
<%= '1 > 2' %>

Simple one-file applications or complex project file tree generation

You can have fun whilst still be able to right business apps

# Lite app

#!/usr/bin/env perl
use 'Mojolicious::Lite';

get '/' => sub {
    my $self = shift;

    $self->stash(foo => 'bar');
} => 'welcome';
__DATA__
@@ welcome.html.ep
<% $foo %>


# Full app

[mkdir] /private/tmp/my_app/script
[write] /private/tmp/my_app/script/my_app
[chmod] my_app/script/my_app 744
[mkdir] /private/tmp/my_app/lib
[write] /private/tmp/my_app/lib/MyApp.pm
  ...
[write] /private/tmp/my_app/templates/not_found.html.ep
[exist] /private/tmp/my_app/templates
[write] /private/tmp/my_app/templates/exception.html.ep
[mkdir] /private/tmp/my_app/templates/layouts
[write] /private/tmp/my_app/templates/layouts/default.html.ep
[mkdir] /private/tmp/my_app/templates/example
[write] /private/tmp/my_app/templates/example/welcome.html.ep

CPAN Modules

Mojolicious extensions

  • MojoX::Renderer::*
    TT YAML XSLT Mason HTP CTPP2
  • MojoX::Log::Log4Perl
  • MojoX::Auth::Simple

Lots of examples

It's always better to see some code

  • Comet / WebSockets
    • Comet desktop http://github.com/xantus/comet-desktop
    • IRC Client http://github.com/xantus/mojo-websocket-examples
    • Colaborative drawing http://github.com/vti/showmethedrawing
    • Bomberman http://github.com/vti/mojomber
  • Web publishing
    • Bootylicious blog http://github.com/vti/bootylicious
    • Simple URL shortener http://github.com/memowe/urlicious
    • Simple CMS http://github.com/memowe/contenticious
    • Paste service
      • http://github.com/xantus/mojo-paste
      • http://github.com/vti/pastelicious

Thank You


Viacheslav Tykhanovskyi
http://github.com/vti