SlideShare a Scribd company logo
1 of 42
PSGI and Plack from
first principles
Peter Sergeant
Perl Careers
http://perl.careers/
Goals
• Explain PSGI and Plack in the simplest terms
possible, with examples
• Demystify and demagicify how they work
• Leave you in a position where you understand the
mechanics well enough to reason about issues
Specific Goal
• Leave you in a
position where
the following
code makes
perfect sense to
you…
• And you
understand
what’s going on
behind the
scenes
#!/usr/bin/env plackup
use strict; use warnings;
use MyApp::Web;
use Plack::Builder;
builder {
mount '/heartbeat' => sub {
return [
200,
['Content-type' => 'text/plain'],
[ "OK" ]
];
};
mount '/' => builder {
enable_if
{ $_[0]->{REMOTE_ADDR} eq '127.0.0.1' }
'Debug';
enable "GNUTerryPratchett";
MyApp::Web->psgi_app;
}
};
A brief, incomplete and
largely inaccurate history of
dynamic webpages
1991
• HTTP0.9
• Webservers exist to serve mostly static HTML
documents
• Some HTML documents carry <ISINDEX>, which
causes the browser to give you a text box you can
type in, and it’ll stick it on the end of the request
after a ?
• Immediately obvious to everyone that it’d be much
cooler to have fully interactive pages like on BBSs
1993
• 02 Jun: “HTML+” gains <INPUT> and <SELECT>
elements
• 05 Sep: Mosaic implements sending that data in
the /?foo=bar&baz=flux format
• 13 Sep: NCSA httpd supports:
• "server scripts, which are executable programs
which the server runs to generate documents on the
fly. They are easy to write and can be written in your
favorite language, whether it be C, PERL, or even
the Bourne shell"
1993 continued
• 14 Nov
• NCSA httpd author complains that no-one is writing scripts
because they’re worried the interface will change
• Asks for help solving some of the issues and concerns about
this interface
• 17 Nov
• He incorporates feedback, releases “CGP/1.0 Specification”
• Two days later he renames it to “CGI”
• 13 Dec
• NCSA httpd 1.0 comes out of alpha, released with “CGI
Support” and some samples
• Pretty much all of these examples still work perfectly
CGI
• The webserver asks the OS to execute a specific
executable, and passes data from the HTTP
request to it via STDIN and ENV
• The executable is expected to pass back HTTP
headers and content on STDOUT
• It’s really simple
• Although it them almost 11 years to get an RFC out
CGI - Example
#!/usr/bin/perl
use strict; use warnings; use URI::Escape qw/uri_unescape/;
my $who = $ENV{'REMOTE_ADDR'};
my $query_string = $ENV{'QUERY_STRING'};
# Don't do this, use CGI.pm
my %p = map { uri_unescape $_ } map { split(/=/, $_) } split(/&/, $query_string
);
my $message = sprintf("Hello [%s] - you gave us the message: [%s]",
$who, $p{'message'} || '(no message)');
my $status = 200;
my $content_type = 'text/plain';
print <<"RESPONSE";
Status: $status
Content-type: $content_type
$message
RESPONSE
Easy to run
• Pretend to be a webserver on the command line:
$ REMOTE_ADDR=127.0.0.1 QUERY_STRING="message=Hello%20World” 
./hello_world.cgi
Status: 200
Content-type: text/plain
Hello [127.0.0.1] - you gave us the message: [Hello World]
Easy to run
• Apache runs it just as well without any
modification
CGI
• Still going strong after 22 years
• 2004 saw the release of an RFC, after 7 years of
work(!)
• Doesn’t scale
• Fires up a new process on each request
• This can be expensive when:
• The process is perl
• It wants to load a bunch of modules from disk
• Sets up a DB connection or three
• Reads and parses your config file
• etc
Persistent Approaches
• Load perl and your application once
• Fast!
• Several approaches
mod_perl
• Most popular approach
• Apache-specific
• Each Apache process embeds perl
• Reformulate your code as a module, that
implements a specific interface
mod_perl example
package HelloWorld::Simple;
use strict; use warnings;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
$r->content_type('text/plain');
$r->send_http_header;
my $who = $r->get_remote_host;
# Don't do this, use CGI.pm
my %p =
map { uri_unescape $_ } map { split( /=/, $_ ) } split( /&/, $r->args );
$r->print(
sprintf(
<<RESPONSE,
Hello [%s] - you gave us the message: [%s]
RESPONSE
$who, $p{'message'} || '(no message)'
)
);
return OK;}
1;
Other approaches
• FastCGI – provides server-specific shims to
communicate with long-running perl processes
• ActivePerl ISAPI interface for IIS
• Perl-based web server
• … each of which has a different API that needs
targeting …
Pre-PSGI landscape
• Your application needed to know what kind of server it was
going to run on
• Each framework that tried to abstract the details needed
server-specific shims, eg:
• Catalyst::Engine::CGI
• Catalyst::Engine::SCGI
• Catalyst::Engine::Zeus
• Catalyst::Engine::FastCGI
• Catalyst::Engine::Apache::MP13
• Catalyst::Engine::Apache2::MP19
• Catalyst::Engine::Apache2::MP20
• Catalyst::Engine::HTTP::POE
• ... and the rest
PSGI
Perl (Web)Server Gateway Interface
Where it fits in the landscape
Server-agnostic Perl
Long-running Perl-level API
CGI
mod_perl
FastCGI
PSGI
Not so very different from
CGI
Rather than reading from %ENV and writing to STDOUT, our PSGI file defines
an anonymous subroutine which accepts a hashref, and returns an arrayref
That CGI example again …as a PSGI application
Runs on the command
line
• Needs a little bit of massaging, but:
$ REMOTE_ADDR=127.0.0.1 QUERY_STRING="message=Hello%20World” 
perl -e 'my $app = do ”hello.psgi"; print join "n", map { ref
$_ ? @$_ : $_ } @{ $app->(%ENV); }’
200
Content-type
text/plain
Hello [127.0.0.1] - you gave us the message: [Hello World]
Build your own CGI PSGI
interface!
• We can write a simple (and stupid) adaptor to run
PSGI
#!/usr/bin/perl
use strict; use warnings;
my $app = do "plack.psgi";
my ( $status, $headers, $content ) = @{ $app->( %ENV ) };
print "Status: $statusn";
while ( @$headers ) {
printf("%s: %sn", shift( @$headers ), shift( @$headers ));
}
print "n"; # Delineate headers and body
print join "n", @$content;
Or even…
• A simple mod_perl adaptor
• An LWP work-alike which pushes requests directly
in to our app
• All sorts of other things we don’t have time for,
BUT…
Actually…
• Don’t do any of that…
• Plack provides a set of tools that implement PSGI
• Plack::Handler::CGI
• Plack::Handler::Apache[12]
• Plack::Handler::LWPish
• The point is, there’s NO MAGIC
• A PSGI file is just a file which returns a Perl
subroutine reference
SO WHAT?
So What?
• Kinda cool
• Nice to know it exists
• Primarily of interest to framework creators
• Why should you care?
Fun with functions
• Because the interface is a subroutine reference,
with a predictable interface, you can combine
these subroutines
• Let’s say you wanted to combine two different
PSGI-based services, and dispatch them based
on URL…
• Perhaps you had a monitoring system which
expected a certain end-point, and you didn’t want to
bake that in to your business logic…
Fun with functions
#!perl
use strict; use warnings;
my $monitoring = do "./monitoring.psgi";
my $main_app = do "./app.psgi";
my $app = sub {
my $env = $_[0];
if ( $env->{'PATH_INFO'} eq 'heartbeat' )
{
return $monitoring->( @_ );
} else {
return $main_app->( @_ );
}
};
Fun with functions
• Because you know the input and output format,
you can wrap the request incoming and outgoing
• YAPC::EU 2003 saw a bit of an obsession with the
colour orange, and led to the creation of
Acme::Tango, which turns colours orange
• This is obviously important functionality, but
probably shouldn’t live in the business logic…
Acme::Tango example
#!/usr/bin/perl
use strict; use warnings;
use Acme::Tango;
use Plack::App::Proxy;
my $main_app = do "tango_target_app.psgi";
my $app = sub {
my $env = shift();
my ( $status, $headers, $content ) = @{ $main_app->( $env ) };
my %headers = @$headers;
if ( ( $headers{'Content-type'} || $headers{'Content-Type'} ) =~
m'text/(html|css)' ) {
if ( ref $content eq 'ARRAY' ) {
$content = [ map {
s/(#[a-f0-9]{6}|#[a-f0-9]{3})b/Acme::Tango::drink($1)/gei; $_
} @$content ]
}
}
return [ $status, $headers, $content ];
};
Before…
After!
Wrapping for fun and
profit
• Generally the idea of being able to add wrapping
code around your app is useful
• These wrappers are called “Middleware” in the
PSGI / Plack world
Plack::Builder makes this
easy!
• ‘builder’ takes a
subroutine which
should return a PSGI
app
• ‘enable’ adds the
name of a
middleware you wish
to apply to that app to
a list
• ‘builder’ wraps the
app in that
middleware, returning
… a new PSGI app
use Plack::Builder;
my $app = sub { ... };
builder {
enable "Deflater";
enable "+My::Plack::Middleware";
enable_if
{ $_[0]->{REMOTE_ADDR} eq '127.0.0.1' }
'Debug'
return $app;
};
CPAN is full of Plack
Middleware
AccessLog Auth::Basic Auth::Digest Auth::OAuth Chunked Class::Refresh
Compile Conditional ConditionalGETConsoleLogger ContentLength
ContentMD5 CrossOriginCSRFBlock Dancer::Debug DBIC::QueryLog Debug
Debug::DBIC::QueryLogDebug::DBIProfile Debug::Profiler::NYTProf
Debug::W3CValidateDeflater DebugDebug::CatalystPluginCache
DoCoMoGUID Doorman ErrorDocument ErrorDocument ESI ETagExpires
File::Sass Firebug::Lite FirePHP ForceEnv Head HeaderHTMLify HTMLMinify
HTTPExceptions IEnosniff IIS6ScriptNameFixImage::Scale Inline
InteractiveDebugger IPAddressFilter iPhoneJavaScript::Ectype JSConcat
JSONP LighttpdScriptNameFix Lint LintLog::Contextual Log4perl Log::Minimal
LogDispatch Logger LogWarnMethodOverride Mirror NeverExpire NoDeflate
NoMultipleSlashesNullLogger Options OptionsOK Precompressed
ProxyMapRearrangeHeaders Recursive RefererCheck Refresh Refresh REPL
ReproxyReverseProxy ReverseProxy Rewrite Runtime Scope::Container
Scope::SessionServerStatus::Lite Session Session Session::SerializedCookie
SetAcceptSimpleContentFilter SimpleLogger SizeLimit SocketIO
SSIStackTrace StackTrace Static Static Static::Minifier StaticShared
StatusTest::StashWarnings Throttle Throttle TMT UseChromeFrame
Watermark
An
Example…
• We’ve only
got time for
one example
in a 20
minute talk…
• Add a couple
of lines to
wrap out
Hello World
app in
Plack::Mid
dleware::D
ebug
#!/usr/bin/perl
use strict;
use warnings;
use URI::Escape qw/uri_unescape/;
use Plack::Builder;
my $app = sub {
local %ENV = %{ shift() };
my $who = $ENV{'REMOTE_ADDR'};
my $query_string = $ENV{'QUERY_STRING'};
# Don't do this, use CGI.pm
my %p =
map { uri_unescape $_ }
map { split( /=/, $_ ) } split( /&/, $query_string );
my $message = sprintf(
"<html><head></head><body>Hello [%s] - " .
"you gave us the message: [%s]</body></html>",
$who, $p{'message'} || '(no message)' );
my $status = 200;
my $content_type = 'text/html';
return [ $status, [ 'Content-type' => $content_type ],
[$message], ];
};
builder {
enable 'Debug', panels => [ qw(Memory Timer) ];
$app;
}
An Example…
An Example…
An Example…
In Summary
• PSGI defines inputs and outputs for a subroutine which
encapsulate a web app
• A PSGI file simply returns a subroutine reference
• The hosting webserver `evals` (actually `do`) the PSGI file, and
takes a copy of the resulting subroutine reference, and
executes it on each request
• Plack
• Provides the ways to hook that up to the webservers of your choice
• Makes it easy to wrap/manipulate these subroutine with some
syntactic sugar
• There’s an incredible collection of prewritten wrappers called
Middleware on the CPAN
The starting example, at the
end
#!/usr/bin/env plackup
use strict; use warnings;
use MyApp::Web;
use Plack::Builder;
builder {
mount '/heartbeat' => sub {
return [
200,
['Content-type' => 'text/plain'],
[ "OK" ]
];
};
mount '/' => builder {
enable_if
{ $_[0]->{REMOTE_ADDR} eq '127.0.0.1' }
'Debug';
enable "GNUTerryPratchett";
MyApp::Web->psgi_app;
}
};
fin

More Related Content

What's hot

Rancher と GitLab を使う3つの理由
Rancher と GitLab を使う3つの理由Rancher と GitLab を使う3つの理由
Rancher と GitLab を使う3つの理由Tetsurou Yano
 
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming ApplicationsRunning Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming ApplicationsLightbend
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
 
Tips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsTips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsSarvesh Kushwaha
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service WorkerAnna Su
 
Le Wagon - Javascript for Beginners
Le Wagon - Javascript for BeginnersLe Wagon - Javascript for Beginners
Le Wagon - Javascript for BeginnersSébastien Saunier
 
Advanced GitHub Enterprise Administration
Advanced GitHub Enterprise AdministrationAdvanced GitHub Enterprise Administration
Advanced GitHub Enterprise AdministrationLars Schneider
 
Building your First gRPC Service
Building your First gRPC ServiceBuilding your First gRPC Service
Building your First gRPC ServiceJessie Barnett
 
Clean architectures with fast api pycones
Clean architectures with fast api   pyconesClean architectures with fast api   pycones
Clean architectures with fast api pyconesAlvaro Del Castillo
 
NATS - A new nervous system for distributed cloud platforms
NATS - A new nervous system for distributed cloud platformsNATS - A new nervous system for distributed cloud platforms
NATS - A new nervous system for distributed cloud platformsDerek Collison
 
Microservice Resilience Patterns @VoxxedCern'24
Microservice Resilience Patterns @VoxxedCern'24Microservice Resilience Patterns @VoxxedCern'24
Microservice Resilience Patterns @VoxxedCern'24Victor Rentea
 
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015CODE BLUE
 
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...confluent
 
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in DepthA Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in DepthYoshifumi Kawai
 
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.Mikhail Egorov
 
High Performance Systems in Go - GopherCon 2014
High Performance Systems in Go - GopherCon 2014High Performance Systems in Go - GopherCon 2014
High Performance Systems in Go - GopherCon 2014Derek Collison
 
Introduction to go language programming
Introduction to go language programmingIntroduction to go language programming
Introduction to go language programmingMahmoud Masih Tehrani
 
SIP Attack Handling (Kamailio World 2021)
SIP Attack Handling (Kamailio World 2021)SIP Attack Handling (Kamailio World 2021)
SIP Attack Handling (Kamailio World 2021)Fred Posner
 

What's hot (20)

Rancher と GitLab を使う3つの理由
Rancher と GitLab を使う3つの理由Rancher と GitLab を使う3つの理由
Rancher と GitLab を使う3つの理由
 
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming ApplicationsRunning Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 
Building Advanced XSS Vectors
Building Advanced XSS VectorsBuilding Advanced XSS Vectors
Building Advanced XSS Vectors
 
Tips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsTips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC Applications
 
Git advanced
Git advancedGit advanced
Git advanced
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
Le Wagon - Javascript for Beginners
Le Wagon - Javascript for BeginnersLe Wagon - Javascript for Beginners
Le Wagon - Javascript for Beginners
 
Advanced GitHub Enterprise Administration
Advanced GitHub Enterprise AdministrationAdvanced GitHub Enterprise Administration
Advanced GitHub Enterprise Administration
 
Building your First gRPC Service
Building your First gRPC ServiceBuilding your First gRPC Service
Building your First gRPC Service
 
Clean architectures with fast api pycones
Clean architectures with fast api   pyconesClean architectures with fast api   pycones
Clean architectures with fast api pycones
 
NATS - A new nervous system for distributed cloud platforms
NATS - A new nervous system for distributed cloud platformsNATS - A new nervous system for distributed cloud platforms
NATS - A new nervous system for distributed cloud platforms
 
Microservice Resilience Patterns @VoxxedCern'24
Microservice Resilience Patterns @VoxxedCern'24Microservice Resilience Patterns @VoxxedCern'24
Microservice Resilience Patterns @VoxxedCern'24
 
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
 
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...
Performance Analysis and Optimizations for Kafka Streams Applications (Guozha...
 
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in DepthA Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
 
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
 
High Performance Systems in Go - GopherCon 2014
High Performance Systems in Go - GopherCon 2014High Performance Systems in Go - GopherCon 2014
High Performance Systems in Go - GopherCon 2014
 
Introduction to go language programming
Introduction to go language programmingIntroduction to go language programming
Introduction to go language programming
 
SIP Attack Handling (Kamailio World 2021)
SIP Attack Handling (Kamailio World 2021)SIP Attack Handling (Kamailio World 2021)
SIP Attack Handling (Kamailio World 2021)
 

Viewers also liked

Top 10 Perl Performance Tips
Top 10 Perl Performance TipsTop 10 Perl Performance Tips
Top 10 Perl Performance TipsPerrin Harkins
 
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題Masahiro Nagano
 
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-Thon
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-ThonApache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-Thon
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-ThonMasahiro Nagano
 
How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server Masahiro Nagano
 
Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency managerTatsuhiko Miyagawa
 

Viewers also liked (12)

Top 10 Perl Performance Tips
Top 10 Perl Performance TipsTop 10 Perl Performance Tips
Top 10 Perl Performance Tips
 
Plack at OSCON 2010
Plack at OSCON 2010Plack at OSCON 2010
Plack at OSCON 2010
 
nginx mod PSGI
nginx mod PSGInginx mod PSGI
nginx mod PSGI
 
Introduction to PSGI
Introduction to PSGIIntroduction to PSGI
Introduction to PSGI
 
Hachiojipm41
Hachiojipm41Hachiojipm41
Hachiojipm41
 
Web::Scraper for SF.pm LT
Web::Scraper for SF.pm LTWeb::Scraper for SF.pm LT
Web::Scraper for SF.pm LT
 
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
 
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-Thon
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-ThonApache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-Thon
Apache::LogFormat::Compiler YAPC::Asia 2013 Tokyo LT-Thon
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
From CGI to mod_perl 2.0, Fast!
From CGI to mod_perl 2.0, Fast! From CGI to mod_perl 2.0, Fast!
From CGI to mod_perl 2.0, Fast!
 
How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server
 
Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
 

Similar to PSGI and Plack from first principles

PECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterPECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterZendCon
 
HackU PHP and Node.js
HackU PHP and Node.jsHackU PHP and Node.js
HackU PHP and Node.jssouridatta
 
PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)xSawyer
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统yiditushe
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpmsom_nangia
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpmwilburlo
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment Evaldo Felipe
 
Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!cloudbring
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with PerlDave Cross
 

Similar to PSGI and Plack from first principles (20)

Modern Perl
Modern PerlModern Perl
Modern Perl
 
Plack at YAPC::NA 2010
Plack at YAPC::NA 2010Plack at YAPC::NA 2010
Plack at YAPC::NA 2010
 
Pecl Picks
Pecl PicksPecl Picks
Pecl Picks
 
PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
PECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterPECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life better
 
HackU PHP and Node.js
HackU PHP and Node.jsHackU PHP and Node.js
HackU PHP and Node.js
 
PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Api Design
Api DesignApi Design
Api Design
 
Lecture8
Lecture8Lecture8
Lecture8
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!
 
Sprockets
SprocketsSprockets
Sprockets
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 

Recently uploaded

TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...marcuskenyatta275
 
2024 May Patch Tuesday
2024 May Patch Tuesday2024 May Patch Tuesday
2024 May Patch TuesdayIvanti
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptxFIDO Alliance
 
Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftshyamraj55
 
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Hiroshi SHIBATA
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...FIDO Alliance
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Skynet Technologies
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfalexjohnson7307
 
Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024Patrick Viafore
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024Stephen Perrenod
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxFIDO Alliance
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxFIDO Alliance
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024Lorenzo Miniero
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe中 央社
 
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial IntelligenceRevolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial IntelligencePrecisely
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentationyogeshlabana357357
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightSafe Software
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxFIDO Alliance
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfAnubhavMangla3
 

Recently uploaded (20)

TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
 
2024 May Patch Tuesday
2024 May Patch Tuesday2024 May Patch Tuesday
2024 May Patch Tuesday
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
 
Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoft
 
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdf
 
Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptx
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial IntelligenceRevolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
 

PSGI and Plack from first principles

  • 1. PSGI and Plack from first principles Peter Sergeant Perl Careers http://perl.careers/
  • 2. Goals • Explain PSGI and Plack in the simplest terms possible, with examples • Demystify and demagicify how they work • Leave you in a position where you understand the mechanics well enough to reason about issues
  • 3. Specific Goal • Leave you in a position where the following code makes perfect sense to you… • And you understand what’s going on behind the scenes #!/usr/bin/env plackup use strict; use warnings; use MyApp::Web; use Plack::Builder; builder { mount '/heartbeat' => sub { return [ 200, ['Content-type' => 'text/plain'], [ "OK" ] ]; }; mount '/' => builder { enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' } 'Debug'; enable "GNUTerryPratchett"; MyApp::Web->psgi_app; } };
  • 4. A brief, incomplete and largely inaccurate history of dynamic webpages
  • 5. 1991 • HTTP0.9 • Webservers exist to serve mostly static HTML documents • Some HTML documents carry <ISINDEX>, which causes the browser to give you a text box you can type in, and it’ll stick it on the end of the request after a ? • Immediately obvious to everyone that it’d be much cooler to have fully interactive pages like on BBSs
  • 6. 1993 • 02 Jun: “HTML+” gains <INPUT> and <SELECT> elements • 05 Sep: Mosaic implements sending that data in the /?foo=bar&baz=flux format • 13 Sep: NCSA httpd supports: • "server scripts, which are executable programs which the server runs to generate documents on the fly. They are easy to write and can be written in your favorite language, whether it be C, PERL, or even the Bourne shell"
  • 7. 1993 continued • 14 Nov • NCSA httpd author complains that no-one is writing scripts because they’re worried the interface will change • Asks for help solving some of the issues and concerns about this interface • 17 Nov • He incorporates feedback, releases “CGP/1.0 Specification” • Two days later he renames it to “CGI” • 13 Dec • NCSA httpd 1.0 comes out of alpha, released with “CGI Support” and some samples • Pretty much all of these examples still work perfectly
  • 8. CGI • The webserver asks the OS to execute a specific executable, and passes data from the HTTP request to it via STDIN and ENV • The executable is expected to pass back HTTP headers and content on STDOUT • It’s really simple • Although it them almost 11 years to get an RFC out
  • 9. CGI - Example #!/usr/bin/perl use strict; use warnings; use URI::Escape qw/uri_unescape/; my $who = $ENV{'REMOTE_ADDR'}; my $query_string = $ENV{'QUERY_STRING'}; # Don't do this, use CGI.pm my %p = map { uri_unescape $_ } map { split(/=/, $_) } split(/&/, $query_string ); my $message = sprintf("Hello [%s] - you gave us the message: [%s]", $who, $p{'message'} || '(no message)'); my $status = 200; my $content_type = 'text/plain'; print <<"RESPONSE"; Status: $status Content-type: $content_type $message RESPONSE
  • 10. Easy to run • Pretend to be a webserver on the command line: $ REMOTE_ADDR=127.0.0.1 QUERY_STRING="message=Hello%20World” ./hello_world.cgi Status: 200 Content-type: text/plain Hello [127.0.0.1] - you gave us the message: [Hello World]
  • 11. Easy to run • Apache runs it just as well without any modification
  • 12. CGI • Still going strong after 22 years • 2004 saw the release of an RFC, after 7 years of work(!) • Doesn’t scale • Fires up a new process on each request • This can be expensive when: • The process is perl • It wants to load a bunch of modules from disk • Sets up a DB connection or three • Reads and parses your config file • etc
  • 13. Persistent Approaches • Load perl and your application once • Fast! • Several approaches
  • 14. mod_perl • Most popular approach • Apache-specific • Each Apache process embeds perl • Reformulate your code as a module, that implements a specific interface
  • 15. mod_perl example package HelloWorld::Simple; use strict; use warnings; use Apache::Constants qw(:common); sub handler { my $r = shift; $r->content_type('text/plain'); $r->send_http_header; my $who = $r->get_remote_host; # Don't do this, use CGI.pm my %p = map { uri_unescape $_ } map { split( /=/, $_ ) } split( /&/, $r->args ); $r->print( sprintf( <<RESPONSE, Hello [%s] - you gave us the message: [%s] RESPONSE $who, $p{'message'} || '(no message)' ) ); return OK;} 1;
  • 16. Other approaches • FastCGI – provides server-specific shims to communicate with long-running perl processes • ActivePerl ISAPI interface for IIS • Perl-based web server • … each of which has a different API that needs targeting …
  • 17. Pre-PSGI landscape • Your application needed to know what kind of server it was going to run on • Each framework that tried to abstract the details needed server-specific shims, eg: • Catalyst::Engine::CGI • Catalyst::Engine::SCGI • Catalyst::Engine::Zeus • Catalyst::Engine::FastCGI • Catalyst::Engine::Apache::MP13 • Catalyst::Engine::Apache2::MP19 • Catalyst::Engine::Apache2::MP20 • Catalyst::Engine::HTTP::POE • ... and the rest
  • 19. Where it fits in the landscape Server-agnostic Perl Long-running Perl-level API CGI mod_perl FastCGI PSGI
  • 20. Not so very different from CGI Rather than reading from %ENV and writing to STDOUT, our PSGI file defines an anonymous subroutine which accepts a hashref, and returns an arrayref That CGI example again …as a PSGI application
  • 21. Runs on the command line • Needs a little bit of massaging, but: $ REMOTE_ADDR=127.0.0.1 QUERY_STRING="message=Hello%20World” perl -e 'my $app = do ”hello.psgi"; print join "n", map { ref $_ ? @$_ : $_ } @{ $app->(%ENV); }’ 200 Content-type text/plain Hello [127.0.0.1] - you gave us the message: [Hello World]
  • 22. Build your own CGI PSGI interface! • We can write a simple (and stupid) adaptor to run PSGI #!/usr/bin/perl use strict; use warnings; my $app = do "plack.psgi"; my ( $status, $headers, $content ) = @{ $app->( %ENV ) }; print "Status: $statusn"; while ( @$headers ) { printf("%s: %sn", shift( @$headers ), shift( @$headers )); } print "n"; # Delineate headers and body print join "n", @$content;
  • 23. Or even… • A simple mod_perl adaptor • An LWP work-alike which pushes requests directly in to our app • All sorts of other things we don’t have time for, BUT…
  • 24. Actually… • Don’t do any of that… • Plack provides a set of tools that implement PSGI • Plack::Handler::CGI • Plack::Handler::Apache[12] • Plack::Handler::LWPish • The point is, there’s NO MAGIC • A PSGI file is just a file which returns a Perl subroutine reference
  • 26. So What? • Kinda cool • Nice to know it exists • Primarily of interest to framework creators • Why should you care?
  • 27. Fun with functions • Because the interface is a subroutine reference, with a predictable interface, you can combine these subroutines • Let’s say you wanted to combine two different PSGI-based services, and dispatch them based on URL… • Perhaps you had a monitoring system which expected a certain end-point, and you didn’t want to bake that in to your business logic…
  • 28. Fun with functions #!perl use strict; use warnings; my $monitoring = do "./monitoring.psgi"; my $main_app = do "./app.psgi"; my $app = sub { my $env = $_[0]; if ( $env->{'PATH_INFO'} eq 'heartbeat' ) { return $monitoring->( @_ ); } else { return $main_app->( @_ ); } };
  • 29. Fun with functions • Because you know the input and output format, you can wrap the request incoming and outgoing • YAPC::EU 2003 saw a bit of an obsession with the colour orange, and led to the creation of Acme::Tango, which turns colours orange • This is obviously important functionality, but probably shouldn’t live in the business logic…
  • 30. Acme::Tango example #!/usr/bin/perl use strict; use warnings; use Acme::Tango; use Plack::App::Proxy; my $main_app = do "tango_target_app.psgi"; my $app = sub { my $env = shift(); my ( $status, $headers, $content ) = @{ $main_app->( $env ) }; my %headers = @$headers; if ( ( $headers{'Content-type'} || $headers{'Content-Type'} ) =~ m'text/(html|css)' ) { if ( ref $content eq 'ARRAY' ) { $content = [ map { s/(#[a-f0-9]{6}|#[a-f0-9]{3})b/Acme::Tango::drink($1)/gei; $_ } @$content ] } } return [ $status, $headers, $content ]; };
  • 33. Wrapping for fun and profit • Generally the idea of being able to add wrapping code around your app is useful • These wrappers are called “Middleware” in the PSGI / Plack world
  • 34. Plack::Builder makes this easy! • ‘builder’ takes a subroutine which should return a PSGI app • ‘enable’ adds the name of a middleware you wish to apply to that app to a list • ‘builder’ wraps the app in that middleware, returning … a new PSGI app use Plack::Builder; my $app = sub { ... }; builder { enable "Deflater"; enable "+My::Plack::Middleware"; enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' } 'Debug' return $app; };
  • 35. CPAN is full of Plack Middleware AccessLog Auth::Basic Auth::Digest Auth::OAuth Chunked Class::Refresh Compile Conditional ConditionalGETConsoleLogger ContentLength ContentMD5 CrossOriginCSRFBlock Dancer::Debug DBIC::QueryLog Debug Debug::DBIC::QueryLogDebug::DBIProfile Debug::Profiler::NYTProf Debug::W3CValidateDeflater DebugDebug::CatalystPluginCache DoCoMoGUID Doorman ErrorDocument ErrorDocument ESI ETagExpires File::Sass Firebug::Lite FirePHP ForceEnv Head HeaderHTMLify HTMLMinify HTTPExceptions IEnosniff IIS6ScriptNameFixImage::Scale Inline InteractiveDebugger IPAddressFilter iPhoneJavaScript::Ectype JSConcat JSONP LighttpdScriptNameFix Lint LintLog::Contextual Log4perl Log::Minimal LogDispatch Logger LogWarnMethodOverride Mirror NeverExpire NoDeflate NoMultipleSlashesNullLogger Options OptionsOK Precompressed ProxyMapRearrangeHeaders Recursive RefererCheck Refresh Refresh REPL ReproxyReverseProxy ReverseProxy Rewrite Runtime Scope::Container Scope::SessionServerStatus::Lite Session Session Session::SerializedCookie SetAcceptSimpleContentFilter SimpleLogger SizeLimit SocketIO SSIStackTrace StackTrace Static Static Static::Minifier StaticShared StatusTest::StashWarnings Throttle Throttle TMT UseChromeFrame Watermark
  • 36. An Example… • We’ve only got time for one example in a 20 minute talk… • Add a couple of lines to wrap out Hello World app in Plack::Mid dleware::D ebug #!/usr/bin/perl use strict; use warnings; use URI::Escape qw/uri_unescape/; use Plack::Builder; my $app = sub { local %ENV = %{ shift() }; my $who = $ENV{'REMOTE_ADDR'}; my $query_string = $ENV{'QUERY_STRING'}; # Don't do this, use CGI.pm my %p = map { uri_unescape $_ } map { split( /=/, $_ ) } split( /&/, $query_string ); my $message = sprintf( "<html><head></head><body>Hello [%s] - " . "you gave us the message: [%s]</body></html>", $who, $p{'message'} || '(no message)' ); my $status = 200; my $content_type = 'text/html'; return [ $status, [ 'Content-type' => $content_type ], [$message], ]; }; builder { enable 'Debug', panels => [ qw(Memory Timer) ]; $app; }
  • 40. In Summary • PSGI defines inputs and outputs for a subroutine which encapsulate a web app • A PSGI file simply returns a subroutine reference • The hosting webserver `evals` (actually `do`) the PSGI file, and takes a copy of the resulting subroutine reference, and executes it on each request • Plack • Provides the ways to hook that up to the webservers of your choice • Makes it easy to wrap/manipulate these subroutine with some syntactic sugar • There’s an incredible collection of prewritten wrappers called Middleware on the CPAN
  • 41. The starting example, at the end #!/usr/bin/env plackup use strict; use warnings; use MyApp::Web; use Plack::Builder; builder { mount '/heartbeat' => sub { return [ 200, ['Content-type' => 'text/plain'], [ "OK" ] ]; }; mount '/' => builder { enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' } 'Debug'; enable "GNUTerryPratchett"; MyApp::Web->psgi_app; } };
  • 42. fin