SlideShare a Scribd company logo
Plack
Superglue for Perl Web Frameworks
         Tatsuhiko Miyagawa
           Perl Oasis 2010
Tatsuhiko Miyagawa

• Japanese, lives in San Francisco
• Works at Six Apart
• 170+ CPAN modules (id:MIYAGAWA)
• @miyagawa
• bulknews.typepad.com
Background
40 slides of why we need Plack.
   May I fast-forward them?
      (since Stevan spoiled)
Web Frameworks
Maypole Mason Mojo Sledge Catalyst 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
Most of them run on
 mod_perl and CGI
Some run on FastCGI
Some run standalone
Very few supports
  non-blocking
Because:
No common server
environment layers
CGI.pm
Runs “fine” on:
    CGI, FastCGI, mod_perl (1 & 2)
Standalone (with HTTP::Server::Simple)
CGI.pm = LCD
   It’s also Perl core
:-(
Catalyst
The most popular framework as of today
Catalyst::Engine::*
            Server abstractions.
Well supported Apache, FCGI and Standalone
                No CGI.pm
CGI.pm
  Jifty, CGI::Application, Spoon


mod_perl centric
Mason, Sledge, PageKit, WebGUI


       Adapters
  Catalyst, Maypole, Squatting
Problems:
       Duplicated efforts
No fair performance evaluations
Question:
Can we share?
Attempt:
HTTP::Engine
HTTP::Engine
Lots of adapters (FCGI, Apache2, POE)
     Clean Request/Response API
Written by Yappo, tokuhirom and others
Problems
Mo[ou]se everywhere
 Moose is non-realistic in CGI environment
 Mouse is lovely but has its own problems :p
Monolithic
All implementations share HTTP::Engine roles
and builders, which is sometimes hard to adapt
      and has less place for optimizations.
APIs everywhere
Most frameworks have their request/response API
          Sometimes there are gaps.
    Annoying to write bridges and wrappers
Solution
Steal great stuff
from Python/Ruby
WSGI (Python)
   Rack
WSGI (PEP-333)
mod_wsgi, Paste, AppEngine
 Django, CherryPy, Pylons
Plack perl superglue for web frameworks and servers
Rack
Passenger, thin, Unicorn, Mongrel, Heroku
            Rails, Merb, Sinatra
Plack perl superglue for web frameworks and servers
WSGI/Rack
 Completely separate interface
from the actual implementation
Approach
Split HTTP::Engine
 into three parts
Interface
       Servers
Utils & Middleware
PSGI (interface)
HTTP::Server::PSGI etc. (servers)
     Plack (utils & middleware)
PSGI
Perl Web Server Gateway Interface
Interface
WARNING
You DON’T need to care about these
   interface details unless you are
framework or middleware developers
   (But i guess many of you are ...)
# WSGI
def hello(environ, start_response):
 start_response(“200 OK”, [
   (‘Content-Type’, ‘text/plain’)
 ])
 return [“Hello World”]
# Rack
class Hello
 def call(env)
   return [
     200,
     { “Content-Type” => ”text/plain” },
     [“Hello World”]
   ]
 end
end
# PSGI
my $app = sub {
   my $env = shift;
   return [
      200,
      [ ‘Content-Type’, ‘text/plain’ ],
      [ ‘Hello World’ ],
   ];
};
PSGI application
   code reference
   $app = sub {...};
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
environment hash
$env: CGI-like env variables
+ psgi.input, psgi.errors etc.
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
Response
 array ref with three elements
status code, headers (array ref)
and body (IO-like or array ref)
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};
$body
  IO::Handle-like
getline() and close()
IO::Handle::Util
Easily turns perl code ref into a IO::Handle
Streaming interface
my $app = sub {
  my $env = shift;
  return sub {
    my $respond = shift;
    # You could do some event loop
    # to delay response (e.g. Comet)
    $respond->([ $status, $header, $body ]);
  };
};
my $app = sub {
  my $env = shift;
  return sub {
    my $respond = shift;
    my $w = $respond->([ $status, $header ]);
    $w->write($body);
    $w->write($body);
    ...
    $w->close;
  };
};
Streaming Interface
 Originally designed for non-blocking servers
Now available for most servers incl. CGI, Apache
Catalyst            CGI::App              Jifty        Tatsumaki


                                                    Plack::Middleware

                               PSGI

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


Apache       lighttpd       HTTP::Server::PSGI      mod_psgi   Perlbal
PSGI adaptation
Maypole Mason Mojo Sledge Catalyst 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
Maypole Mason Mojo Sledge Catalyst 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
Applications
MT::App, WebGUI
Plack
“PSGI toolkit”
HTTP::Server::PSGI
 Reference PSGI web server
      bundled in Plack
Very fast
 3000 QPS on standalone
15000 QPS with prefork :)
Plack::Handler
Connects PSGI apps to Web servers
 CGI, FastCGI, Apache, Standalone
Utilities
Plackup
Run PSGI app instantly from CLI
     (inspired by rackup)
Plack::Runner
            plackup backend
Use this to make CLI for your web app
Middleware
Plack perl superglue for web frameworks and servers
my $app = sub {
   my $env = shift;
   return [ $status, $header, $body ];
};

my $mw = sub {
   my $env = shift;
   # do something with $env
   my $res = $app->($env);
   # do something with $res;
   return $res;
};
Middleware
    Debug, Session, Runtime, Static, AccessLog,
  ConditionalGET, ErrorDocument, StackTrace,
Auth::Basic, Auth::Digest, ReverseProxy, Refresh etc.
Plack::Middleware
  reusable and extensible
  Middleware framework
 Plack::Builder DSL in .psgi
my $app = sub {
   return [ $status, $header, $body ];
};

use Plack::Builder;

builder {
  enable “Static”, root => “/htdocs”,
    path => qr!^/static/!;
  enable “Deflater”; # gzip/deflate
  $app;
}
plackup compatible
plackup -e ‘enable “Foo”;’ app.psgi
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;

builder {
  mount “/cat” => $c1;
  mount “/cgi-app” => builder {
    enable “StackTrace”;
    $c2;
  };
}
CGI::PSGI
Easy migration from CGI.pm
CGI::Emulate::PSGI
    CGI::Compile
Easiest migration from CGI scripts (like Registry)
Plack::Request
    like libapreq (Apache::Request)
wrapper APIs for middleware developers
Plack::Test
 Unified interface to write 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 $cb = shift;
   my $req = GET “http://localhost/foo”;
   my $res = $cb->($req);
   # test $res;
};
use Plack::Test;
use HTTP::Request::Common;
$Plack::Test::Impl = “Server”;

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

test_psgi app => $app, client => sub {
   my $cb = shift;
   my $req = GET “http://localhost/foo”;
   my $res = $cb->($req);
   # test $res;
};
Test::WWW::Mechanize::PSGI
           acme++
Other PSGI Servers
Non-blocking servers
     psgi.nonblocking = true
AnyEvent, Coro, POE, Danga::Socket
Tatsumaki
 Non-blocking Web App framework
Comet, Server push, async HTTP client
http://github.com/miyagawa/Tatsumaki
Nomo
Unixy PSGI web servers with supervisors support
       http://github.com/miyagawa/Nomo
Re’em
Unicorn in Moose + FCGI::Manager
 http://github.com/perigrin/re-em
nginx embedded perl
 http://github.com/yappo/nginx-psgi-patchs
mod_psgi
http://github.com/spiritloose/mod_psgi
evpsgi
http://github.com/sekimura/evpsgi
Perlbal plugin
http://github.com/miyagawa/Perlbal-Plugin-PSGI
Catalyst            CGI::App              Jifty        Tatsumaki


                                                    Plack::Middleware

                               PSGI

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


Apache       lighttpd       HTTP::Server::PSGI      mod_psgi   Perlbal
DEMO
Recent Updates
Common Confusions
“Is Plack a (new)
  framework?”
No.
Plack is intended to be used by developers for
   framework, web servers and middleware.
“But what is this
Plack::Request then?”
Ugh.
Plack::Request can be used as a micro framework.
   But our plan is to rename the existing one.
“Is Plack a web server?”
Not anymore.
Decided to give web servers ::PSGI name such as:
    HTTP::Server::PSGI, PoCo::Server::PSGI,
         AnyEvent::HTTPD::PSGI, etc.
“Implements PSGI
  = use Plack?”
Yeah, but not
 necessarily.
Future
PSGI 1.1
psgi.streaming
  becomes SHOULD (from MAY)
Will be BufferedStreaming middleware
psgi.input
read callback (for WebSockets)
psgi.logger
Optional: Log::Dispatch-ish logger object
useful for Debug and FirePHP integration
psgix.session
Optional: Session as a hash ref
      (API is in Piglet)
Plack 1.0
HTTP::Server::PSGI
 (partial) HTTP/1.1 support
   pull prefork out of core
refactoring loaders
Restarter, Shotgun, gateway.cgi
   Plack::Handler renames
Merge Plack::Request
   Becomes a library for middleware writers
Make it work better when created multiple times
Summary

• PSGI is an interface, Plack is the code.
• We have many (pretty fast) PSGI servers.
• We have adapters and tools for most web
  frameworks.
• Use it!
http://github.com/miyagawa/Plack
        http://plackperl.org/
   http://advent.plackperl.org/
      irc://irc.perl.org/#plack
BTW
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
We can fix this.
1) Help me SEO
 <a href=”http://plackperl.org/”>
(put “Perl” and “Web” here)</a>
2) More insanely:
% ls -l perlwebserver-0.3/lib/PerlWebServer/Module/
total 208
-rw-r--r-- 1 miyagawa staff 6029 Dec 15 2000 mod_cgi.pm
-rw-r--r-- 1 miyagawa staff 71770 Dec 15 2000 mod_homer.pm
-rw-r--r-- 1 miyagawa staff 5337 Jan 15 15:29 mod_psgi.pm
-rw-r--r-- 1 miyagawa staff 7394 Dec 15 2000 mod_ssi.pm
httpi: I gave up.
There is tools/phproxy which does similar things.
Questions?

More Related Content

Plack perl superglue for web frameworks and servers