Plack Basics
Leo Lapworth @ YAPC::EU 2011




  Much content from Tatsuhiko Miyagawa’s
          YAPC::NA 2010 talk
What is Plack?
What is Plack?

“Superglue for Perl 5 Web
  Frameworks and Web
        Servers”
How will that help me?
How will that help me?
‣ Flexibility
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
‣ Development
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
‣ Development
‣ Testing
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
‣ Development
‣ Testing
‣ Deployment
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
‣ Development
‣ Testing
‣ Deployment
‣ World peace
How will that help me?
‣ Flexibility
‣ Middleware (plugins)
‣ Apps
‣ Development
‣ Testing
‣ Deployment
‣ World peace
History...
Hello World
#!/usr/bin/perl
use strict;

print “Content-Type: text/plainrnrn”;
print “Hello World”;
package HelloWorld;
use strict;
use Apache::RequestRec;
use Apache::RequestIO;
use Apache::Const -compile => qw(OK);

sub handler {
  my $r = shift;

     $r->content_type(‘text/plain’);
     $r->print(“Hello World”);

     return Apache::Const::OK;
}

1;
use FCGI;

my $req = FCGI::Request();

while ($req->Accept >= 0) {

    print “Content-Type: text/plainrnrn”;
    print “Hello World”;

}
package HelloWorld;
use base qw(HTTP::Server::Simple::CGI);

sub handle_request {
  my($self, $cgi) = @_;

     print “HTTP/1.0 200 OKrn”;
     print “Content-Type: text/plainrnrn”;
     print “Hello World”;
}

1;
All similar
but slightly different
Painful to support
  all of them 
There was
one common way
 to do all of this.
CGI.pm
#!/usr/bin/perl
use CGI;

my $q = CGI->new;

print $q->header(‘text/plain’);
print “Hello World”;
Works under...
          CGI
        FastCGI
       mod_perl
HTTP::Server::Simple::CGI
CGI.pm

mod_perl    CGI     fastcgi



Apache       IIS    lighttpd
CGI.pm?
CGI.pm?
  meh
Frameworks
to the rescue!
Catalyst Maypole Mason Mojo Sledge 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
Let’s look how they
handled web servers.
CGI.pm

mod_perl    CGI     fastcgi



Apache       IIS    lighttpd
CGI::Application




Apache             IIS   lighttpd
CGI::Application




             CGI.pm




Apache             IIS   lighttpd
CGI::Application




             CGI.pm

 mod_perl          CGI   fastcgi



Apache             IIS   lighttpd
CGI::Application         Jifty




             CGI.pm

 mod_perl          CGI     fastcgi



Apache             IIS      lighttpd
CGI::Application         Jifty         Catalyst




             CGI.pm

 mod_perl          CGI     fastcgi



Apache             IIS      lighttpd
CGI::Application         Jifty               Catalyst




             CGI.pm                  Catalyst::Engine


 mod_perl          CGI     fastcgi



Apache             IIS      lighttpd
CGI::Application         Jifty               Catalyst




             CGI.pm                  Catalyst::Engine


 mod_perl          CGI     fastcgi



Apache             IIS      lighttpd          nginx
CGI::Application         Jifty               Catalyst




                            CGI.pm                  Catalyst::Engine


                mod_perl          CGI     fastcgi


HTTP::Server
  ::Simple     Apache             IIS      lighttpd          nginx
Mason          CGI::Application         Jifty               Catalyst




                            CGI.pm                  Catalyst::Engine


                mod_perl          CGI     fastcgi


HTTP::Server
  ::Simple     Apache             IIS      lighttpd          nginx
Mason           CGI::Application         Jifty               Catalyst




Mason::CGIHandler
                                 CGI.pm                  Catalyst::Engine


                     mod_perl          CGI     fastcgi


    HTTP::Server
      ::Simple      Apache             IIS      lighttpd          nginx
Gross.
CGI.pm
  Jifty, CGI::Application, Spoon


mod_perl centric
Mason, Sledge, PageKit, WebGUI


       Adapters
  Catalyst, Maypole, Squatting
That was 2008...
Gentleman thief &
            Double agent

Miyagawa
Acquired a great idea
 from Python/Ruby
WSGI (Python)
 Rack (Ruby)
WSGI (PEP-333)
WSGI Python Frameworks
 •   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 Ruby Frameworks
•   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
Perl ?
PSGI     Perl ?
Perl Web Server Gateway Interface
Interface
Interface
Interface
PSGI != Plack
PSGI application
   code reference
   $app = sub {...};
# PSGI Hello World
my $app = sub {
   my $env = shift;
   return [
      200,
      [ ‘Content-Type’, ‘text/plain’ ],
      [ ‘Hello World’ ],
   ];
};
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

         CGI-like environment variables
          + psgi.input, psgi.errors etc.
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};


     HTTP status code (int.): 200, 404 etc.
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

        Array reference of header pairs:
        [ ‘Content-Type’, ‘text/html’, ... ]
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

  String, array reference of content chunks,
     Filehandle or IO::Handle-ish object
That’s it.
(There’s a callback based streaming interface as well)
# PSGI
my $app = sub {
   my $env = shift;
   return [
      200,
      [ ‘Content-Type’, ‘text/plain’ ],
      [ ‘Hello World’ ],
   ];
};
Now you’ve got
a PSGI compatible
   application.
Mason            CGI::App           Jifty               Catalyst




Mason::CGIHandler
                               CGI.pm               Catalyst::Engine


                    mod_perl    CGI       fastcgi


    HTTP::Server
      ::Simple      Apache       IIS       lighttpd          nginx
Catalyst            CGI::App              Jifty         Mason 2


                                                    Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI      mod_psgi   Perlbal
Catalyst            CGI::App              Jifty         Mason 2


                                                    Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI      mod_psgi   Perlbal


                     other PSGI Webservers
Web Servers
Plack::Handler
Connects PSGI compatible apps
      to Web servers...
FCGI
Plack::Handler::FCGI
Apache
Plack::Handler::Apache1
Plack::Handler::Apache2
Starman
UNIX Preforking HTTP servers (like Unicorn.rb)
  HTTP/1.1 chunk + keep-alives / Very Fast
HTTP::Server::Simple::PSGI
 Zero-deps other than HTTP::Server::Simple
    Best for embedding PSGI applications
Twiggy
    Non-blocking web server (like Thin.rb)
       based on AnyEvent framework




                Starlet
        Simpler UNIX HTTP/1.0 Server
Best used with Server::Starter and nginx/lighttpd
Perlbal plugin
http://github.com/miyagawa/Perlbal-Plugin-PSGI
nginx embedded perl
 http://github.com/yappo/nginx-psgi-patchs
mod_psgi
http://github.com/spiritloose/mod_psgi
                Apache2
Corona                             uWSGI
Coroutine for each connection      http://projects.unbit.it/uwsgi/
     based on Coro.pm


     Feersum                              evpsgi
http://github.com/stash/Feersum http://github.com/sekimura/evpsgi


                        Gepok
                 http://metacpan/module/Gepok
                  Pure Perl standalone HTTPS
                     First released July 2011
Frameworks                 Apps            Your own code


                                           Plack::Middleware

                               PSGI


   Plack::Handler::* (CGI, FCGI, Apache)
Frameworks                  Apps                     Your own code


                                                 Plack::Middleware

                                PSGI


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


Apache       lighttpd       HTTP::Server::PSGI   mod_psgi       Perlbal


Starman      Twiggy        uWSGI            Corona         etc, etc
25+ Plack::Handlers
Adoption?
Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI   mod_psgi     Perlbal


Starman      Twiggy        uWSGI            Corona          etc
?
                                                 Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI   mod_psgi     Perlbal


Starman      Twiggy        uWSGI            Corona          etc
Catalyst Maypole Mason Mojo Sledge 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
Catalyst Maypole Mason Mojo Sledge 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
PSGI Perl Frameworks
•   Amon               •   Hydrant       •   Schenker

•   Angelos            •   Jifty         •   Sledge

•   Ark                •   Mason         •   Squatting

•   Catalyst           •   Maypole       •   Tatsumaki

•   CGI::Application   •   Mojo          •   Titanium

•   Continuity         •   Mojolicious   •   Web::Simple

•   Dancer             •   Noe
Applications
        Movable Type 6
           WebGUI 8
                RT4
   ACT (conference toolkit)
Bricolage (if someone gets time)
Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI   mod_psgi     Perlbal


Starman      Twiggy        uWSGI            Corona   evpsgi
Catalyst            CGI::App               Jifty        Tatsumaki

   Dancer            Mojoliscious            MT6           Mason 2

 Web::Simple          WebGui 8               Mojo            etc...

                                                     Plack::Middleware

                  PSGI Compatible App


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


Apache       lighttpd       HTTP::Server::PSGI       mod_psgi     Perlbal


Starman      Twiggy        uWSGI            Corona       evpsgi
PSGI from a framework
use Dancer;

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

dance;
use Mojolicious::Lite;

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

app->start;
use My::Jifty::App;

my $app = My::Jifty::App->psgi_app;
use Web::Simple ‘MyApp’;

package MyApp;

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

my $app = MyApp->as_psgi;
use My::Catalyst::App;

My::Catalyst::App->setup_engine(‘PSGI’);

my $app = sub {

  My::Catalyst::App->run(@_)

  };
catalyst.pl My::Catalyst::App
Plack
“PSGI implementation & toolkit”
Plack toolkit
Plack toolkit
Plack::Handlers   Connect PSGI apps and Web Servers
Plack toolkit
Plack::Handlers   Connect PSGI apps and Web Servers

   plackup        Command line launcher
Plack toolkit
Plack::Handlers   Connect PSGI apps and Web Servers

   plackup        Command line launcher

Plack::Loader     (auto)load Plack Servers
Plack toolkit
 Plack::Handlers    Connect PSGI apps and Web Servers

    plackup         Command line launcher

  Plack::Loader     (auto)load Plack Servers

Plack::Middleware   Easy-to-use PSGI Middleware
Plack toolkit
 Plack::Handlers    Connect PSGI apps and Web Servers

     plackup        Command line launcher

  Plack::Loader     (auto)load Plack Servers

Plack::Middleware   Easy-to-use PSGI Middleware

  Plack::Builder    OO & DSL to enable Middleware
Plack toolkit
 Plack::Handlers    Connect PSGI apps and Web Servers

     plackup        Command line launcher

  Plack::Loader     (auto)load Plack Servers

Plack::Middleware   Easy-to-use PSGI Middleware

  Plack::Builder    OO & DSL to enable Middleware

   Plack::Apps      Apps
Plack toolkit
 Plack::Handlers    Connect PSGI apps and Web Servers

     plackup        Command line launcher

  Plack::Loader     (auto)load Plack Servers

Plack::Middleware   Easy-to-use PSGI Middleware

  Plack::Builder    OO & DSL to enable Middleware

   Plack::Apps      Apps

   Plack::Test      Testing
plackup
Runs PSGI app instantly from CLI
      (inspired by rackup)
> plackup app.psgi
> plackup app.psgi
HTTP::Server::PSGI: Accepting
connections at http://0:5000/
HTTP::Server::PSGI
  Reference PSGI web server
       bundled in Plack

 Standalone, single-process HTTP server
    great for development and testing
Plack::Middleware
  (160+ modules - July 2011)
Middleware
        Debug, Session, Logger, Static, Lint,
AccessLog, ErrorDocument, StackTrace, Auth::Basic,
 Auth::Digest, ReverseProxy, Refresh, Auth::OAuth,
                    Throttle....
Chunked Class::Refresh Compile Conditional ConditionalGET
ConsoleLogger ContentLength ContentMD5 CrossOrigin
CSRFBlock Dancer::Debug DBIC::QueryLog Debug
Debug::CatalystPluginCache Debug::DBIC::QueryLog
Debug::DBIProfile Debug::Profiler::NYTProf Debug::W3CValidate
Deflater DoCoMoGUID Doorman ErrorDocument ESI ETag
Expires File::Sass Firebug::Lite FirePHP ForceEnv Head Header
HTMLify HTMLMinify HTTPExceptions IEnosniff IIS6ScriptNameFix
Image::Scale Inline InteractiveDebugger IPAddressFilter iPhone
JavaScript::Ectype JSConcat JSONP LighttpdScriptNameFix Lint
Log::Contextual Log::Minimal Log4perl LogDispatch LogWarn
MethodOverride Mirror NeverExpire NoDeflate NoMultipleSlashes
NullLogger Options OptionsOK Precompressed ProxyMap
RearrangeHeaders Recursive RefererCheck Refresh REPL Reproxy
ReverseProxy Rewrite Runtime Scope::Container Scope::Session
ServerStatus::Lite Session Session::SerializedCookie SetAccept
SimpleContentFilter SimpleLogger SizeLimit SocketIO SSI
StackTrace Static Static::Minifier StaticShared Status
Test::StashWarnings Throttle TMT UseChromeFrame Watermark
Plack Middleware
 Wraps a PSGI application
to add pre/post processing
Logging
Logging
Status code redirect
Logging
Status code redirect
Error Handler
Logging
Status code redirect
Error Handler
Cache Middleware
Logging
Status code redirect
Error Handler
Cache Middleware
Session Middleware
Logging
Status code redirect
Error Handler
Cache Middleware
Session Middleware
Routes Middleware
Logging
Status code redirect
Error Handler
Cache Middleware
Session Middleware
Routes Middleware
Your App
Plack::Middleware::A

      Plack::Middleware::B
                        PSGI Compatible App
Plack::Middleware::A

      Plack::Middleware::B
                        PSGI Compatible App




Request in
Plack::Middleware::A

      Plack::Middleware::B
                        PSGI Compatible App




Request in



        P::MW::A
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in



        P::MW::A


              P::MW::B
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in



        P::MW::A


              P::MW::B


                             PSGI App
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in



        P::MW::A


              P::MW::B                    P::MW::B


                             PSGI App
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in



        P::MW::A                               P::MW::A


              P::MW::B                    P::MW::B


                             PSGI App
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in                                           Response out



        P::MW::A                               P::MW::A


              P::MW::B                    P::MW::B


                             PSGI App
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in               e.g. Redirect               Response out



        P::MW::A                               P::MW::A


              P::MW::B                    P::MW::B


                             PSGI App
Plack::Middleware::A

      Plack::Middleware::B
                         PSGI Compatible App




Request in               e.g. Redirect                Response out



        P::MW::A                                P::MW::A
                             e.g. Static


              P::MW::B                     P::MW::B


                             PSGI App
Enabling
Plack::Middleware
  reusable and extensible
  Middleware framework
 Plack::Builder DSL in .psgi
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”;
   enable “B”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”;
   enable “B”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”;
   enable “B”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”;
   enable “B”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”; # Plack::Middleware::A
   enable “B”; # Order matters
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “A”;
   enable “B”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
   enable “Deflater”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
   enable “Deflater”;
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
   enable “Deflater”; # gzip/deflate
   $app;
}
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

return builder {
   enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
   enable “Deflater”;
   $app;
}
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in



             Static
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                        Response out
                        =~ ^/static

             Static
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                        Response out
                          =~ ^/static

             Static


                      -
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                        Response out
                          =~ ^/static

             Static


                      -


                              PSGI App
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                            Response out
                          =~ ^/static

             Static


                      -                   Deflate compresses


                              PSGI App
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                               Response out
                          =~ ^/static

             Static                                  -


                      -                   Deflate compresses


                              PSGI App
Plack::Middleware::Static

    Plack::Middleware::Deflate
                            PSGI Compatible App




Request in                                               Response out
                          =~ ^/static

             Static                                  -


                      -                   Deflate compresses


                              PSGI App
plackup compatible
plackup -e ‘enable “Foo”;’ app.psgi
Middleware
Write once, run in every framework
A few demos..
Assume...
use Plack::Builder;

my $body = ‘<html><body>Hello World</body></html>’;

my $app = sub {
  my $self = shift;

     return [200, ['Content-Type' => 'text/html'], [ $body ]];
};
Assume...
use Plack::Builder;

my $body = ‘<html><body>Hello World</body></html>’;

my $app = sub {
  my $self = shift;

     return [200, ['Content-Type' => 'text/html'], [ $body ]];
};
Assume...
use Plack::Builder;

my $body = ‘<html><body>Hello World</body></html>’;

my $app = sub {
  my $self = shift;

     return [200, ['Content-Type' => 'text/html'], [ $body ]];
};
Debugger
return builder {
   # Precious debug info. Right on your page!
   enable 'Debug';

    $app;
}
InteractiveDebugger
my $app = sub {
  my $foo = 'bar';
  die "oops" if $foo eq 'bar';

     [200, ['Content-Type' => 'text/html'], [ $body ]];
};

return builder {
   # Enable Interactive debugging
   enable "InteractiveDebugger";

     $app;
}
my $app = sub {
  my $foo = 'bar';
  die "oops" if $foo eq 'bar';

     [200, ['Content-Type' => 'text/html'], [ $body ]];
};

return builder {
   # Enable Interactive debugging
   enable "InteractiveDebugger";

     $app;
}
my $app = sub {
  my $foo = 'bar';
  die "oops" if $foo eq 'bar';

     [200, ['Content-Type' => 'text/html'], [ $body ]];
};

return builder {
   # Enable Interactive debugging
   enable "InteractiveDebugger";

     $app;
}
NYTProf - profiler
First rule of Program
    Optimisation
Don’t do it!
Second rule of Program
      Optimisation
   (for experts only)
Don’t do it -
   yet!
return builder {
   enable 'Debug', panels => [ [ 'Profiler::NYTProf' ] ];
   $app;
};
ServerStatus::Lite
use Plack::Builder;

return builder {
   enable "ServerStatus::Lite",
     path => '/server-status',
     allow => [ '127.0.0.1'],
     scoreboard => '/tmp/score';
   $app;
}
SizeLimit
use Plack::Builder;

return builder {
   enable "SizeLimit",
     max_unshared_size_in_kb => 3000,
     check_every_n_requests => 5;
   $app;
}
Plack::App::*
ready-to-use applications
Apache::ActionWrapper CGIBin Cascade
CocProxy DAV Directory Directory::Xslate
FCGIDispatcher File ImageMagick JSP PSGIBin
Path::Router Proxy
Proxy::Backend::AnyEvent::HTTP
Proxy::Backend::LWP Proxy::Selective Proxy::Test
URLMap WrapApacheReq
WrapApacheReq::FakeRequest WrapCGI
Plack::App::CGIBin
mount /cgi-bin as PSGI applications
CGI::PSGI
Easy migration from CGI.pm
Plack::App::Directory
   Static content file server
Plack::App::Proxy
    (non-blocking) proxy server
Can be used as reverse proxy as well
Plack::App::JSP
Runs JavaScript PSGI apps :)
# app.psgi - Javascript!
Plack::App::JSP->new( js => q{
  function respond(body) {
    return [ 200, [ 'Content-type', 'text/html' ], [ body ] ]
  }

   respond("Five factorial is " +
      (function(x) {
        if ( x<2 ) return x;
        return x * arguments.callee(x - 1);
      })(5)
   );
});
# app.psgi - Javascript!
Plack::App::JSP->new( js => q{
  function respond(body) {
    return [ 200, [ 'Content-type', 'text/html' ], [ body ] ]
  }

   respond("Five factorial is " +
      (function(x) {
        if ( x<2 ) return x;
        return x * arguments.callee(x - 1);
      })(5)
   );
});
Plack::App::URLMap
    Multiplex multiple apps
 Integrated with Builder DSL
use CatApp;
use CGIApp;

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

use Plack::Builder;

return builder {
  mount “/cat” => $c1;
  mount “/cgi-app” => builder {
    enable “StackTrace”;
    $c2;
  };
}
use CatApp;
use CGIApp;

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

use Plack::Builder;

return builder {
  mount “/cat” => $c1;
  mount “/cgi-app” => builder {
    enable “StackTrace”;
    $c2;
  };
}
use CatApp;
use CGIApp;

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

use Plack::Builder;

return builder {
  mount “/cat” => $c1;
  mount “/cgi-app” => builder {
    enable “StackTrace”;
    $c2;
  };
}
Some more demos...
Basic website
TemplateToolkit +
     Static
my $root = '/path/to/html_doc_root';

my $app = Plack::Middleware::TemplateToolkit->new(
   INCLUDE_PATH => root,
)->to_app;

return builder {

    enable 'Static',
      path =>
         qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$},
      root => $root;

    $app;
}
my $root = '/path/to/html_doc_root';

my $app = Plack::Middleware::TemplateToolkit->new(
   INCLUDE_PATH => root,
)->to_app;

return builder {

    enable 'Static',
      path =>
         qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$},
      root => $root;

    $app;
}
my $root = '/path/to/html_doc_root';

my $app = Plack::Middleware::TemplateToolkit->new(
   INCLUDE_PATH => root,
)->to_app;

return builder {

    enable 'Static',
      path =>
         qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$},
      root => $root;

    $app;
}
my $root = '/path/to/html_doc_root';

my $app = Plack::Middleware::TemplateToolkit->new(
   INCLUDE_PATH => root,
)->to_app;

return builder {

    enable 'Static',
      path =>
         qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$},
      root => $root;

    $app;
}
my $root = '/path/to/html_doc_root';

my $app = Plack::Middleware::TemplateToolkit->new(
   INCLUDE_PATH => root,
)->to_app;

return builder {

    enable 'Static',
      path =>
         qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$},
      root => $root;

    $app;
}
Creating utilities
Caching Proxy
Website
Website




Developing code
Website




Developing code
Slow website
    Website




Developing code
Slow website




Developing code
Slow website




 Caching Proxy




Developing code
use Plack::Middleware::Cache;
use Plack::App::Proxy;

my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

return builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache';
   $app;
};
use Plack::Middleware::Cache;
use Plack::App::Proxy;

my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

return builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache';
   $app;
};
use Plack::Middleware::Cache;
use Plack::App::Proxy;

my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

return builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache';
   $app;
};
use LWP::Simple;

my $content = get(‘http://localhost:5000/’);
Caching Proxy +
 Domain hijack
use LWP::Simple;

my $content = get(‘http://localhost:5000/’);
use LWP::Simple;

my $content = get(‘http://london.pm.org/’);
my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

return builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache2';
   $app;
};
my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

return builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache2';
   $app;
};
my $app
  = Plack::App::Proxy->new(
     remote => "http://london.pm.org/" )->to_app;

$app = builder {
   enable "Cache",
     match_url => '^/.*',        # everything
     cache_dir => '/tmp/plack-cache2';
   $app;
};
# Hijack Any LWP::Useragent requests
LWP::Protocol::PSGI->register($app);

use LWP::Simple;

my $content = get("http://london.pm.org/");

say 'o/' if $content =~ /London Perl Mongers/;
# Hijack Any LWP::Useragent requests
LWP::Protocol::PSGI->register($app);

use LWP::Simple;

my $content = get("http://london.pm.org/");

say 'o/' if $content =~ /London Perl Mongers/;
# Hijack Any LWP::Useragent requests
LWP::Protocol::PSGI->register($app);

use LWP::Simple;

my $content = get("http://london.pm.org/");

say 'o/' if $content =~ /London Perl Mongers/;
# Hijack Any LWP::Useragent requests
LWP::Protocol::PSGI->register($app);

use LWP::Simple;

my $content = get("http://london.pm.org/");

say 'o/' if $content =~ /London Perl Mongers/;
Plack::Test
Unified interface to write TAP tests
 with Mock HTTP and 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 $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
use Plack::Test;
use HTTP::Request::Common;

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

test_psgi
    app => $app,
    client => sub {
           my $callback = shift;
           my $req = GET “http://localhost/foo”;
            my $res = $callback->($req);
            ok $res->[0] == ‘200’, ‘Success’;
    };
Test::WWW::Mechanize::PSGI
use Test::WWW::Mechanize::PSGI;
 
my $mech =
    Test::WWW::Mechanize::PSGI->new(
     app => $app,
    );

$mech->get_ok('/');
use Test::WWW::Mechanize::PSGI;
 
my $mech =
    Test::WWW::Mechanize::PSGI->new(
     app => $app,
    );

$mech->get_ok('/');
Testing your full configuration!
Network setup tip
Use a reverse proxy
Use a reverse proxy
• Sits in front of servers, not clients - “reverse”
Use a reverse proxy
• Sits in front of servers, not clients - “reverse”
• Makes servers more efficient
Use a reverse proxy
• Sits in front of servers, not clients - “reverse”
• Makes servers more efficient
• Add HTTPS easily
Use a reverse proxy
• Sits in front of servers, not clients - “reverse”
• Makes servers more efficient
• Add HTTPS easily
• Makes scaling easier
Internet / Users




Webserver App
Internet / Users




Webserver App
Internet / Users




Webserver App
Internet / Users




Webserver App
Internet / Users

 Reverse Proxy
 NGINX   Perlbal   Pound




Webserver App
Internet / Users

 Reverse Proxy
 NGINX   Perlbal   Pound




Webserver App
Internet / Users

 Reverse Proxy
 NGINX   Perlbal   Pound




Webserver App
Internet / Users

 Reverse Proxy
 NGINX   Perlbal   Pound




Webserver App
Internet / Users

 Reverse Proxy
 NGINX   Perlbal   Pound




Webserver App
Reverse Proxy
NGINX    Perlbal   Pound




        Server
Reverse Proxy
  NGINX    Perlbal      Pound




Server 1             Server 2
Reverse Proxy
     NGINX     Perlbal   Pound




Server 1                  Server 3

             Server 2
Reverse Proxy
     NGINX     Perlbal   Pound




Server 1                  Server 3

             Server 2
Plack::Middleware::ReverseProxy

          Updates
 $env->{REMOTE_ADDRESS}
Why use Plack?
Why use Plack?
‣ Flexibility
‣ Middleware
‣ Apps
‣ Development
‣ Testing
‣ Deployment
Flexibility

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


Apache       lighttpd       HTTP::Server::PSGI   mod_psgi   Perlbal


Starman      Twiggy        uWSGI            Corona    etc
Flexibility
• Easy to change webserver (25+!)
        Plack::Handler::* (CGI, FCGI, Apache)


    Apache       lighttpd       HTTP::Server::PSGI   mod_psgi   Perlbal


    Starman      Twiggy        uWSGI            Corona    etc
Flexibility
• Easy to change webserver (25+!)
        Plack::Handler::* (CGI, FCGI, Apache)


    Apache       lighttpd       HTTP::Server::PSGI   mod_psgi   Perlbal


    Starman      Twiggy        uWSGI            Corona    etc




• Starman seems to be used most
Middleware
Middleware


• Easy to reuse with any PSGI app
Middleware


• Easy to reuse with any PSGI app
• Many tools to make your life easy
Middleware


• Easy to reuse with any PSGI app
• Many tools to make your life easy
• 160+ on CPAN now
App
App


• URLMapping / Routing
App


• URLMapping / Routing
• Static files
App


• URLMapping / Routing
• Static files
• Proxying
Development
Development

• plackup
Development

• plackup
• Restarter (monitor changes on disk)
Development

• plackup
• Restarter (monitor changes on disk)
• HTTP::Server::PSGI
Development

• plackup
• Restarter (monitor changes on disk)
• HTTP::Server::PSGI
• Debugging middleware
Development

• plackup
• Restarter (monitor changes on disk)
• HTTP::Server::PSGI
• Debugging middleware
• Profiler
Testing
Testing


• Testing your full configuration
Testing


• Testing your full configuration
• Test::WWW::Mechanize::PSGI
Testing


• Testing your full configuration
• Test::WWW::Mechanize::PSGI
• Plack::Test
Deployment
Deployment


• No separate configuration files
Deployment


• No separate configuration files
• Easy to choose/change webserver
Deployment


• No separate configuration files
• Easy to choose/change webserver
• DotCloud etc - cloud deployment
Summary
Summary
✦ PSGI is an interface, Plack is the code.
Summary
✦ PSGI is an interface, Plack is the code.
✦ Many fast PSGI servers.
Summary
✦ PSGI is an interface, Plack is the code.
✦ Many fast PSGI servers.
✦ Adapters and tools for frameworks and
  webservers.
Summary
✦ PSGI is an interface, Plack is the code.
✦ Many fast PSGI servers.
✦ Adapters and tools for frameworks and
  webservers.
✦ An amazing amount of middleware
Summary
✦ PSGI is an interface, Plack is the code.
✦ Many fast PSGI servers.
✦ Adapters and tools for frameworks and
  webservers.
✦ An amazing amount of middleware
✦ Used in many production systems
Use Plack
Thank you!
Slides: http://slideshare.net/ranguard

        http://plackperl.org/

      irc://irc.perl.org/#plack

Plack basics for Perl websites - YAPC::EU 2011

  • 1.
    Plack Basics Leo Lapworth@ YAPC::EU 2011 Much content from Tatsuhiko Miyagawa’s YAPC::NA 2010 talk
  • 2.
  • 3.
    What is Plack? “Supergluefor Perl 5 Web Frameworks and Web Servers”
  • 4.
    How will thathelp me?
  • 5.
    How will thathelp me? ‣ Flexibility
  • 6.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins)
  • 7.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps
  • 8.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development
  • 9.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing
  • 10.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment
  • 11.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment ‣ World peace
  • 12.
    How will thathelp me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment ‣ World peace
  • 13.
  • 14.
  • 15.
    #!/usr/bin/perl use strict; print “Content-Type:text/plainrnrn”; print “Hello World”;
  • 16.
    package HelloWorld; use strict; useApache::RequestRec; use Apache::RequestIO; use Apache::Const -compile => qw(OK); sub handler { my $r = shift; $r->content_type(‘text/plain’); $r->print(“Hello World”); return Apache::Const::OK; } 1;
  • 17.
    use FCGI; my $req= FCGI::Request(); while ($req->Accept >= 0) { print “Content-Type: text/plainrnrn”; print “Hello World”; }
  • 18.
    package HelloWorld; use baseqw(HTTP::Server::Simple::CGI); sub handle_request { my($self, $cgi) = @_; print “HTTP/1.0 200 OKrn”; print “Content-Type: text/plainrnrn”; print “Hello World”; } 1;
  • 19.
  • 20.
    Painful to support all of them 
  • 21.
    There was one commonway to do all of this.
  • 22.
  • 23.
    #!/usr/bin/perl use CGI; my $q= CGI->new; print $q->header(‘text/plain’); print “Hello World”;
  • 24.
    Works under... CGI FastCGI mod_perl HTTP::Server::Simple::CGI
  • 25.
    CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 26.
  • 27.
  • 28.
  • 30.
    Catalyst Maypole MasonMojo Sledge 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
  • 31.
    Let’s look howthey handled web servers.
  • 32.
    CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 33.
  • 34.
    CGI::Application CGI.pm Apache IIS lighttpd
  • 35.
    CGI::Application CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 36.
    CGI::Application Jifty CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 37.
    CGI::Application Jifty Catalyst CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 38.
    CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi Apache IIS lighttpd
  • 39.
    CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi Apache IIS lighttpd nginx
  • 40.
    CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  • 41.
    Mason CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  • 42.
    Mason CGI::Application Jifty Catalyst Mason::CGIHandler CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  • 43.
  • 44.
    CGI.pm Jifty,CGI::Application, Spoon mod_perl centric Mason, Sledge, PageKit, WebGUI Adapters Catalyst, Maypole, Squatting
  • 45.
  • 46.
    Gentleman thief & Double agent Miyagawa
  • 47.
    Acquired a greatidea from Python/Ruby
  • 48.
  • 49.
  • 50.
    WSGI Python Frameworks • Django • mod_wsgi • Bottle • Paste • CherryPy • gunicorn • Tornado • uWSGI • Pylons • wsgiref • Flask • Google AppEngine
  • 51.
    Django Bottle Flask Tornado WSGI middleware WSGI wsgi handlers Apache lighttpd nginx mod_wsgi GAE
  • 52.
  • 53.
    Rack Ruby Frameworks • Rails • Unicorn • Merb • Thin • Sinatra • Mongrel • Camping • Rainbows! • Ramaze • Phusion Passenger • etc. • Heroku
  • 54.
    Rails Merb Sinatra Ramaze Rack middleware Rack Rack handlers Apache lighttpd Thin Unicorn Mongrel
  • 55.
  • 56.
    PSGI Perl ? Perl Web Server Gateway Interface
  • 57.
  • 58.
  • 59.
  • 60.
    PSGI application code reference $app = sub {...};
  • 61.
    # PSGI HelloWorld my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; };
  • 62.
    my $app =sub { my $env = shift; return [ $status, $header, $body ]; }; CGI-like environment variables + psgi.input, psgi.errors etc.
  • 63.
    my $app =sub { my $env = shift; return [ $status, $header, $body ]; }; HTTP status code (int.): 200, 404 etc.
  • 64.
    my $app =sub { my $env = shift; return [ $status, $header, $body ]; }; Array reference of header pairs: [ ‘Content-Type’, ‘text/html’, ... ]
  • 65.
    my $app =sub { my $env = shift; return [ $status, $header, $body ]; }; String, array reference of content chunks, Filehandle or IO::Handle-ish object
  • 66.
    That’s it. (There’s acallback based streaming interface as well)
  • 67.
    # PSGI my $app= sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; };
  • 68.
    Now you’ve got aPSGI compatible application.
  • 69.
    Mason CGI::App Jifty Catalyst Mason::CGIHandler CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  • 70.
    Catalyst CGI::App Jifty Mason 2 Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal
  • 71.
    Catalyst CGI::App Jifty Mason 2 Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal other PSGI Webservers
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
    Starman UNIX Preforking HTTPservers (like Unicorn.rb) HTTP/1.1 chunk + keep-alives / Very Fast
  • 77.
    HTTP::Server::Simple::PSGI Zero-deps otherthan HTTP::Server::Simple Best for embedding PSGI applications
  • 78.
    Twiggy Non-blocking web server (like Thin.rb) based on AnyEvent framework Starlet Simpler UNIX HTTP/1.0 Server Best used with Server::Starter and nginx/lighttpd
  • 79.
  • 80.
    nginx embedded perl http://github.com/yappo/nginx-psgi-patchs
  • 81.
  • 82.
    Corona uWSGI Coroutine for each connection http://projects.unbit.it/uwsgi/ based on Coro.pm Feersum evpsgi http://github.com/stash/Feersum http://github.com/sekimura/evpsgi Gepok http://metacpan/module/Gepok Pure Perl standalone HTTPS First released July 2011
  • 83.
    Frameworks Apps Your own code Plack::Middleware PSGI Plack::Handler::* (CGI, FCGI, Apache)
  • 84.
    Frameworks Apps Your own code Plack::Middleware PSGI Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc, etc
  • 85.
  • 86.
  • 87.
    Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  • 88.
    ? Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  • 89.
    Catalyst Maypole MasonMojo Sledge 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
  • 90.
    Catalyst Maypole MasonMojo Sledge 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
  • 91.
    PSGI Perl Frameworks • Amon • Hydrant • Schenker • Angelos • Jifty • Sledge • Ark • Mason • Squatting • Catalyst • Maypole • Tatsumaki • CGI::Application • Mojo • Titanium • Continuity • Mojolicious • Web::Simple • Dancer • Noe
  • 92.
    Applications Movable Type 6 WebGUI 8 RT4 ACT (conference toolkit) Bricolage (if someone gets time)
  • 93.
    Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona evpsgi
  • 94.
    Catalyst CGI::App Jifty Tatsumaki Dancer Mojoliscious MT6 Mason 2 Web::Simple WebGui 8 Mojo etc... Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona evpsgi
  • 95.
    PSGI from aframework
  • 96.
    use Dancer; get ‘/’=> sub { “Hello World”; }; dance;
  • 97.
    use Mojolicious::Lite; get ‘/:name’=> sub { my $self = shift; $self->render_text(‘Hello!’); }; app->start;
  • 98.
    use My::Jifty::App; my $app= My::Jifty::App->psgi_app;
  • 99.
    use Web::Simple ‘MyApp’; packageMyApp; dispatch { sub(GET) { [ 200, [...], [ ‘Hello’ ] ]; } }; my $app = MyApp->as_psgi;
  • 100.
  • 104.
  • 105.
  • 106.
  • 107.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers
  • 108.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher
  • 109.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack Servers
  • 110.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack Servers Plack::Middleware Easy-to-use PSGI Middleware
  • 111.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack Servers Plack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware
  • 112.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack Servers Plack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware Plack::Apps Apps
  • 113.
    Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack Servers Plack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware Plack::Apps Apps Plack::Test Testing
  • 114.
    plackup Runs PSGI appinstantly from CLI (inspired by rackup)
  • 115.
  • 116.
    > plackup app.psgi HTTP::Server::PSGI:Accepting connections at http://0:5000/
  • 117.
    HTTP::Server::PSGI ReferencePSGI web server bundled in Plack Standalone, single-process HTTP server great for development and testing
  • 118.
    Plack::Middleware (160+modules - July 2011)
  • 119.
    Middleware Debug, Session, Logger, Static, Lint, AccessLog, ErrorDocument, StackTrace, Auth::Basic, Auth::Digest, ReverseProxy, Refresh, Auth::OAuth, Throttle....
  • 121.
    Chunked Class::Refresh CompileConditional ConditionalGET ConsoleLogger ContentLength ContentMD5 CrossOrigin CSRFBlock Dancer::Debug DBIC::QueryLog Debug Debug::CatalystPluginCache Debug::DBIC::QueryLog Debug::DBIProfile Debug::Profiler::NYTProf Debug::W3CValidate Deflater DoCoMoGUID Doorman ErrorDocument ESI ETag Expires File::Sass Firebug::Lite FirePHP ForceEnv Head Header HTMLify HTMLMinify HTTPExceptions IEnosniff IIS6ScriptNameFix Image::Scale Inline InteractiveDebugger IPAddressFilter iPhone JavaScript::Ectype JSConcat JSONP LighttpdScriptNameFix Lint Log::Contextual Log::Minimal Log4perl LogDispatch LogWarn MethodOverride Mirror NeverExpire NoDeflate NoMultipleSlashes NullLogger Options OptionsOK Precompressed ProxyMap RearrangeHeaders Recursive RefererCheck Refresh REPL Reproxy ReverseProxy Rewrite Runtime Scope::Container Scope::Session ServerStatus::Lite Session Session::SerializedCookie SetAccept SimpleContentFilter SimpleLogger SizeLimit SocketIO SSI StackTrace Static Static::Minifier StaticShared Status Test::StashWarnings Throttle TMT UseChromeFrame Watermark
  • 122.
    Plack Middleware Wrapsa PSGI application to add pre/post processing
  • 124.
  • 125.
  • 126.
  • 127.
    Logging Status code redirect ErrorHandler Cache Middleware
  • 128.
    Logging Status code redirect ErrorHandler Cache Middleware Session Middleware
  • 129.
    Logging Status code redirect ErrorHandler Cache Middleware Session Middleware Routes Middleware
  • 130.
    Logging Status code redirect ErrorHandler Cache Middleware Session Middleware Routes Middleware Your App
  • 131.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App
  • 132.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in
  • 133.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A
  • 134.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B
  • 135.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B PSGI App
  • 136.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B P::MW::B PSGI App
  • 137.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  • 138.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in Response out P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  • 139.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in e.g. Redirect Response out P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  • 140.
    Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in e.g. Redirect Response out P::MW::A P::MW::A e.g. Static P::MW::B P::MW::B PSGI App
  • 141.
    Enabling Plack::Middleware reusableand extensible Middleware framework Plack::Builder DSL in .psgi
  • 142.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; enable “B”; $app; }
  • 143.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; enable “B”; $app; }
  • 144.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; enable “B”; $app; }
  • 145.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; enable “B”; $app; }
  • 146.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; # Plack::Middleware::A enable “B”; # Order matters $app; }
  • 147.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “A”; enable “B”; $app; }
  • 148.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app; }
  • 149.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app; }
  • 150.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; # gzip/deflate $app; }
  • 151.
    my $app =sub { return [ $status, $header, $body ]; }; use Plack::Builder; return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app; }
  • 152.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App
  • 153.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in
  • 154.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Static
  • 155.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static
  • 156.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static -
  • 157.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - PSGI App
  • 158.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - Deflate compresses PSGI App
  • 159.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - - Deflate compresses PSGI App
  • 160.
    Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - - Deflate compresses PSGI App
  • 161.
    plackup compatible plackup -e‘enable “Foo”;’ app.psgi
  • 162.
    Middleware Write once, runin every framework
  • 163.
  • 164.
    Assume... use Plack::Builder; my $body= ‘<html><body>Hello World</body></html>’; my $app = sub { my $self = shift; return [200, ['Content-Type' => 'text/html'], [ $body ]]; };
  • 165.
    Assume... use Plack::Builder; my $body= ‘<html><body>Hello World</body></html>’; my $app = sub { my $self = shift; return [200, ['Content-Type' => 'text/html'], [ $body ]]; };
  • 166.
    Assume... use Plack::Builder; my $body= ‘<html><body>Hello World</body></html>’; my $app = sub { my $self = shift; return [200, ['Content-Type' => 'text/html'], [ $body ]]; };
  • 167.
  • 168.
    return builder { # Precious debug info. Right on your page! enable 'Debug'; $app; }
  • 177.
  • 178.
    my $app =sub { my $foo = 'bar'; die "oops" if $foo eq 'bar'; [200, ['Content-Type' => 'text/html'], [ $body ]]; }; return builder { # Enable Interactive debugging enable "InteractiveDebugger"; $app; }
  • 179.
    my $app =sub { my $foo = 'bar'; die "oops" if $foo eq 'bar'; [200, ['Content-Type' => 'text/html'], [ $body ]]; }; return builder { # Enable Interactive debugging enable "InteractiveDebugger"; $app; }
  • 180.
    my $app =sub { my $foo = 'bar'; die "oops" if $foo eq 'bar'; [200, ['Content-Type' => 'text/html'], [ $body ]]; }; return builder { # Enable Interactive debugging enable "InteractiveDebugger"; $app; }
  • 187.
  • 188.
    First rule ofProgram Optimisation
  • 189.
  • 190.
    Second rule ofProgram Optimisation (for experts only)
  • 191.
  • 192.
    return builder { enable 'Debug', panels => [ [ 'Profiler::NYTProf' ] ]; $app; };
  • 198.
  • 199.
    use Plack::Builder; return builder{ enable "ServerStatus::Lite", path => '/server-status', allow => [ '127.0.0.1'], scoreboard => '/tmp/score'; $app; }
  • 204.
  • 205.
    use Plack::Builder; return builder{ enable "SizeLimit", max_unshared_size_in_kb => 3000, check_every_n_requests => 5; $app; }
  • 206.
  • 208.
    Apache::ActionWrapper CGIBin Cascade CocProxyDAV Directory Directory::Xslate FCGIDispatcher File ImageMagick JSP PSGIBin Path::Router Proxy Proxy::Backend::AnyEvent::HTTP Proxy::Backend::LWP Proxy::Selective Proxy::Test URLMap WrapApacheReq WrapApacheReq::FakeRequest WrapCGI
  • 209.
  • 210.
  • 211.
    Plack::App::Directory Static content file server
  • 212.
    Plack::App::Proxy (non-blocking) proxy server Can be used as reverse proxy as well
  • 213.
  • 214.
    # app.psgi -Javascript! Plack::App::JSP->new( js => q{ function respond(body) { return [ 200, [ 'Content-type', 'text/html' ], [ body ] ] } respond("Five factorial is " + (function(x) { if ( x<2 ) return x; return x * arguments.callee(x - 1); })(5) ); });
  • 215.
    # app.psgi -Javascript! Plack::App::JSP->new( js => q{ function respond(body) { return [ 200, [ 'Content-type', 'text/html' ], [ body ] ] } respond("Five factorial is " + (function(x) { if ( x<2 ) return x; return x * arguments.callee(x - 1); })(5) ); });
  • 216.
    Plack::App::URLMap Multiplex multiple apps Integrated with Builder DSL
  • 217.
    use CatApp; use CGIApp; my$c1 = sub { CatApp->run }; my $c2 = sub { CGIApp->run_psgi }; use Plack::Builder; return builder { mount “/cat” => $c1; mount “/cgi-app” => builder { enable “StackTrace”; $c2; }; }
  • 218.
    use CatApp; use CGIApp; my$c1 = sub { CatApp->run }; my $c2 = sub { CGIApp->run_psgi }; use Plack::Builder; return builder { mount “/cat” => $c1; mount “/cgi-app” => builder { enable “StackTrace”; $c2; }; }
  • 219.
    use CatApp; use CGIApp; my$c1 = sub { CatApp->run }; my $c2 = sub { CGIApp->run_psgi }; use Plack::Builder; return builder { mount “/cat” => $c1; mount “/cgi-app” => builder { enable “StackTrace”; $c2; }; }
  • 220.
  • 221.
  • 222.
  • 223.
    my $root ='/path/to/html_doc_root'; my $app = Plack::Middleware::TemplateToolkit->new( INCLUDE_PATH => root, )->to_app; return builder { enable 'Static', path => qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$}, root => $root; $app; }
  • 224.
    my $root ='/path/to/html_doc_root'; my $app = Plack::Middleware::TemplateToolkit->new( INCLUDE_PATH => root, )->to_app; return builder { enable 'Static', path => qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$}, root => $root; $app; }
  • 225.
    my $root ='/path/to/html_doc_root'; my $app = Plack::Middleware::TemplateToolkit->new( INCLUDE_PATH => root, )->to_app; return builder { enable 'Static', path => qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$}, root => $root; $app; }
  • 226.
    my $root ='/path/to/html_doc_root'; my $app = Plack::Middleware::TemplateToolkit->new( INCLUDE_PATH => root, )->to_app; return builder { enable 'Static', path => qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$}, root => $root; $app; }
  • 227.
    my $root ='/path/to/html_doc_root'; my $app = Plack::Middleware::TemplateToolkit->new( INCLUDE_PATH => root, )->to_app; return builder { enable 'Static', path => qr{.[gif|png|jpg|swf|ico|mov|mp3|pdf|js|css]$}, root => $root; $app; }
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
    Slow website Website Developing code
  • 234.
  • 235.
    Slow website CachingProxy Developing code
  • 236.
    use Plack::Middleware::Cache; use Plack::App::Proxy; my$app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; return builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache'; $app; };
  • 237.
    use Plack::Middleware::Cache; use Plack::App::Proxy; my$app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; return builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache'; $app; };
  • 238.
    use Plack::Middleware::Cache; use Plack::App::Proxy; my$app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; return builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache'; $app; };
  • 242.
    use LWP::Simple; my $content= get(‘http://localhost:5000/’);
  • 243.
    Caching Proxy + Domain hijack
  • 244.
    use LWP::Simple; my $content= get(‘http://localhost:5000/’);
  • 245.
    use LWP::Simple; my $content= get(‘http://london.pm.org/’);
  • 246.
    my $app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; return builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache2'; $app; };
  • 247.
    my $app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; return builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache2'; $app; };
  • 248.
    my $app = Plack::App::Proxy->new( remote => "http://london.pm.org/" )->to_app; $app = builder { enable "Cache", match_url => '^/.*', # everything cache_dir => '/tmp/plack-cache2'; $app; };
  • 249.
    # Hijack AnyLWP::Useragent requests LWP::Protocol::PSGI->register($app); use LWP::Simple; my $content = get("http://london.pm.org/"); say 'o/' if $content =~ /London Perl Mongers/;
  • 250.
    # Hijack AnyLWP::Useragent requests LWP::Protocol::PSGI->register($app); use LWP::Simple; my $content = get("http://london.pm.org/"); say 'o/' if $content =~ /London Perl Mongers/;
  • 251.
    # Hijack AnyLWP::Useragent requests LWP::Protocol::PSGI->register($app); use LWP::Simple; my $content = get("http://london.pm.org/"); say 'o/' if $content =~ /London Perl Mongers/;
  • 252.
    # Hijack AnyLWP::Useragent requests LWP::Protocol::PSGI->register($app); use LWP::Simple; my $content = get("http://london.pm.org/"); say 'o/' if $content =~ /London Perl Mongers/;
  • 256.
    Plack::Test Unified interface towrite TAP tests with Mock HTTP and Live HTTP
  • 257.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 258.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 259.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 260.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 261.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 262.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 263.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 264.
    use Plack::Test; use HTTP::Request::Common; my$app = sub { my $env = shift; return [ $status, $header, $body ]; }; test_psgi app => $app, client => sub { my $callback = shift; my $req = GET “http://localhost/foo”; my $res = $callback->($req); ok $res->[0] == ‘200’, ‘Success’; };
  • 265.
  • 266.
    use Test::WWW::Mechanize::PSGI;   my $mech= Test::WWW::Mechanize::PSGI->new(      app => $app, ); $mech->get_ok('/');
  • 267.
    use Test::WWW::Mechanize::PSGI;   my $mech= Test::WWW::Mechanize::PSGI->new(      app => $app, ); $mech->get_ok('/');
  • 268.
    Testing your fullconfiguration!
  • 269.
  • 270.
  • 271.
    Use a reverseproxy • Sits in front of servers, not clients - “reverse”
  • 272.
    Use a reverseproxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient
  • 273.
    Use a reverseproxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient • Add HTTPS easily
  • 274.
    Use a reverseproxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient • Add HTTPS easily • Makes scaling easier
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
    Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  • 280.
    Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  • 281.
    Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  • 282.
    Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  • 283.
    Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  • 284.
    Reverse Proxy NGINX Perlbal Pound Server
  • 285.
    Reverse Proxy NGINX Perlbal Pound Server 1 Server 2
  • 286.
    Reverse Proxy NGINX Perlbal Pound Server 1 Server 3 Server 2
  • 287.
    Reverse Proxy NGINX Perlbal Pound Server 1 Server 3 Server 2
  • 288.
    Plack::Middleware::ReverseProxy Updates $env->{REMOTE_ADDRESS}
  • 289.
  • 290.
    Why use Plack? ‣Flexibility ‣ Middleware ‣ Apps ‣ Development ‣ Testing ‣ Deployment
  • 291.
    Flexibility Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  • 292.
    Flexibility • Easy tochange webserver (25+!) Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  • 293.
    Flexibility • Easy tochange webserver (25+!) Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc • Starman seems to be used most
  • 294.
  • 295.
    Middleware • Easy toreuse with any PSGI app
  • 296.
    Middleware • Easy toreuse with any PSGI app • Many tools to make your life easy
  • 297.
    Middleware • Easy toreuse with any PSGI app • Many tools to make your life easy • 160+ on CPAN now
  • 298.
  • 299.
  • 300.
    App • URLMapping /Routing • Static files
  • 301.
    App • URLMapping /Routing • Static files • Proxying
  • 302.
  • 303.
  • 304.
    Development • plackup • Restarter(monitor changes on disk)
  • 305.
    Development • plackup • Restarter(monitor changes on disk) • HTTP::Server::PSGI
  • 306.
    Development • plackup • Restarter(monitor changes on disk) • HTTP::Server::PSGI • Debugging middleware
  • 307.
    Development • plackup • Restarter(monitor changes on disk) • HTTP::Server::PSGI • Debugging middleware • Profiler
  • 308.
  • 309.
    Testing • Testing yourfull configuration
  • 310.
    Testing • Testing yourfull configuration • Test::WWW::Mechanize::PSGI
  • 311.
    Testing • Testing yourfull configuration • Test::WWW::Mechanize::PSGI • Plack::Test
  • 312.
  • 313.
    Deployment • No separateconfiguration files
  • 314.
    Deployment • No separateconfiguration files • Easy to choose/change webserver
  • 315.
    Deployment • No separateconfiguration files • Easy to choose/change webserver • DotCloud etc - cloud deployment
  • 316.
  • 317.
    Summary ✦ PSGI isan interface, Plack is the code.
  • 318.
    Summary ✦ PSGI isan interface, Plack is the code. ✦ Many fast PSGI servers.
  • 319.
    Summary ✦ PSGI isan interface, Plack is the code. ✦ Many fast PSGI servers. ✦ Adapters and tools for frameworks and webservers.
  • 320.
    Summary ✦ PSGI isan interface, Plack is the code. ✦ Many fast PSGI servers. ✦ Adapters and tools for frameworks and webservers. ✦ An amazing amount of middleware
  • 321.
    Summary ✦ PSGI isan interface, Plack is the code. ✦ Many fast PSGI servers. ✦ Adapters and tools for frameworks and webservers. ✦ An amazing amount of middleware ✦ Used in many production systems
  • 322.
  • 323.
    Thank you! Slides: http://slideshare.net/ranguard http://plackperl.org/ irc://irc.perl.org/#plack