Plack
O canivete suiço das Frameworks Web
       Original de Tatsuhiko Miyagawa
        Assassinado por Pedro Melo
Uma breve
 viagem...
Frameworks Web
    em Perl
Mil e uma maneiras de
escrever aplicações Web
Maypole Mason Mojo Sledge Catalyst Spoon
 PageKit AxKit Egg Gantry Continuity Solstice
 Mojolicious Tripletail Konstrukt Reaction Jifty
  Cyclone3 WebGUI OpenInteract Squatting
 Dancer CGI::Application Nanoa Ark Angelos
        Noe Schenker Tatsumaki Amon
Apache2::WebApp Web::Simple Apache2::REST
          SweetPea Hydrant Titanium
Algumas maneiras de
         correr
aplicações Web em Perl
CGI, FastCGI
& mod_perl
Por exemplo....
CGI.pm
Corre “fixe” em:
     CGI, FastCGI, mod_perl (1 & 2)
Standalone (usando HTTP::Server::Simple)
CGI.pm = MDC
     (máximo denominador comum)


Módulo Perl incluído de base
8803 linhas de código
   Versão inicial:
  Novembro 1995
:-(
CGI.PM
tem de ir
 com os
 porcos!!
(tou a brincar...)
Catalyst
A framework web em Perl que todas as vedetas usam
         (brinco de brilhantes estilo Ronaldo ou Quaresma não incluído)
Catalyst::Engine::*
     Adaptadores para servidores:
 Apache, FastCGI, Standalone e Prefork
CGI.pm
    Jifty, CGI::Application, Spoon


baseadas em mod_perl
  Mason, Sledge, PageKit, WebGUI


     Adaptadores
    Catalyst, Maypole, Squatting
Problemas
Duplicação de esforços
 Difícil de comparar
     performance
Que tal partilhar
 esse código?
Algumas tentativas...
HTTP::Engine
Yappo, tokuhirom, nothingmuch e
           companhia
Vitória!
“Rouba-se” o código do Catalyst e cria-se
 uma biblioteca à parte. Tá feito! Siga pa
                 bingo!
Err... talvez não
  Um pedaço de código disforme, sem
separação de interface e implementação:
                “À cão”
Até que em
Setembro 2009...
miyagawa
http://www.flickr.com/photos/hanekomu/4518057694/
Episode IV:
A new hope
Que tal utilizar
 umas ideias fines
do Python e Ruby?
Posto de outra forma
      Vamos importar ideias
 estruturantes que provaram ser
  populares noutros contextos
 dinâmicos, criando sinergias que
  nos permitem agilizar a nossa
 entrada no mercado global com
uma proposta de valor vencedora
“...A gente vai gamar a
      cena toda...”
WSGI (Python)
 Rack (Ruby)
WSGI (PEP-333)
WSGI
•   Django       •   mod_wsgi

•   Bottle       •   Paste

•   CherryPy     •   gunicorn

•   Tornado      •   uWSGI

•   Pylons       •   wsgiref

•   Flask        •   Google AppEngine
Django              Bottle         Flask        Tornado


                                             WSGI middleware

                             WSGI


             wsgi handlers


Apache     lighttpd          nginx   mod_wsgi          GAE
Rack
Rack
•   Rails       •   Unicorn

•   Merb        •   Thin

•   Sinatra     •   Mongrel

•   Camping     •   Rainbows!

•   Ramaze      •   Phusion Passenger

•   etc.        •   Heroku
Rails              Merb          Sinatra     Ramaze


                                         Rack middleware

                             Rack


             Rack handlers


Apache     lighttpd          Thin    Unicorn      Mongrel
A prata da casa...
PSGI
Perl Web Server Gateway Interface
Interface++
Atenção!
   o próximo programa inclui
   cenas de Perl explicito, só
recomendadas a programadores
de Frameworks Perl, ou pessoas
à procura de novas experiências
# WSGI
def hello(environ, start_response):
 start_response(“200 OK”, [
   (‘Content-Type’, ‘text/plain’)
 ])
 return [“Hello World”]
# Rack
class Hello
 def call(env)
   return [
     200,
     { “Content-Type” => ”text/plain” },
     [“Hello World”]
   ]
 end
end
# PSGI
my $app = sub {
   my $env = shift;
   return [
      200,
      [ ‘Content-Type’, ‘text/plain’ ],
      [ ‘Hello World’ ],
   ];
};
Aplicação PSGI
  code reference
  $app = sub {...};
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
hashref com o ambiente
   $env:Variáveis ao estilo CGI
   + psgi.input, psgi.errors, etc.
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
Resposta
      array ref com três elementos
    código HTTP, headers (array ref)
e corpo da resposta (IO-like ou array ref)
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
$body
 IO::Handle-like
getline() e close()
IO::Handle::Util
Ajuda a converter uma coderef em algo parecido com
                   um IO::Handle
E ainda...
Interface para
streaming e/ou “non-
  blocking servers”
my $app = sub {
  my $env = shift;
  return sub {
    my $respond = shift;
    # Aqui podem delegar num event-loop estilo
    # POE ou AnyEvent para implementar cenas
    # tipo Comet
    $respond->([ $status, $header, $body ]);
  };
};
my $app = sub {
  my $env = shift;
  return sub {
    my $respond = shift;
    my $w = $respond->([ $status, $header ]);
    $w->write($body);
    $w->write($body);
    ...
    $w->close;
  };
};
Interface de Streaming
Inicialmente desenhado para servidores “non-blocking”
  Já disponível para a maioria dos servidores incluindo
                      CGI e Apache
Catalyst            CGI::App              Jifty        Tatsumaki


                                                    Plack::Middleware

                                PSGI


    Plack::Handler::* (CGI, FCGI, Apache)


Apache       lighttpd       HTTP::Server::PSGI      mod_psgi   Perlbal
E como estamos em
termos de adopção do
        PSGI?
Maypole Mason Mojo Sledge Catalyst Spoon PageKit
 AxKit Egg Gantry Continuity Solstice Mojolicious
Tripletail Konstrukt Reaction Jifty Cyclone3 WebGUI
  OpenInteract Squatting Dancer CGI::Application
 Nanoa Ark Angelos Noe Schenker Tatsumaki Amon
   Apache2::WebApp Web::Simple Apache2::REST
             SweetPea Hydrant Titanium
Maypole Mason Mojo Sledge Catalyst Spoon PageKit
 AxKit Egg Gantry Continuity Solstice Mojolicious
Tripletail Konstrukt Reaction Jifty Cyclone3 WebGUI
  OpenInteract Squatting Dancer CGI::Application
 Nanoa Ark Angelos Noe Schenker Tatsumaki Amon
   Apache2::WebApp Web::Simple Apache2::REST
             SweetPea Hydrant Titanium
Aplicações
Movable Type, WebGUI
# Catalyst
use MyApp;

MyApp->setup_engine(‘PSGI’);
my $app = sub { MyApp->run(@_) };

# $app é uma aplicação PSGI!
# Jifty
use MyPonyApp;
my $app = MyPonyApp->psgi_app;

# $app é uma aplicação PSGI!
# Dancer
use Dancer;

get ‘/’ => sub {
   “Hello World”;
};

use Dancer::Config ‘setting’;
setting apphandler => ‘PSGI’;

my $app = sub {
  my $r = Dancer::Request->new(shift);
  Dancer->dance($r);
};

# $app é uma aplicação PSGI!
# Mojolicious::Lite
use Mojolicious::Lite;

get ‘/:name’ => sub {
   my $self = shift;
   $self->render_text(‘Hello!’);
};

shagadelic; # devolve uma aplicação PSGI
# Web::Simple
use Web::Simple ‘MyApp’;

package MyApp;
dispatch {
  sub(GET) {
    [ 200, [...], [ ‘Hello’ ] ];
  }
};

my $app = MyApp->as_psgi;

# $app é uma aplicação PSGI!
Então o que isto do
      Plack?
Plack
“PSGI toolkit”
HTTP::Server::PSGI
 Implementação de referência de um
servidor Web com suporte para PSGI,
    incluído de base com o Plack
Plack::Handler
Liga aplicações PSGI a servidores Web
                  via
      CGI, FastCGI, Apache, SCGI
Plackup
Corre uma aplicação PSGI directamente a
      partir da linha de comandos
> plackup app.psgi
Bife+Salsicha+Linguiça
      +Fiambre
Middleware dos
amantes da francesinha
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

my $mw = sub {
   my $env = shift;
   # do something with $env
   my $res = $app->($env);
   # do something with $res;
   return $res;
};
Middleware
 Debug, Session, Logger, Runtime, Static, AccessLog,
  ConditionalGET, ErrorDocument, StackTrace,
Auth::Basic, Auth::Digest, ReverseProxy, Refresh etc.
           (“Importado” via Rack & Paste)
Plack::Middleware
framework extensível e reutilizável para
            criar Middleware
   Plack::Builder DSL para criar .psgi
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

builder {
  enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
  enable “Deflater”; # gzip/deflate
  $app;
}
Compatível com plackup
  plackup -e ‘enable “Foo”;’ app.psgi
Plack::App::URLMap
  Multiplex de várias aplicações
Integrado com a DSL do Builder
     (“Importado” do Rack)
use CatApp;
use CGIApp;

my $c1 = sub { CatApp->run };
my $c2 = sub { CGIApp->run_psgi };

use Plack::Builder;

builder {
  mount “/cat” => $c1;
  mount “/cgi-app” => builder {
    enable “StackTrace”;
    $c2;
  };
}
CGI::PSGI
Migração fácil para aplicações CGI.pm
CGI::Emulate::PSGI
     CGI::Compile
A maneira mais fácil para migrar aplicações CGI.pm
          (tipo Registry do mod_perl)
Plack::Request
semelhante ao libapreq (Apache::Request)
  APIs para developers de Middleware
Plack::Test
Interface para escrever testes para apps
                  PSGI
  suporta “mock” HTTP e “live” HTTP
use Plack::Test;
use HTTP::Request::Common;

my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

test_psgi app => $app, client => sub {
   my $cb = shift;
   my $req = GET “http://localhost/foo”;
   my $res = $cb->($req);
   # test $res;
};
use Plack::Test;
use HTTP::Request::Common;
$Plack::Test::Impl = “Server”;

my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

test_psgi app => $app, client => sub {
   my $cb = shift;
   my $req = GET “http://localhost/foo”;
   my $res = $cb->($req);
   # test $res;
};
Servidores Web PSGI
Starman
Servidor HTTP “Preforking” para UNIX (estilo Unicorn.rb)
 HTTP/1.1 chunk + keep-alives / “Estupidamente rápido”
Twiggy
Servidor Web “non-blocking” (estilo Thin.rb)
       utiliza a framework AnyEvent
Corona
Baseado no Coro.pm, utiliza co-rotinas para cada
                  pedido
HTTP::Server::Simple::PSGI
    Servidor com o mínimo de dependências
          (apenas HTTP::Server::Simple)
O melhor para correr aplicações sem outro servidor
nginx embedded perl
 http://github.com/yappo/nginx-psgi-patchs
mod_psgi
http://github.com/spiritloose/mod_psgi
evpsgi
http://github.com/sekimura/evpsgi
Perlbal plugin
http://github.com/miyagawa/Perlbal-Plugin-PSGI
uWSGI
http://projects.unbit.it/uwsgi/
Catalyst            CGI::App               Jifty        Tatsumaki


                                                     Plack::Middleware

                                PSGI


    Plack::Handler::* (CGI, FCGI, Apache)


Apache       lighttpd       HTTP::Server::PSGI       mod_psgi     Perlbal


Starman      Twiggy        uWSGI            Corona       evpsgi
Podem começar a
brincar com a coisa...
> cpanm Plack
> cpanm Task::Plack
Cloud?
(Heroku, GAE)
Sunaba
http://sunaba.plackperl.org/
Corre numa “sandbox”
    do Dan Kogai
(.... ele confia muito na
      sua sandbox ....)
Desilusões para script kiddies

    system(“rm -fr /”);
        while (1) { }
Resumo
• PSGI é o interface, Plack é uma
  implementação
• Temos vários servidores PSGI, muito bons
  e bem rápidos
• Temos adaptadores e ferramentas para a
  maioria das frameworks Web
• Pronto a usar!
Processo

• Partilhar é importante
• Utilizar as ideias das outras comunidades é
  um bom inicio
• Integrar algo com utilidade comprovada é
  excelente
Dúvidas?
Obrigado!
            Pedro Melo
{mailto,xmpp}:melo@simplicidade.org


http://github.com/miyagawa/Plack
        http://plackperl.org/
    http://blog.plackperl.org/
      irc://irc.perl.org/#plack

Plack