Successfully reported this slideshow.

Plack basics for Perl websites - YAPC::EU 2011

22

Share

Loading in …3
×
1 of 323
1 of 323

Plack basics for Perl websites - YAPC::EU 2011

22

Share

Download to read offline

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

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Plack basics for Perl websites - YAPC::EU 2011

  1. 1. Plack Basics Leo 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/perl use 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 similar but slightly different
  20. 20. Painful to support all of them 
  21. 21. There was one common way to do all of this.
  22. 22. CGI.pm
  23. 23. #!/usr/bin/perl use CGI; my $q = CGI->new; print $q->header(‘text/plain’); print “Hello World”;
  24. 24. Works under... CGI FastCGI mod_perl HTTP::Server::Simple::CGI
  25. 25. CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  26. 26. CGI.pm?
  27. 27. CGI.pm? meh
  28. 28. Frameworks to 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 Amon Apache2::WebApp Web::Simple Apache2::REST SweetPea Hydrant Titanium
  30. 30. Let’s look how they handled web servers.
  31. 31. CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  32. 32. CGI::Application Apache IIS lighttpd
  33. 33. CGI::Application CGI.pm Apache IIS lighttpd
  34. 34. CGI::Application CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  35. 35. CGI::Application Jifty CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  36. 36. CGI::Application Jifty Catalyst CGI.pm mod_perl CGI fastcgi Apache IIS lighttpd
  37. 37. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi Apache IIS lighttpd
  38. 38. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi Apache IIS lighttpd nginx
  39. 39. CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  40. 40. Mason CGI::Application Jifty Catalyst CGI.pm Catalyst::Engine mod_perl CGI fastcgi HTTP::Server ::Simple Apache IIS lighttpd nginx
  41. 41. Mason CGI::Application Jifty Catalyst Mason::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, Spoon mod_perl centric Mason, Sledge, PageKit, WebGUI Adapters Catalyst, Maypole, Squatting
  44. 44. That was 2008...
  45. 45. Gentleman thief & Double agent Miyagawa
  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 handlers Apache 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 handlers Apache lighttpd Thin Unicorn Mongrel
  54. 54. Perl ?
  55. 55. PSGI Perl ? Perl Web Server Gateway Interface
  56. 56. Interface
  57. 57. Interface
  58. 58. Interface PSGI != Plack
  59. 59. PSGI application code reference $app = sub {...};
  60. 60. # PSGI Hello World my $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. # PSGI my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; };
  67. 67. Now you’ve got a PSGI compatible application.
  68. 68. Mason CGI::App Jifty Catalyst Mason::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::Handler Connects PSGI compatible apps to Web servers...
  73. 73. FCGI Plack::Handler::FCGI
  74. 74. Apache Plack::Handler::Apache1 Plack::Handler::Apache2
  75. 75. Starman UNIX 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 Server Best used with Server::Starter and nginx/lighttpd
  78. 78. Perlbal plugin http://github.com/miyagawa/Perlbal-Plugin-PSGI
  79. 79. nginx embedded perl http://github.com/yappo/nginx-psgi-patchs
  80. 80. mod_psgi http://github.com/spiritloose/mod_psgi Apache2
  81. 81. 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
  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 Perlbal Starman 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 Perlbal Starman Twiggy uWSGI Corona etc
  87. 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. 88. 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
  89. 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. 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 Perlbal Starman 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 Perlbal Starman 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 toolkit Plack::Handlers Connect PSGI apps and Web Servers
  104. 104. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher
  105. 105. Plack toolkit Plack::Handlers Connect PSGI apps and Web Servers plackup Command line launcher Plack::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 Servers Plack::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 Servers Plack::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 Servers Plack::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 Servers Plack::Middleware Easy-to-use PSGI Middleware Plack::Builder OO & DSL to enable Middleware Plack::Apps Apps Plack::Test Testing
  110. 110. plackup Runs PSGI app instantly from CLI (inspired by rackup)
  111. 111. > plackup app.psgi
  112. 112. > plackup app.psgi HTTP::Server::PSGI: Accepting connections 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 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
  117. 117. Plack Middleware Wraps a PSGI application to add pre/post processing
  118. 118. Logging
  119. 119. Logging Status code redirect
  120. 120. Logging Status code redirect Error Handler
  121. 121. Logging Status code redirect Error Handler Cache Middleware
  122. 122. Logging Status code redirect Error Handler Cache Middleware Session Middleware
  123. 123. Logging Status code redirect Error Handler Cache Middleware Session Middleware Routes Middleware
  124. 124. Logging Status code redirect Error Handler Cache Middleware Session Middleware Routes Middleware Your App
  125. 125. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App
  126. 126. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in
  127. 127. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A
  128. 128. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B
  129. 129. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B PSGI App
  130. 130. Plack::Middleware::A Plack::Middleware::B PSGI Compatible App Request in P::MW::A P::MW::B P::MW::B PSGI App
  131. 131. 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
  132. 132. 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
  133. 133. 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
  134. 134. 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
  135. 135. Enabling Plack::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 App Request in
  148. 148. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Static
  149. 149. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static
  150. 150. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static -
  151. 151. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - PSGI App
  152. 152. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - Deflate compresses PSGI App
  153. 153. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - - Deflate compresses PSGI App
  154. 154. Plack::Middleware::Static Plack::Middleware::Deflate PSGI Compatible App Request in Response out =~ ^/static Static - - Deflate compresses PSGI App
  155. 155. plackup compatible plackup -e ‘enable “Foo”;’ app.psgi
  156. 156. Middleware Write 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 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
  179. 179. Plack::App::CGIBin mount /cgi-bin as PSGI applications
  180. 180. CGI::PSGI Easy migration from CGI.pm
  181. 181. Plack::App::Directory Static content file server
  182. 182. Plack::App::Proxy (non-blocking) proxy server Can be used as reverse proxy as well
  183. 183. Plack::App::JSP Runs 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. Website Developing code
  202. 202. Website Developing code
  203. 203. Slow website Website Developing code
  204. 204. Slow website Developing code
  205. 205. Slow website Caching Proxy Developing 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 requests LWP::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 requests LWP::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 requests LWP::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 requests LWP::Protocol::PSGI->register($app); use LWP::Simple; my $content = get("http://london.pm.org/"); say 'o/' if $content =~ /London Perl Mongers/;
  220. 220. Plack::Test Unified 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 / Users Webserver App
  240. 240. Internet / Users Webserver App
  241. 241. Internet / Users Webserver App
  242. 242. Internet / Users Webserver App
  243. 243. Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  244. 244. Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  245. 245. Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  246. 246. Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  247. 247. Internet / Users Reverse Proxy NGINX Perlbal Pound Webserver App
  248. 248. Reverse Proxy NGINX Perlbal Pound Server
  249. 249. Reverse Proxy NGINX Perlbal Pound Server 1 Server 2
  250. 250. Reverse Proxy NGINX Perlbal Pound Server 1 Server 3 Server 2
  251. 251. Reverse Proxy NGINX Perlbal Pound Server 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 Perlbal Starman 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

×