Your SlideShare is downloading. ×
0
Plack BasicsLeo 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/perluse 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 handle...
use FCGI;my $req = FCGI::Request();while ($req->Accept >= 0) {    print “Content-Type: text/plainrnrn”;    print “Hello Wo...
package HelloWorld;use base qw(HTTP::Server::Simple::CGI);sub handle_request {  my($self, $cgi) = @_;     print “HTTP/1.0 ...
All similarbut slightly different
Painful to support  all of them 
There wasone common way to do all of this.
CGI.pm
#!/usr/bin/perluse CGI;my $q = CGI->new;print $q->header(‘text/plain’);print “Hello World”;
Works under...          CGI        FastCGI       mod_perlHTTP::Server::Simple::CGI
CGI.pmmod_perl    CGI     fastcgiApache       IIS    lighttpd
CGI.pm?
CGI.pm?  meh
Frameworksto the rescue!
Catalyst Maypole Mason Mojo Sledge Spoon PageKit AxKit Egg Gantry Continuity Solstice Mojolicious Tripletail Konstrukt Rea...
Let’s look how theyhandled web servers.
CGI.pmmod_perl    CGI     fastcgiApache       IIS    lighttpd
CGI::ApplicationApache             IIS   lighttpd
CGI::Application             CGI.pmApache             IIS   lighttpd
CGI::Application             CGI.pm mod_perl          CGI   fastcgiApache             IIS   lighttpd
CGI::Application         Jifty             CGI.pm mod_perl          CGI     fastcgiApache             IIS      lighttpd
CGI::Application         Jifty         Catalyst             CGI.pm mod_perl          CGI     fastcgiApache             IIS...
CGI::Application         Jifty               Catalyst             CGI.pm                  Catalyst::Engine mod_perl       ...
CGI::Application         Jifty               Catalyst             CGI.pm                  Catalyst::Engine mod_perl       ...
CGI::Application         Jifty               Catalyst                            CGI.pm                  Catalyst::Engine ...
Mason          CGI::Application         Jifty               Catalyst                            CGI.pm                  Ca...
Mason           CGI::Application         Jifty               CatalystMason::CGIHandler                                 CGI...
Gross.
CGI.pm  Jifty, CGI::Application, Spoonmod_perl centricMason, Sledge, PageKit, WebGUI       Adapters  Catalyst, Maypole, Sq...
That was 2008...
Gentleman thief &            Double agentMiyagawa
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    •  ...
Django              Bottle         Flask        Tornado                                             WSGI middleware       ...
Rack
Rack Ruby Frameworks•   Rails     •   Unicorn•   Merb      •   Thin•   Sinatra   •   Mongrel•   Camping   •   Rainbows!•  ...
Rails              Merb          Sinatra     Ramaze                                         Rack middleware               ...
Perl ?
PSGI     Perl ?Perl Web Server Gateway Interface
Interface
Interface
InterfacePSGI != Plack
PSGI application   code reference   $app = sub {...};
# PSGI Hello Worldmy $app = sub {   my $env = shift;   return [      200,      [ ‘Content-Type’, ‘text/plain’ ],      [ ‘H...
my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};         CGI-like environment variables         ...
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:        ...
my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};  String, array reference of content chunks,    ...
That’s it.(There’s a callback based streaming interface as well)
# PSGImy $app = sub {   my $env = shift;   return [      200,      [ ‘Content-Type’, ‘text/plain’ ],      [ ‘Hello World’ ...
Now you’ve gota PSGI compatible   application.
Mason            CGI::App           Jifty               CatalystMason::CGIHandler                               CGI.pm    ...
Catalyst            CGI::App              Jifty         Mason 2                                                    Plack::...
Catalyst            CGI::App              Jifty         Mason 2                                                    Plack::...
Web Servers
Plack::HandlerConnects PSGI compatible apps      to Web servers...
FCGIPlack::Handler::FCGI
ApachePlack::Handler::Apache1Plack::Handler::Apache2
StarmanUNIX 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 U...
Perlbal pluginhttp://github.com/miyagawa/Perlbal-Plugin-PSGI
nginx embedded perl http://github.com/yappo/nginx-psgi-patchs
mod_psgihttp://github.com/spiritloose/mod_psgi                Apache2
Corona                             uWSGICoroutine for each connection      http://projects.unbit.it/uwsgi/     based on Co...
Frameworks                 Apps            Your own code                                           Plack::Middleware      ...
Frameworks                  Apps                     Your own code                                                 Plack::...
25+ Plack::Handlers
Adoption?
Plack::Middleware                  PSGI Compatible App    Plack::Handler::* (CGI, FCGI, Apache)Apache       lighttpd      ...
?                                                 Plack::Middleware                  PSGI Compatible App    Plack::Handler...
Catalyst Maypole Mason Mojo Sledge Spoon PageKit AxKit Egg Gantry Continuity Solstice MojoliciousTripletail Konstrukt Reac...
Catalyst Maypole Mason Mojo Sledge Spoon PageKit AxKit Egg Gantry Continuity Solstice MojoliciousTripletail Konstrukt Reac...
PSGI Perl Frameworks•   Amon               •   Hydrant       •   Schenker•   Angelos            •   Jifty         •   Sled...
Applications        Movable Type 6           WebGUI 8                RT4   ACT (conference toolkit)Bricolage (if someone g...
Plack::Middleware                  PSGI Compatible App    Plack::Handler::* (CGI, FCGI, Apache)Apache       lighttpd      ...
Catalyst            CGI::App               Jifty        Tatsumaki   Dancer            Mojoliscious            MT6         ...
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 toolkitPlack::Handlers   Connect PSGI apps and Web Servers
Plack toolkitPlack::Handlers   Connect PSGI apps and Web Servers   plackup        Command line launcher
Plack toolkitPlack::Handlers   Connect PSGI apps and Web Servers   plackup        Command line launcherPlack::Loader     (...
Plack toolkit Plack::Handlers    Connect PSGI apps and Web Servers    plackup         Command line launcher  Plack::Loader...
Plack toolkit Plack::Handlers    Connect PSGI apps and Web Servers     plackup        Command line launcher  Plack::Loader...
Plack toolkit Plack::Handlers    Connect PSGI apps and Web Servers     plackup        Command line launcher  Plack::Loader...
Plack toolkit Plack::Handlers    Connect PSGI apps and Web Servers     plackup        Command line launcher  Plack::Loader...
plackupRuns PSGI app instantly from CLI      (inspired by rackup)
> plackup app.psgi
> plackup app.psgiHTTP::Server::PSGI: Acceptingconnections at http://0:5000/
HTTP::Server::PSGI  Reference PSGI web server       bundled in Plack Standalone, single-process HTTP server    great for d...
Plack::Middleware  (160+ modules - July 2011)
Middleware        Debug, Session, Logger, Static, Lint,AccessLog, ErrorDocument, StackTrace, Auth::Basic, Auth::Digest, Re...
Chunked Class::Refresh Compile Conditional ConditionalGETConsoleLogger ContentLength ContentMD5 CrossOriginCSRFBlock Dance...
Plack Middleware Wraps a PSGI applicationto add pre/post processing
Logging
LoggingStatus code redirect
LoggingStatus code redirectError Handler
LoggingStatus code redirectError HandlerCache Middleware
LoggingStatus code redirectError HandlerCache MiddlewareSession Middleware
LoggingStatus code redirectError HandlerCache MiddlewareSession MiddlewareRoutes Middleware
LoggingStatus code redirectError HandlerCache MiddlewareSession MiddlewareRoutes MiddlewareYour App
Plack::Middleware::A      Plack::Middleware::B                        PSGI Compatible App
Plack::Middleware::A      Plack::Middleware::B                        PSGI Compatible AppRequest in
Plack::Middleware::A      Plack::Middleware::B                        PSGI Compatible AppRequest in        P::MW::A
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in        P::MW::A      ...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in        P::MW::A      ...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in        P::MW::A      ...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in        P::MW::A      ...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in                      ...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in               e.g. Re...
Plack::Middleware::A      Plack::Middleware::B                         PSGI Compatible AppRequest in               e.g. Re...
EnablingPlack::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”;   $...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “A”;   enable “B”;   $...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “A”;   enable “B”;   $...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “A”;   enable “B”;   $...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “A”; # Plack::Middlewa...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “A”;   enable “B”;   $...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “Static”, root => “/ht...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “Static”, root => “/ht...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “Static”, root => “/ht...
my $app = sub {   return [ $status, $header, $body ];};use Plack::Builder;return builder {   enable “Static”, root => “/ht...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible App
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
Plack::Middleware::Static    Plack::Middleware::Deflate                            PSGI Compatible AppRequest in           ...
plackup compatibleplackup -e ‘enable “Foo”;’ app.psgi
MiddlewareWrite 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;     retu...
Assume...use Plack::Builder;my $body = ‘<html><body>Hello World</body></html>’;my $app = sub {  my $self = shift;     retu...
Assume...use Plack::Builder;my $body = ‘<html><body>Hello World</body></html>’;my $app = sub {  my $self = shift;     retu...
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 bui...
my $app = sub {  my $foo = bar;  die "oops" if $foo eq bar;     [200, [Content-Type => text/html], [ $body ]];};return bui...
my $app = sub {  my $foo = bar;  die "oops" if $foo eq bar;     [200, [Content-Type => text/html], [ $body ]];};return bui...
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], ...
SizeLimit
use Plack::Builder;return builder {   enable "SizeLimit",     max_unshared_size_in_kb => 3000,     check_every_n_requests ...
Plack::App::*ready-to-use applications
Apache::ActionWrapper CGIBin CascadeCocProxy DAV Directory Directory::XslateFCGIDispatcher File ImageMagick JSP PSGIBinPat...
Plack::App::CGIBinmount /cgi-bin as PSGI applications
CGI::PSGIEasy migration from CGI.pm
Plack::App::Directory   Static content file server
Plack::App::Proxy    (non-blocking) proxy serverCan be used as reverse proxy as well
Plack::App::JSPRuns JavaScript PSGI apps :)
# app.psgi - Javascript!Plack::App::JSP->new( js => q{  function respond(body) {    return [ 200, [ Content-type, text/htm...
# app.psgi - Javascript!Plack::App::JSP->new( js => q{  function respond(body) {    return [ 200, [ Content-type, text/htm...
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 {  ...
use CatApp;use CGIApp;my $c1 = sub { CatApp->run };my $c2 = sub { CGIApp->run_psgi };use Plack::Builder;return builder {  ...
use CatApp;use CGIApp;my $c1 = sub { CatApp->run };my $c2 = sub { CGIApp->run_psgi };use Plack::Builder;return builder {  ...
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;retu...
my $root = /path/to/html_doc_root;my $app = Plack::Middleware::TemplateToolkit->new(   INCLUDE_PATH => root,)->to_app;retu...
my $root = /path/to/html_doc_root;my $app = Plack::Middleware::TemplateToolkit->new(   INCLUDE_PATH => root,)->to_app;retu...
my $root = /path/to/html_doc_root;my $app = Plack::Middleware::TemplateToolkit->new(   INCLUDE_PATH => root,)->to_app;retu...
my $root = /path/to/html_doc_root;my $app = Plack::Middleware::TemplateToolkit->new(   INCLUDE_PATH => root,)->to_app;retu...
Creating utilities
Caching Proxy
Website
WebsiteDeveloping code
WebsiteDeveloping code
Slow website    WebsiteDeveloping code
Slow websiteDeveloping code
Slow website Caching ProxyDeveloping code
use Plack::Middleware::Cache;use Plack::App::Proxy;my $app  = Plack::App::Proxy->new(     remote => "http://london.pm.org/...
use Plack::Middleware::Cache;use Plack::App::Proxy;my $app  = Plack::App::Proxy->new(     remote => "http://london.pm.org/...
use Plack::Middleware::Cache;use Plack::App::Proxy;my $app  = Plack::App::Proxy->new(     remote => "http://london.pm.org/...
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",     ...
my $app  = Plack::App::Proxy->new(     remote => "http://london.pm.org/" )->to_app;return builder {   enable "Cache",     ...
my $app  = Plack::App::Proxy->new(     remote => "http://london.pm.org/" )->to_app;$app = builder {   enable "Cache",     ...
# Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.p...
# Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.p...
# Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.p...
# Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.p...
Plack::TestUnified 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_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
use Plack::Test;use HTTP::Request::Common;my $app = sub {   my $env = shift;   return [ $status, $header, $body ];};test_p...
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• Mak...
Internet / UsersWebserver App
Internet / UsersWebserver App
Internet / UsersWebserver App
Internet / UsersWebserver App
Internet / Users Reverse Proxy NGINX   Perlbal   PoundWebserver App
Internet / Users Reverse Proxy NGINX   Perlbal   PoundWebserver App
Internet / Users Reverse Proxy NGINX   Perlbal   PoundWebserver App
Internet / Users Reverse Proxy NGINX   Perlbal   PoundWebserver App
Internet / Users Reverse Proxy NGINX   Perlbal   PoundWebserver App
Reverse ProxyNGINX    Perlbal   Pound        Server
Reverse Proxy  NGINX    Perlbal      PoundServer 1             Server 2
Reverse Proxy     NGINX     Perlbal   PoundServer 1                  Server 3             Server 2
Reverse Proxy     NGINX     Perlbal   PoundServer 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   PerlbalSta...
Flexibility• Easy to change webserver (25+!)        Plack::Handler::* (CGI, FCGI, Apache)    Apache       lighttpd       H...
Flexibility• Easy to change webserver (25+!)        Plack::Handler::* (CGI, FCGI, Apache)    Apache       lighttpd       H...
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  webserv...
Summary✦ PSGI is an interface, Plack is the code.✦ Many fast PSGI servers.✦ Adapters and tools for frameworks and  webserv...
Summary✦ PSGI is an interface, Plack is the code.✦ Many fast PSGI servers.✦ Adapters and tools for frameworks and  webserv...
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
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
Upcoming SlideShare
Loading in...5
×

Plack basics for Perl websites - YAPC::EU 2011

20,955

Published on

Run a website with Perl? - you should learn how to use Plack. Most Perl web frameworks support it and it makes your life a lot easier and a lot more fun

Published in: Technology
0 Comments
21 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
20,955
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
183
Comments
0
Likes
21
Embeds 0
No embeds

No notes for slide

Transcript of "Plack basics for Perl websites - YAPC::EU 2011"

  1. 1. Plack BasicsLeo Lapworth @ YAPC::EU 2011 Much content from Tatsuhiko Miyagawa’s YAPC::NA 2010 talk
  2. 2. What is Plack?
  3. 3. What is Plack?“Superglue for Perl 5 Web Frameworks and Web Servers”
  4. 4. How will that help me?
  5. 5. How will that help me?‣ Flexibility
  6. 6. How will that help me?‣ Flexibility‣ Middleware (plugins)
  7. 7. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps
  8. 8. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps‣ Development
  9. 9. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps‣ Development‣ Testing
  10. 10. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps‣ Development‣ Testing‣ Deployment
  11. 11. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps‣ Development‣ Testing‣ Deployment‣ World peace
  12. 12. How will that help me?‣ Flexibility‣ Middleware (plugins)‣ Apps‣ Development‣ Testing‣ Deployment‣ World peace
  13. 13. History...
  14. 14. Hello World
  15. 15. #!/usr/bin/perluse strict;print “Content-Type: text/plainrnrn”;print “Hello World”;
  16. 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. 17. use FCGI;my $req = FCGI::Request();while ($req->Accept >= 0) { print “Content-Type: text/plainrnrn”; print “Hello World”;}
  18. 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;
  19. 19. All similarbut slightly different
  20. 20. Painful to support all of them 
  21. 21. There wasone common way to do all of this.
  22. 22. CGI.pm
  23. 23. #!/usr/bin/perluse CGI;my $q = CGI->new;print $q->header(‘text/plain’);print “Hello World”;
  24. 24. Works under... CGI FastCGI mod_perlHTTP::Server::Simple::CGI
  25. 25. CGI.pmmod_perl CGI fastcgiApache IIS lighttpd
  26. 26. CGI.pm?
  27. 27. CGI.pm? meh
  28. 28. Frameworksto the rescue!
  29. 29. 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 AmonApache2::WebApp Web::Simple Apache2::REST SweetPea Hydrant Titanium
  30. 30. Let’s look how theyhandled web servers.
  31. 31. CGI.pmmod_perl CGI fastcgiApache IIS lighttpd
  32. 32. CGI::ApplicationApache IIS lighttpd
  33. 33. CGI::Application CGI.pmApache IIS lighttpd
  34. 34. CGI::Application CGI.pm mod_perl CGI fastcgiApache IIS lighttpd
  35. 35. CGI::Application Jifty CGI.pm mod_perl CGI fastcgiApache IIS lighttpd
  36. 36. CGI::Application Jifty Catalyst CGI.pm mod_perl CGI fastcgiApache IIS lighttpd
  37. 37. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiApache IIS lighttpd
  38. 38. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiApache IIS lighttpd nginx
  39. 39. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiHTTP::Server ::Simple Apache IIS lighttpd nginx
  40. 40. Mason CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiHTTP::Server ::Simple Apache IIS lighttpd nginx
  41. 41. Mason CGI::Application Jifty CatalystMason::CGIHandler CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  42. 42. Gross.
  43. 43. CGI.pm Jifty, CGI::Application, Spoonmod_perl centricMason, Sledge, PageKit, WebGUI Adapters Catalyst, Maypole, Squatting
  44. 44. That was 2008...
  45. 45. Gentleman thief & Double agentMiyagawa
  46. 46. Acquired a great idea from Python/Ruby
  47. 47. WSGI (Python) Rack (Ruby)
  48. 48. WSGI (PEP-333)
  49. 49. WSGI Python Frameworks • Django • mod_wsgi • Bottle • Paste • CherryPy • gunicorn • Tornado • uWSGI • Pylons • wsgiref • Flask • Google AppEngine
  50. 50. Django Bottle Flask Tornado WSGI middleware WSGI wsgi handlersApache lighttpd nginx mod_wsgi GAE
  51. 51. Rack
  52. 52. Rack Ruby Frameworks• Rails • Unicorn• Merb • Thin• Sinatra • Mongrel• Camping • Rainbows!• Ramaze • Phusion Passenger• etc. • Heroku
  53. 53. Rails Merb Sinatra Ramaze Rack middleware Rack Rack handlersApache lighttpd Thin Unicorn Mongrel
  54. 54. Perl ?
  55. 55. PSGI Perl ?Perl Web Server Gateway Interface
  56. 56. Interface
  57. 57. Interface
  58. 58. InterfacePSGI != Plack
  59. 59. PSGI application code reference $app = sub {...};
  60. 60. # PSGI Hello Worldmy $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ];};
  61. 61. my $app = sub { my $env = shift; return [ $status, $header, $body ];}; CGI-like environment variables + psgi.input, psgi.errors etc.
  62. 62. my $app = sub { my $env = shift; return [ $status, $header, $body ];}; HTTP status code (int.): 200, 404 etc.
  63. 63. my $app = sub { my $env = shift; return [ $status, $header, $body ];}; Array reference of header pairs: [ ‘Content-Type’, ‘text/html’, ... ]
  64. 64. my $app = sub { my $env = shift; return [ $status, $header, $body ];}; String, array reference of content chunks, Filehandle or IO::Handle-ish object
  65. 65. That’s it.(There’s a callback based streaming interface as well)
  66. 66. # PSGImy $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ];};
  67. 67. Now you’ve gota PSGI compatible application.
  68. 68. Mason CGI::App Jifty CatalystMason::CGIHandler CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  69. 69. Catalyst CGI::App Jifty Mason 2 Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal
  70. 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 other PSGI Webservers
  71. 71. Web Servers
  72. 72. Plack::HandlerConnects PSGI compatible apps to Web servers...
  73. 73. FCGIPlack::Handler::FCGI
  74. 74. ApachePlack::Handler::Apache1Plack::Handler::Apache2
  75. 75. StarmanUNIX Preforking HTTP servers (like Unicorn.rb) HTTP/1.1 chunk + keep-alives / Very Fast
  76. 76. HTTP::Server::Simple::PSGI Zero-deps other than HTTP::Server::Simple Best for embedding PSGI applications
  77. 77. Twiggy Non-blocking web server (like Thin.rb) based on AnyEvent framework Starlet Simpler UNIX HTTP/1.0 ServerBest used with Server::Starter and nginx/lighttpd
  78. 78. Perlbal pluginhttp://github.com/miyagawa/Perlbal-Plugin-PSGI
  79. 79. nginx embedded perl http://github.com/yappo/nginx-psgi-patchs
  80. 80. mod_psgihttp://github.com/spiritloose/mod_psgi Apache2
  81. 81. Corona uWSGICoroutine for each connection http://projects.unbit.it/uwsgi/ based on Coro.pm Feersum evpsgihttp://github.com/stash/Feersum http://github.com/sekimura/evpsgi Gepok http://metacpan/module/Gepok Pure Perl standalone HTTPS First released July 2011
  82. 82. Frameworks Apps Your own code Plack::Middleware PSGI Plack::Handler::* (CGI, FCGI, Apache)
  83. 83. Frameworks Apps Your own code Plack::Middleware PSGI Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona etc, etc
  84. 84. 25+ Plack::Handlers
  85. 85. Adoption?
  86. 86. Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona etc
  87. 87. ? Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona etc
  88. 88. Catalyst Maypole Mason Mojo Sledge Spoon PageKit AxKit Egg Gantry Continuity Solstice MojoliciousTripletail 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
  89. 89. Catalyst Maypole Mason Mojo Sledge Spoon PageKit AxKit Egg Gantry Continuity Solstice MojoliciousTripletail 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. 90. 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
  91. 91. Applications Movable Type 6 WebGUI 8 RT4 ACT (conference toolkit)Bricolage (if someone gets time)
  92. 92. Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona evpsgi
  93. 93. 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 PerlbalStarman Twiggy uWSGI Corona evpsgi
  94. 94. PSGI from a framework
  95. 95. use Dancer;get ‘/’ => sub { “Hello World”;};dance;
  96. 96. use Mojolicious::Lite;get ‘/:name’ => sub { my $self = shift; $self->render_text(‘Hello!’);};app->start;
  97. 97. use My::Jifty::App;my $app = My::Jifty::App->psgi_app;
  98. 98. use Web::Simple ‘MyApp’;package MyApp;dispatch { sub(GET) { [ 200, [...], [ ‘Hello’ ] ]; }};my $app = MyApp->as_psgi;
  99. 99. use My::Catalyst::App;My::Catalyst::App->setup_engine(‘PSGI’);my $app = sub { My::Catalyst::App->run(@_) };
  100. 100. catalyst.pl My::Catalyst::App
  101. 101. Plack“PSGI implementation & toolkit”
  102. 102. Plack toolkit
  103. 103. Plack toolkitPlack::Handlers Connect PSGI apps and Web Servers
  104. 104. Plack toolkitPlack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher
  105. 105. Plack toolkitPlack::Handlers Connect PSGI apps and Web Servers plackup Command line launcherPlack::Loader (auto)load Plack Servers
  106. 106. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack ServersPlack::Middleware Easy-to-use PSGI Middleware
  107. 107. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack ServersPlack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware
  108. 108. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack ServersPlack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware Plack::Apps Apps
  109. 109. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::Loader (auto)load Plack ServersPlack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware Plack::Apps Apps Plack::Test Testing
  110. 110. plackupRuns PSGI app instantly from CLI (inspired by rackup)
  111. 111. > plackup app.psgi
  112. 112. > plackup app.psgiHTTP::Server::PSGI: Acceptingconnections at http://0:5000/
  113. 113. HTTP::Server::PSGI Reference PSGI web server bundled in Plack Standalone, single-process HTTP server great for development and testing
  114. 114. Plack::Middleware (160+ modules - July 2011)
  115. 115. Middleware Debug, Session, Logger, Static, Lint,AccessLog, ErrorDocument, StackTrace, Auth::Basic, Auth::Digest, ReverseProxy, Refresh, Auth::OAuth, Throttle....
  116. 116. Chunked Class::Refresh Compile Conditional ConditionalGETConsoleLogger ContentLength ContentMD5 CrossOriginCSRFBlock Dancer::Debug DBIC::QueryLog DebugDebug::CatalystPluginCache Debug::DBIC::QueryLogDebug::DBIProfile Debug::Profiler::NYTProf Debug::W3CValidateDeflater DoCoMoGUID Doorman ErrorDocument ESI ETagExpires File::Sass Firebug::Lite FirePHP ForceEnv Head HeaderHTMLify HTMLMinify HTTPExceptions IEnosniff IIS6ScriptNameFixImage::Scale Inline InteractiveDebugger IPAddressFilter iPhoneJavaScript::Ectype JSConcat JSONP LighttpdScriptNameFix LintLog::Contextual Log::Minimal Log4perl LogDispatch LogWarnMethodOverride Mirror NeverExpire NoDeflate NoMultipleSlashesNullLogger Options OptionsOK Precompressed ProxyMapRearrangeHeaders Recursive RefererCheck Refresh REPL ReproxyReverseProxy Rewrite Runtime Scope::Container Scope::SessionServerStatus::Lite Session Session::SerializedCookie SetAcceptSimpleContentFilter SimpleLogger SizeLimit SocketIO SSIStackTrace Static Static::Minifier StaticShared StatusTest::StashWarnings Throttle TMT UseChromeFrame Watermark
  117. 117. Plack Middleware Wraps a PSGI applicationto add pre/post processing
  118. 118. Logging
  119. 119. LoggingStatus code redirect
  120. 120. LoggingStatus code redirectError Handler
  121. 121. LoggingStatus code redirectError HandlerCache Middleware
  122. 122. LoggingStatus code redirectError HandlerCache MiddlewareSession Middleware
  123. 123. LoggingStatus code redirectError HandlerCache MiddlewareSession MiddlewareRoutes Middleware
  124. 124. LoggingStatus code redirectError HandlerCache MiddlewareSession MiddlewareRoutes MiddlewareYour App
  125. 125. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App
  126. 126. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in
  127. 127. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A
  128. 128. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::B
  129. 129. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::B PSGI App
  130. 130. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::B P::MW::B PSGI App
  131. 131. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  132. 132. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in Response out P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  133. 133. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in e.g. Redirect Response out P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  134. 134. Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in e.g. Redirect Response out P::MW::A P::MW::A e.g. Static P::MW::B P::MW::B PSGI App
  135. 135. EnablingPlack::Middleware reusable and extensible Middleware framework Plack::Builder DSL in .psgi
  136. 136. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; enable “B”; $app;}
  137. 137. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; enable “B”; $app;}
  138. 138. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; enable “B”; $app;}
  139. 139. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; enable “B”; $app;}
  140. 140. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; # Plack::Middleware::A enable “B”; # Order matters $app;}
  141. 141. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “A”; enable “B”; $app;}
  142. 142. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app;}
  143. 143. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app;}
  144. 144. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; # gzip/deflate $app;}
  145. 145. my $app = sub { return [ $status, $header, $body ];};use Plack::Builder;return builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; $app;}
  146. 146. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App
  147. 147. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in
  148. 148. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Static
  149. 149. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static
  150. 150. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static -
  151. 151. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - PSGI App
  152. 152. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - Deflate compresses PSGI App
  153. 153. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - - Deflate compresses PSGI App
  154. 154. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - - Deflate compresses PSGI App
  155. 155. plackup compatibleplackup -e ‘enable “Foo”;’ app.psgi
  156. 156. MiddlewareWrite once, run in every framework
  157. 157. A few demos..
  158. 158. 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 ]];};
  159. 159. 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 ]];};
  160. 160. 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 ]];};
  161. 161. Debugger
  162. 162. return builder { # Precious debug info. Right on your page! enable Debug; $app;}
  163. 163. InteractiveDebugger
  164. 164. 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;}
  165. 165. 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;}
  166. 166. 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;}
  167. 167. NYTProf - profiler
  168. 168. First rule of Program Optimisation
  169. 169. Don’t do it!
  170. 170. Second rule of Program Optimisation (for experts only)
  171. 171. Don’t do it - yet!
  172. 172. return builder { enable Debug, panels => [ [ Profiler::NYTProf ] ]; $app;};
  173. 173. ServerStatus::Lite
  174. 174. use Plack::Builder;return builder { enable "ServerStatus::Lite", path => /server-status, allow => [ 127.0.0.1], scoreboard => /tmp/score; $app;}
  175. 175. SizeLimit
  176. 176. use Plack::Builder;return builder { enable "SizeLimit", max_unshared_size_in_kb => 3000, check_every_n_requests => 5; $app;}
  177. 177. Plack::App::*ready-to-use applications
  178. 178. Apache::ActionWrapper CGIBin CascadeCocProxy DAV Directory Directory::XslateFCGIDispatcher File ImageMagick JSP PSGIBinPath::Router ProxyProxy::Backend::AnyEvent::HTTPProxy::Backend::LWP Proxy::Selective Proxy::TestURLMap WrapApacheReqWrapApacheReq::FakeRequest WrapCGI
  179. 179. Plack::App::CGIBinmount /cgi-bin as PSGI applications
  180. 180. CGI::PSGIEasy migration from CGI.pm
  181. 181. Plack::App::Directory Static content file server
  182. 182. Plack::App::Proxy (non-blocking) proxy serverCan be used as reverse proxy as well
  183. 183. Plack::App::JSPRuns JavaScript PSGI apps :)
  184. 184. # 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) );});
  185. 185. # 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) );});
  186. 186. Plack::App::URLMap Multiplex multiple apps Integrated with Builder DSL
  187. 187. 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; };}
  188. 188. 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; };}
  189. 189. 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; };}
  190. 190. Some more demos...
  191. 191. Basic website
  192. 192. TemplateToolkit + Static
  193. 193. 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;}
  194. 194. 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;}
  195. 195. 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;}
  196. 196. 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;}
  197. 197. 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;}
  198. 198. Creating utilities
  199. 199. Caching Proxy
  200. 200. Website
  201. 201. WebsiteDeveloping code
  202. 202. WebsiteDeveloping code
  203. 203. Slow website WebsiteDeveloping code
  204. 204. Slow websiteDeveloping code
  205. 205. Slow website Caching ProxyDeveloping code
  206. 206. 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;};
  207. 207. 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;};
  208. 208. 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;};
  209. 209. use LWP::Simple;my $content = get(‘http://localhost:5000/’);
  210. 210. Caching Proxy + Domain hijack
  211. 211. use LWP::Simple;my $content = get(‘http://localhost:5000/’);
  212. 212. use LWP::Simple;my $content = get(‘http://london.pm.org/’);
  213. 213. 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;};
  214. 214. 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;};
  215. 215. 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;};
  216. 216. # Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.pm.org/");say o/ if $content =~ /London Perl Mongers/;
  217. 217. # Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.pm.org/");say o/ if $content =~ /London Perl Mongers/;
  218. 218. # Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.pm.org/");say o/ if $content =~ /London Perl Mongers/;
  219. 219. # Hijack Any LWP::Useragent requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.pm.org/");say o/ if $content =~ /London Perl Mongers/;
  220. 220. Plack::TestUnified interface to write TAP tests with Mock HTTP and Live HTTP
  221. 221. 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’; };
  222. 222. 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’; };
  223. 223. 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’; };
  224. 224. 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’; };
  225. 225. 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’; };
  226. 226. 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’; };
  227. 227. 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’; };
  228. 228. 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’; };
  229. 229. Test::WWW::Mechanize::PSGI
  230. 230. use Test::WWW::Mechanize::PSGI; my $mech = Test::WWW::Mechanize::PSGI->new(     app => $app, );$mech->get_ok(/);
  231. 231. use Test::WWW::Mechanize::PSGI; my $mech = Test::WWW::Mechanize::PSGI->new(     app => $app, );$mech->get_ok(/);
  232. 232. Testing your full configuration!
  233. 233. Network setup tip
  234. 234. Use a reverse proxy
  235. 235. Use a reverse proxy• Sits in front of servers, not clients - “reverse”
  236. 236. Use a reverse proxy• Sits in front of servers, not clients - “reverse”• Makes servers more efficient
  237. 237. Use a reverse proxy• Sits in front of servers, not clients - “reverse”• Makes servers more efficient• Add HTTPS easily
  238. 238. Use a reverse proxy• Sits in front of servers, not clients - “reverse”• Makes servers more efficient• Add HTTPS easily• Makes scaling easier
  239. 239. Internet / UsersWebserver App
  240. 240. Internet / UsersWebserver App
  241. 241. Internet / UsersWebserver App
  242. 242. Internet / UsersWebserver App
  243. 243. Internet / Users Reverse Proxy NGINX Perlbal PoundWebserver App
  244. 244. Internet / Users Reverse Proxy NGINX Perlbal PoundWebserver App
  245. 245. Internet / Users Reverse Proxy NGINX Perlbal PoundWebserver App
  246. 246. Internet / Users Reverse Proxy NGINX Perlbal PoundWebserver App
  247. 247. Internet / Users Reverse Proxy NGINX Perlbal PoundWebserver App
  248. 248. Reverse ProxyNGINX Perlbal Pound Server
  249. 249. Reverse Proxy NGINX Perlbal PoundServer 1 Server 2
  250. 250. Reverse Proxy NGINX Perlbal PoundServer 1 Server 3 Server 2
  251. 251. Reverse Proxy NGINX Perlbal PoundServer 1 Server 3 Server 2
  252. 252. Plack::Middleware::ReverseProxy Updates $env->{REMOTE_ADDRESS}
  253. 253. Why use Plack?
  254. 254. Why use Plack?‣ Flexibility‣ Middleware‣ Apps‣ Development‣ Testing‣ Deployment
  255. 255. Flexibility Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona etc
  256. 256. Flexibility• Easy to change webserver (25+!) Plack::Handler::* (CGI, FCGI, Apache) Apache lighttpd HTTP::Server::PSGI mod_psgi Perlbal Starman Twiggy uWSGI Corona etc
  257. 257. 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
  258. 258. Middleware
  259. 259. Middleware• Easy to reuse with any PSGI app
  260. 260. Middleware• Easy to reuse with any PSGI app• Many tools to make your life easy
  261. 261. Middleware• Easy to reuse with any PSGI app• Many tools to make your life easy• 160+ on CPAN now
  262. 262. App
  263. 263. App• URLMapping / Routing
  264. 264. App• URLMapping / Routing• Static files
  265. 265. App• URLMapping / Routing• Static files• Proxying
  266. 266. Development
  267. 267. Development• plackup
  268. 268. Development• plackup• Restarter (monitor changes on disk)
  269. 269. Development• plackup• Restarter (monitor changes on disk)• HTTP::Server::PSGI
  270. 270. Development• plackup• Restarter (monitor changes on disk)• HTTP::Server::PSGI• Debugging middleware
  271. 271. Development• plackup• Restarter (monitor changes on disk)• HTTP::Server::PSGI• Debugging middleware• Profiler
  272. 272. Testing
  273. 273. Testing• Testing your full configuration
  274. 274. Testing• Testing your full configuration• Test::WWW::Mechanize::PSGI
  275. 275. Testing• Testing your full configuration• Test::WWW::Mechanize::PSGI• Plack::Test
  276. 276. Deployment
  277. 277. Deployment• No separate configuration files
  278. 278. Deployment• No separate configuration files• Easy to choose/change webserver
  279. 279. Deployment• No separate configuration files• Easy to choose/change webserver• DotCloud etc - cloud deployment
  280. 280. Summary
  281. 281. Summary✦ PSGI is an interface, Plack is the code.
  282. 282. Summary✦ PSGI is an interface, Plack is the code.✦ Many fast PSGI servers.
  283. 283. Summary✦ PSGI is an interface, Plack is the code.✦ Many fast PSGI servers.✦ Adapters and tools for frameworks and webservers.
  284. 284. 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
  285. 285. 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
  286. 286. Use Plack
  287. 287. Thank you!Slides: http://slideshare.net/ranguard http://plackperl.org/ irc://irc.perl.org/#plack
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×