Plack basics for Perl websites - YAPC::EU 2011
Upcoming SlideShare
Loading in...5
×
 

Plack basics for Perl websites - YAPC::EU 2011

on

  • 19,202 views

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

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

Statistics

Views

Total Views
19,202
Views on SlideShare
17,573
Embed Views
1,629

Actions

Likes
18
Downloads
169
Comments
0

16 Embeds 1,629

http://blog.plackperl.org 1482
http://sayperl.org 44
http://blog.briang.org 25
http://lickck.blogspot.tw 24
http://www.sayperl.org 22
http://lickck.blogspot.com 10
http://leapf.org 4
http://draft.blogger.com 4
http://www.linkedin.com 3
http://www.techgig.com 3
http://news.int80.biz 2
https://twitter.com 2
http://twitter.com 1
http://www.onlydoo.com 1
http://lickck.blogspot.jp 1
https://duckduckgo.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial LicenseCC Attribution-NonCommercial License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Plack basics for Perl websites - YAPC::EU 2011 Plack basics for Perl websites - YAPC::EU 2011 Presentation Transcript

  • 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 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 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 Reaction Jifty Cyclone3 WebGUI OpenInteract Squatting Dancer CGI::Application Nanoa Ark Angelos Noe Schenker Tatsumaki AmonApache2::WebApp Web::Simple Apache2::REST SweetPea Hydrant Titanium
  • 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 lighttpd
  • CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiApache IIS lighttpd
  • CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiApache IIS lighttpd nginx
  • CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiHTTP::Server ::Simple Apache IIS lighttpd nginx
  • Mason CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgiHTTP::Server ::Simple Apache IIS lighttpd nginx
  • Mason CGI::Application Jifty CatalystMason::CGIHandler CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  • Gross.
  • CGI.pm Jifty, CGI::Application, Spoonmod_perl centricMason, Sledge, PageKit, WebGUI Adapters Catalyst, Maypole, Squatting
  • 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 • uWSGI • Pylons • wsgiref • Flask • Google AppEngine
  • Django Bottle Flask Tornado WSGI middleware WSGI wsgi handlersApache 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 handlersApache lighttpd Thin Unicorn Mongrel
  • 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’ ], [ ‘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)
  • # 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::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::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 UNIX HTTP/1.0 ServerBest used with Server::Starter and nginx/lighttpd
  • 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 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
  • 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 PerlbalStarman 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 PerlbalStarman Twiggy uWSGI Corona etc
  • ? Plack::Middleware PSGI Compatible App Plack::Handler::* (CGI, FCGI, Apache)Apache lighttpd HTTP::Server::PSGI mod_psgi PerlbalStarman Twiggy uWSGI Corona etc
  • 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
  • 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
  • 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 PerlbalStarman 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 PerlbalStarman 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 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 (auto)load Plack Servers
  • 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 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 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 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
  • 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 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 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
  • 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 P::MW::B
  • Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::B PSGI App
  • Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::B P::MW::B PSGI App
  • Plack::Middleware::A Plack::Middleware::B PSGI Compatible AppRequest in P::MW::A P::MW::A P::MW::B P::MW::B PSGI App
  • 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
  • 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
  • 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
  • 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”; $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 AppRequest in
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Static
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static -
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - PSGI App
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - Deflate compresses PSGI App
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - - Deflate compresses PSGI App
  • Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible AppRequest in Response out =~ ^/static Static - - Deflate compresses PSGI App
  • 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; 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 CascadeCocProxy DAV Directory Directory::XslateFCGIDispatcher File ImageMagick JSP PSGIBinPath::Router ProxyProxy::Backend::AnyEvent::HTTPProxy::Backend::LWP Proxy::Selective Proxy::TestURLMap WrapApacheReqWrapApacheReq::FakeRequest WrapCGI
  • 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/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
  • 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/" )->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 requestsLWP::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 requestsLWP::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 requestsLWP::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 requestsLWP::Protocol::PSGI->register($app);use LWP::Simple;my $content = get("http://london.pm.org/");say o/ if $content =~ /London Perl Mongers/;
  • 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_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 / 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 PerlbalStarman 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