SlideShare ist ein Scribd-Unternehmen logo
1 von 323
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Understanding Android Benchmarks
Understanding Android BenchmarksUnderstanding Android Benchmarks
Understanding Android Benchmarks
Koan-Sin Tan
 

Was ist angesagt? (20)

Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
Enterprise Integration Patterns with Apache Camel
Enterprise Integration Patterns with Apache CamelEnterprise Integration Patterns with Apache Camel
Enterprise Integration Patterns with Apache Camel
 
High-speed Database Throughput Using Apache Arrow Flight SQL
High-speed Database Throughput Using Apache Arrow Flight SQLHigh-speed Database Throughput Using Apache Arrow Flight SQL
High-speed Database Throughput Using Apache Arrow Flight SQL
 
Networking in Java with NIO and Netty
Networking in Java with NIO and NettyNetworking in Java with NIO and Netty
Networking in Java with NIO and Netty
 
Under the Hood of a Shard-per-Core Database Architecture
Under the Hood of a Shard-per-Core Database ArchitectureUnder the Hood of a Shard-per-Core Database Architecture
Under the Hood of a Shard-per-Core Database Architecture
 
HTTP/3 in curl
HTTP/3 in curlHTTP/3 in curl
HTTP/3 in curl
 
Event-sourced architectures with Akka
Event-sourced architectures with AkkaEvent-sourced architectures with Akka
Event-sourced architectures with Akka
 
Node.js and the MySQL Document Store
Node.js and the MySQL Document StoreNode.js and the MySQL Document Store
Node.js and the MySQL Document Store
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and Groovy
 
In the DOM, no one will hear you scream
In the DOM, no one will hear you screamIn the DOM, no one will hear you scream
In the DOM, no one will hear you scream
 
Apache Arrow Flight Overview
Apache Arrow Flight OverviewApache Arrow Flight Overview
Apache Arrow Flight Overview
 
Understanding Android Benchmarks
Understanding Android BenchmarksUnderstanding Android Benchmarks
Understanding Android Benchmarks
 
Lost with data consistency
Lost with data consistencyLost with data consistency
Lost with data consistency
 
Linux networking
Linux networkingLinux networking
Linux networking
 
Real time replication using Kafka Connect
Real time replication using Kafka ConnectReal time replication using Kafka Connect
Real time replication using Kafka Connect
 
Introduction to Spark Internals
Introduction to Spark InternalsIntroduction to Spark Internals
Introduction to Spark Internals
 
Event-Driven Messaging and Actions using Apache Flink and Apache NiFi
Event-Driven Messaging and Actions using Apache Flink and Apache NiFiEvent-Driven Messaging and Actions using Apache Flink and Apache NiFi
Event-Driven Messaging and Actions using Apache Flink and Apache NiFi
 
Terraform 101
Terraform 101Terraform 101
Terraform 101
 
Reading The Source Code of Presto
Reading The Source Code of PrestoReading The Source Code of Presto
Reading The Source Code of Presto
 

Andere mochten auch

Perl &lt;b>5 Tutorial&lt;/b>, First Edition
Perl &lt;b>5 Tutorial&lt;/b>, First EditionPerl &lt;b>5 Tutorial&lt;/b>, First Edition
Perl &lt;b>5 Tutorial&lt;/b>, First Edition
tutorialsruby
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
Tatsuhiko Miyagawa
 
Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14
Masahiro Nagano
 
Perl hosting for beginners - Cluj.pm March 2013
Perl hosting for beginners - Cluj.pm March 2013Perl hosting for beginners - Cluj.pm March 2013
Perl hosting for beginners - Cluj.pm March 2013
Arpad Szasz
 
Presentacion Reunion 24 01 09
Presentacion Reunion 24 01 09Presentacion Reunion 24 01 09
Presentacion Reunion 24 01 09
pedro_i
 
Ppt 10 july 2007 2032
Ppt 10 july 2007 2032Ppt 10 july 2007 2032
Ppt 10 july 2007 2032
Miguel Mares
 

Andere mochten auch (20)

Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
Modern Core Perl
Modern Core PerlModern Core Perl
Modern Core Perl
 
PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
Dancer's Ecosystem
Dancer's EcosystemDancer's Ecosystem
Dancer's Ecosystem
 
Perl &lt;b>5 Tutorial&lt;/b>, First Edition
Perl &lt;b>5 Tutorial&lt;/b>, First EditionPerl &lt;b>5 Tutorial&lt;/b>, First Edition
Perl &lt;b>5 Tutorial&lt;/b>, First Edition
 
Your first website in under a minute with Dancer
Your first website in under a minute with DancerYour first website in under a minute with Dancer
Your first website in under a minute with Dancer
 
Perl in the Internet of Things
Perl in the Internet of ThingsPerl in the Internet of Things
Perl in the Internet of Things
 
Plack at OSCON 2010
Plack at OSCON 2010Plack at OSCON 2010
Plack at OSCON 2010
 
Message passing
Message passingMessage passing
Message passing
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
 
Web Development in Perl
Web Development in PerlWeb Development in Perl
Web Development in Perl
 
Mojolicious. The web in a box!
Mojolicious. The web in a box!Mojolicious. The web in a box!
Mojolicious. The web in a box!
 
Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14
 
Perl hosting for beginners - Cluj.pm March 2013
Perl hosting for beginners - Cluj.pm March 2013Perl hosting for beginners - Cluj.pm March 2013
Perl hosting for beginners - Cluj.pm March 2013
 
Iglesia asamblea de dios
Iglesia asamblea de diosIglesia asamblea de dios
Iglesia asamblea de dios
 
Discover JustFab success story with Lengow
Discover JustFab success story with LengowDiscover JustFab success story with Lengow
Discover JustFab success story with Lengow
 
Presentacion Reunion 24 01 09
Presentacion Reunion 24 01 09Presentacion Reunion 24 01 09
Presentacion Reunion 24 01 09
 
Pie diabetico..
Pie diabetico..Pie diabetico..
Pie diabetico..
 
Ppt 10 july 2007 2032
Ppt 10 july 2007 2032Ppt 10 july 2007 2032
Ppt 10 july 2007 2032
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 

Ähnlich wie Plack basics for Perl websites - YAPC::EU 2011

Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
Tatsuhiko Miyagawa
 
Movable Type 5.2 Overview at MTDDC 2012
Movable Type 5.2 Overview at MTDDC 2012Movable Type 5.2 Overview at MTDDC 2012
Movable Type 5.2 Overview at MTDDC 2012
Yuji Takayama
 
Apache2 BootCamp : Serving Dynamic Content with CGI
Apache2 BootCamp : Serving Dynamic Content with CGIApache2 BootCamp : Serving Dynamic Content with CGI
Apache2 BootCamp : Serving Dynamic Content with CGI
Wildan Maulana
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
som_nangia
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
wilburlo
 
Developing Rich Internet Applications with Perl and JavaScript
Developing Rich Internet Applications with Perl and JavaScriptDeveloping Rich Internet Applications with Perl and JavaScript
Developing Rich Internet Applications with Perl and JavaScript
nohuhu
 
Docs Python Org Howto Webservers Html
Docs Python Org Howto Webservers HtmlDocs Python Org Howto Webservers Html
Docs Python Org Howto Webservers Html
AkramWaseem
 
State of Developer Tools (WDS09)
State of Developer Tools (WDS09)State of Developer Tools (WDS09)
State of Developer Tools (WDS09)
bgalbs
 

Ähnlich wie Plack basics for Perl websites - YAPC::EU 2011 (20)

Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
 
Plack at YAPC::NA 2010
Plack at YAPC::NA 2010Plack at YAPC::NA 2010
Plack at YAPC::NA 2010
 
Movable Type 5.2 Overview at MTDDC 2012
Movable Type 5.2 Overview at MTDDC 2012Movable Type 5.2 Overview at MTDDC 2012
Movable Type 5.2 Overview at MTDDC 2012
 
Apache2 BootCamp : Serving Dynamic Content with CGI
Apache2 BootCamp : Serving Dynamic Content with CGIApache2 BootCamp : Serving Dynamic Content with CGI
Apache2 BootCamp : Serving Dynamic Content with CGI
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Crafting APIs
Crafting APIsCrafting APIs
Crafting APIs
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
Developing Brilliant and Powerful APIs in Ruby & Python
Developing Brilliant and Powerful APIs in Ruby & PythonDeveloping Brilliant and Powerful APIs in Ruby & Python
Developing Brilliant and Powerful APIs in Ruby & Python
 
Developing Rich Internet Applications with Perl and JavaScript
Developing Rich Internet Applications with Perl and JavaScriptDeveloping Rich Internet Applications with Perl and JavaScript
Developing Rich Internet Applications with Perl and JavaScript
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
Building dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apacheBuilding dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apache
 
Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020
 
Mastering Microservices with Kong (DevoxxUK 2019)
Mastering Microservices with Kong (DevoxxUK 2019)Mastering Microservices with Kong (DevoxxUK 2019)
Mastering Microservices with Kong (DevoxxUK 2019)
 
Beware the potholes
Beware the potholesBeware the potholes
Beware the potholes
 
Apigility – Lightning Fast API Development - OSSCamp 2014
Apigility – Lightning Fast API Development - OSSCamp 2014 Apigility – Lightning Fast API Development - OSSCamp 2014
Apigility – Lightning Fast API Development - OSSCamp 2014
 
Docs Python Org Howto Webservers Html
Docs Python Org Howto Webservers HtmlDocs Python Org Howto Webservers Html
Docs Python Org Howto Webservers Html
 
State of Developer Tools (WDS09)
State of Developer Tools (WDS09)State of Developer Tools (WDS09)
State of Developer Tools (WDS09)
 
Kubernetes API code-base tour
Kubernetes API code-base tourKubernetes API code-base tour
Kubernetes API code-base tour
 

Mehr von leo lapworth (6)

AWS CDK introduction
AWS CDK introductionAWS CDK introduction
AWS CDK introduction
 
Gitalist
GitalistGitalist
Gitalist
 
DBIx::Class introduction - 2010
DBIx::Class introduction - 2010DBIx::Class introduction - 2010
DBIx::Class introduction - 2010
 
DBIx::Class beginners
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginners
 
Evolving Architecture - Further
Evolving Architecture - FurtherEvolving Architecture - Further
Evolving Architecture - Further
 
Evolving Archetecture
Evolving ArchetectureEvolving Archetecture
Evolving Archetecture
 

Kürzlich hochgeladen

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
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
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
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
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 

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
  • 3. What is Plack? “Superglue for Perl 5 Web Frameworks and Web Servers”
  • 4. How will that help me?
  • 5. How will that help me? ‣ Flexibility
  • 6. How will that help me? ‣ Flexibility ‣ Middleware (plugins)
  • 7. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps
  • 8. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development
  • 9. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing
  • 10. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment
  • 11. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment ‣ World peace
  • 12. How will that help me? ‣ Flexibility ‣ Middleware (plugins) ‣ Apps ‣ Development ‣ Testing ‣ Deployment ‣ World peace
  • 15. #!/usr/bin/perl use strict; print “Content-Type: text/plainrnrn”; print “Hello World”;
  • 16. 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;
  • 17. use FCGI; my $req = FCGI::Request(); while ($req->Accept >= 0) { print “Content-Type: text/plainrnrn”; print “Hello World”; }
  • 18. 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;
  • 20. Painful to support all of them 
  • 21. There was one common way to do all of this.
  • 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
  • 29.
  • 30. 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
  • 31. Let’s look how they handled web servers.
  • 32. CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  • 33. CGI::Application Apache IIS lighttpd
  • 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
  • 44. CGI.pm Jifty, CGI::Application, Spoon mod_perl centric Mason, Sledge, PageKit, WebGUI Adapters Catalyst, Maypole, Squatting
  • 46. Gentleman thief & Double agent Miyagawa
  • 47. Acquired a great idea from Python/Ruby
  • 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. Rack
  • 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
  • 56. PSGI Perl ? Perl Web Server Gateway Interface
  • 60. PSGI application code reference $app = sub {...};
  • 61. # PSGI Hello World 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 a callback 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 a PSGI 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
  • 73. Plack::Handler Connects PSGI compatible apps to Web servers...
  • 76. Starman UNIX Preforking HTTP servers (like Unicorn.rb) HTTP/1.1 chunk + keep-alives / Very Fast
  • 77. HTTP::Server::Simple::PSGI Zero-deps other than 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
  • 80. nginx embedded perl http://github.com/yappo/nginx-psgi-patchs
  • 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
  • 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 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
  • 90. 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
  • 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 a framework
  • 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’; package MyApp; dispatch { sub(GET) { [ 200, [...], [ ‘Hello’ ] ]; } }; my $app = MyApp->as_psgi;
  • 101.
  • 102.
  • 103.
  • 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 app instantly from CLI (inspired by rackup)
  • 116. > plackup app.psgi HTTP::Server::PSGI: Accepting connections at http://0:5000/
  • 117. HTTP::Server::PSGI Reference PSGI 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....
  • 120.
  • 121. 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
  • 122. Plack Middleware Wraps a PSGI application to add pre/post processing
  • 123.
  • 127. Logging Status code redirect Error Handler Cache Middleware
  • 128. Logging Status code redirect Error Handler Cache Middleware Session Middleware
  • 129. Logging Status code redirect Error Handler Cache Middleware Session Middleware Routes Middleware
  • 130. Logging Status code redirect Error Handler 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 reusable and 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, run in every framework
  • 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 ]]; };
  • 168. return builder { # Precious debug info. Right on your page! enable 'Debug'; $app; }
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 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; }
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 188. First rule of Program Optimisation
  • 190. Second rule of Program Optimisation (for experts only)
  • 191. Don’t do it - yet!
  • 192. return builder { enable 'Debug', panels => [ [ 'Profiler::NYTProf' ] ]; $app; };
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 199. use Plack::Builder; return builder { enable "ServerStatus::Lite", path => '/server-status', allow => [ '127.0.0.1'], scoreboard => '/tmp/score'; $app; }
  • 200.
  • 201.
  • 202.
  • 203.
  • 205. use Plack::Builder; return builder { enable "SizeLimit", max_unshared_size_in_kb => 3000, check_every_n_requests => 5; $app; }
  • 207.
  • 208. 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
  • 211. Plack::App::Directory Static content file server
  • 212. Plack::App::Proxy (non-blocking) proxy server Can be used as reverse proxy as well
  • 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; }; }
  • 222. TemplateToolkit + Static
  • 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; }
  • 233. Slow website Website Developing code
  • 235. Slow website Caching Proxy 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; };
  • 239.
  • 240.
  • 241.
  • 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 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/;
  • 250. # 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/;
  • 251. # 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/;
  • 252. # 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/;
  • 253.
  • 254.
  • 255.
  • 256. Plack::Test Unified interface to write 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’; };
  • 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 full configuration!
  • 270. Use a reverse proxy
  • 271. Use a reverse proxy • Sits in front of servers, not clients - “reverse”
  • 272. Use a reverse proxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient
  • 273. Use a reverse proxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient • Add HTTPS easily
  • 274. Use a reverse proxy • Sits in front of servers, not clients - “reverse” • Makes servers more efficient • Add HTTPS easily • Makes scaling easier
  • 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}
  • 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 to change webserver (25+!) Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  • 293. 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
  • 295. Middleware • Easy to reuse with any PSGI app
  • 296. Middleware • Easy to reuse with any PSGI app • Many tools to make your life easy
  • 297. Middleware • Easy to reuse with any PSGI app • Many tools to make your life easy • 160+ on CPAN now
  • 298. App
  • 300. App • URLMapping / Routing • Static files
  • 301. App • URLMapping / Routing • Static files • Proxying
  • 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
  • 309. Testing • Testing your full configuration
  • 310. Testing • Testing your full configuration • Test::WWW::Mechanize::PSGI
  • 311. Testing • Testing your full configuration • Test::WWW::Mechanize::PSGI • Plack::Test
  • 313. Deployment • No separate configuration files
  • 314. Deployment • No separate configuration files • Easy to choose/change webserver
  • 315. Deployment • No separate configuration files • Easy to choose/change webserver • DotCloud etc - cloud deployment
  • 317. Summary ✦ PSGI is an interface, Plack is the code.
  • 318. Summary ✦ PSGI is an interface, Plack is the code. ✦ Many fast PSGI servers.
  • 319. Summary ✦ PSGI is an interface, Plack is the code. ✦ Many fast PSGI servers. ✦ Adapters and tools for frameworks and webservers.
  • 320. 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
  • 321. 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
  • 323. Thank you! Slides: http://slideshare.net/ranguard http://plackperl.org/ irc://irc.perl.org/#plack