Plack Superglue for Perl Web Frameworks Tatsuhiko Miyagawa - - PowerPoint PPT Presentation

plack
SMART_READER_LITE
LIVE PREVIEW

Plack Superglue for Perl Web Frameworks Tatsuhiko Miyagawa - - PowerPoint PPT Presentation

Plack Superglue for Perl Web Frameworks Tatsuhiko Miyagawa YAPC::NA 2010 Tatsuhiko Miyagawa Lives in San Francisco Software Engineer @ Six Apart http://search.cpan.org/~miyagawa/ @miyagawa http://bulknews.typepad.com/ Web


slide-1
SLIDE 1

Plack

Superglue for Perl Web Frameworks

Tatsuhiko Miyagawa YAPC::NA 2010

slide-2
SLIDE 2

Tatsuhiko Miyagawa

  • Lives in San Francisco
  • Software Engineer @ Six Apart
  • http://search.cpan.org/~miyagawa/
  • @miyagawa
  • http://bulknews.typepad.com/
slide-3
SLIDE 3

Web Applications

slide-4
SLIDE 4

Hello World

slide-5
SLIDE 5

#!/usr/bin/perl use strict; print “Content‐Type: text/plain\r\n\r\n”; print “Hello World”;

slide-6
SLIDE 6

use FCGI; my $req = FCGI::Request(); while ($req‐>Accept >= 0) { print “Content‐Type: text/plain\r\n\r\n”; print “Hello World”; }

slide-7
SLIDE 7

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;

slide-8
SLIDE 8

package HelloWorld; use base qw(HTTP::Server::Simple::CGI); sub handle_request { my($self, $cgi) = @_; print “HTTP/1.0 200 OK\r\n”; print “Content‐Type: text/plain\r\n\r\n”; print “Hello World”; } 1;

slide-9
SLIDE 9

All similar but slightly different

slide-10
SLIDE 10

Painful to support all of them :(

slide-11
SLIDE 11

There is (was)

  • ne common way

to do all of this.

slide-12
SLIDE 12

#!/usr/bin/perl use CGI; my $q = CGI‐>new; print $q‐>header(‘text/plain’); print “Hello World”;

slide-13
SLIDE 13

Happens to work on:

CGI, FastCGI, mod_perl (HTTP::Server::Simple::CGI)

slide-14
SLIDE 14

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

slide-15
SLIDE 15

CGI.pm?

meh

slide-16
SLIDE 16

Frameworks to the rescue!

slide-17
SLIDE 17

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 Titanium

slide-18
SLIDE 18

MANY web frameworks

slide-19
SLIDE 19

Let’s look how they handle web servers.

slide-20
SLIDE 20

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

slide-21
SLIDE 21

CGI::Application

Apache IIS lighttpd

slide-22
SLIDE 22

CGI::Application

Apache IIS lighttpd

CGI.pm

slide-23
SLIDE 23

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

slide-24
SLIDE 24

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty

slide-25
SLIDE 25

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Catalyst

slide-26
SLIDE 26

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Catalyst Catalyst::Engine

slide-27
SLIDE 27

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Catalyst Catalyst::Engine nginx

slide-28
SLIDE 28

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Catalyst Catalyst::Engine nginx

HTTP::Server ::Simple

slide-29
SLIDE 29

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Mason Catalyst Catalyst::Engine nginx

HTTP::Server ::Simple

slide-30
SLIDE 30

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Mason Catalyst

Mason::CGIHandler

Catalyst::Engine nginx

HTTP::Server ::Simple

slide-31
SLIDE 31

Gross.

slide-32
SLIDE 32

CGI.pm

Jifty, CGI::Application, Spoon

mod_perl centric

Mason, Sledge, PageKit, WebGUI

Adapters

Catalyst, Maypole, Squatting

slide-33
SLIDE 33

That was 2008.

slide-34
SLIDE 34

Steal great idea from Python/Ruby

slide-35
SLIDE 35

WSGI (Python) Rack (Ruby)

slide-36
SLIDE 36

WSGI (PEP-333)

slide-37
SLIDE 37
slide-38
SLIDE 38

# WSGI def hello(environ, start_response): start_response(“200 OK”, [ (‘Content‐Type’, ‘text/plain’) ]) return [“Hello World”]

slide-39
SLIDE 39

WSGI

  • Django
  • Bottle
  • CherryPy
  • Tornado
  • Pylons
  • Flask
  • mod_wsgi
  • Paste
  • gunicorn
  • uWSGI
  • wsgiref
  • Google AppEngine
slide-40
SLIDE 40

WSGI

WSGI middleware Django Bottle Flask Tornado Apache lighttpd nginx mod_wsgi

wsgi handlers

GAE

slide-41
SLIDE 41

Rack

slide-42
SLIDE 42
slide-43
SLIDE 43

# Rack class Hello def call(env) return [ 200, { “Content‐Type” => ”text/plain” }, [“Hello World”] ] end end

slide-44
SLIDE 44

Rack

  • Rails
  • Merb
  • Sinatra
  • Camping
  • Ramaze
  • etc.
  • Unicorn
  • Thin
  • Mongrel
  • Rainbows!
  • Phusion Passenger
  • Heroku
slide-45
SLIDE 45

Rack

Rack middleware Rails Merb Sinatra Ramaze Apache lighttpd Thin Unicorn

Rack handlers

Mongrel

slide-46
SLIDE 46

PSGI

Perl Web Server Gateway Interface

slide-47
SLIDE 47

Interface

slide-48
SLIDE 48

# WSGI def hello(environ, start_response): start_response(“200 OK”, [ (‘Content‐Type’, ‘text/plain’) ]) return [“Hello World”]

slide-49
SLIDE 49

# Rack class Hello def call(env) return [ 200, { “Content‐Type” => ”text/plain” }, [“Hello World”] ] end end

slide-50
SLIDE 50

# PSGI my $app = sub { my $env = shift; return [ 200, [ ‘Content‐Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; };

slide-51
SLIDE 51

PSGI application

code reference $app = sub {...};

slide-52
SLIDE 52

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

CGI-like environment variables + psgi.input, psgi.errors etc.

slide-53
SLIDE 53

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

Status code (int.): 200, 404 etc.

slide-54
SLIDE 54

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

Array reference of header pairs: [ ‘Content-Type’, ‘text/html’, ... ]

slide-55
SLIDE 55

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

Array reference of content chunks Filehandle or IO::Handle-ish obejct

slide-56
SLIDE 56

That’s it.

(There’s a callback based streaming interface as well)

slide-57
SLIDE 57

# PSGI my $app = sub { my $env = shift; return [ 200, [ ‘Content‐Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; };

slide-58
SLIDE 58

Now you’ve got a PSGI application.

slide-59
SLIDE 59

PSGI makes it so simple to:

slide-60
SLIDE 60

Write a new Perl web app & framework

slide-61
SLIDE 61

Write a new Perl web server

slide-62
SLIDE 62

CGI::Application

Apache IIS lighttpd

CGI.pm

CGI fastcgi mod_perl

Jifty Mason Catalyst

Mason::CGIHandler

Catalyst::Engine nginx

HTTP::Server ::Simple

slide-63
SLIDE 63

PSGI

Plack::Middleware Catalyst CGI::App Jifty Tatsumaki Apache lighttpd

HTTP::Server::PSGI

Perlbal mod_psgi

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

slide-64
SLIDE 64

PSGI adaptation

slide-65
SLIDE 65

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 Titanium

slide-66
SLIDE 66

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 Titanium

slide-67
SLIDE 67

Applications

Movable Type 6, WebGUI 8

slide-68
SLIDE 68

# Catalyst use MyApp; MyApp‐>setup_engine(‘PSGI’); my $app = sub { MyApp‐>run(@_) }; # $app is a PSGI app!

slide-69
SLIDE 69

# Jifty use MyPonyApp; my $app = MyPonyApp‐>psgi_app; # $app is a PSGI app!

slide-70
SLIDE 70

# Dancer use Dancer; get ‘/’ => sub { “Hello World”; }; dance; # returns a PSGI app!

slide-71
SLIDE 71

# Mojolicious::Lite use Mojolicious::Lite; get ‘/:name’ => sub { my $self = shift; $self‐>render_text(‘Hello!’); }; app‐>start; # returns PSGI app

slide-72
SLIDE 72

# Web::Simple use Web::Simple ‘MyApp’; package MyApp; dispatch { sub(GET) { [ 200, [...], [ ‘Hello’ ] ]; } }; my $app = MyApp‐>as_psgi; # $app is a PSGI app!

slide-73
SLIDE 73

perldoc PSGI

If you want to adapt your framework to PSGI.

slide-74
SLIDE 74

Plack

“PSGI toolkit”

slide-75
SLIDE 75

HTTP::Server::PSGI

Reference PSGI web server bundled in Plack

slide-76
SLIDE 76

Plackup

Runs PSGI app instantly from CLI (inspired by rackup)

slide-77
SLIDE 77

> plackup app.psgi

slide-78
SLIDE 78

Plack::Handler

Connects PSGI apps to Web servers CGI, FastCGI, Apache, SCGI

slide-79
SLIDE 79

PSGI Web Servers

slide-80
SLIDE 80

Starman

UNIX Preforking HTTP servers (like Unicorn.rb) HTTP/1.1 chunk + keep-alives / Very Fast

slide-81
SLIDE 81

Starlet

Simpler UNIX HTTP/1.0 Server Best used with Server::Starter and nginx/lighttpd

slide-82
SLIDE 82

Twiggy

Non-blocking web server (like Thin.rb) based on AnyEvent framework

slide-83
SLIDE 83

Corona

Coroutine for each connection based on Coro.pm

slide-84
SLIDE 84

HTTP::Server::Simple::PSGI

Zero-deps other than HTTP::Server::Simple Best for embedding PSGI applications

slide-85
SLIDE 85

uWSGI

http://projects.unbit.it/uwsgi/

slide-86
SLIDE 86

Perlbal plugin

http://github.com/miyagawa/Perlbal-Plugin-PSGI

slide-87
SLIDE 87

nginx embedded perl

http://github.com/yappo/nginx-psgi-patchs

slide-88
SLIDE 88

mod_psgi

http://github.com/spiritloose/mod_psgi

slide-89
SLIDE 89

evpsgi

http://github.com/sekimura/evpsgi

slide-90
SLIDE 90

Feersum

http://github.com/stash/Feersum

slide-91
SLIDE 91

PSGI

Plack::Middleware Catalyst CGI::App Jifty Tatsumaki Apache lighttpd

HTTP::Server::PSGI

Perlbal mod_psgi

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

Starman Twiggy uWSGI Corona evpsgi

slide-92
SLIDE 92

Middleware

slide-93
SLIDE 93
slide-94
SLIDE 94

PSGI Middleware

Wraps a PSGI application to add pre/post processing

slide-95
SLIDE 95

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; };

slide-96
SLIDE 96

PSGI Middleware

coderef -> coderef Higher-order functions

slide-97
SLIDE 97

Middleware

Debug, Session, Logger, Runtime, Static, Lint, AccessLog, ConditionalGET, ErrorDocument, StackTrace, Auth::Basic, Auth::Digest, ReverseProxy, Refresh, Auth::OAuth, Hippie, Throttle

slide-98
SLIDE 98

Plack::Middleware

reusable and extensible Middleware framework Plack::Builder DSL in .psgi

slide-99
SLIDE 99

my $app = sub { return [ $status, $header, $body ]; }; use Plack::Builder; builder { enable “Static”, root => “/htdocs”, path => qr!^/static/!; enable “Deflater”; # gzip/deflate $app; }

slide-100
SLIDE 100

plackup compatible

plackup -e ‘enable “Foo”;’ app.psgi

slide-101
SLIDE 101

Middleware

Write once, run in every framework

slide-102
SLIDE 102

DEMO

slide-103
SLIDE 103

Plack::App::URLMap

Multiplex multiple apps Integrated with Builder DSL

slide-104
SLIDE 104

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; }; }

slide-105
SLIDE 105

CGI::PSGI

Easy migration from CGI.pm

slide-106
SLIDE 106

CGI::Emulate::PSGI CGI::Compile

Easiest migration from CGI scripts (like Registry)

slide-107
SLIDE 107

Plack::Request

like libapreq (Apache::Request) wrapper APIs for middleware developers

slide-108
SLIDE 108

Plack::Test

Unified interface to write tests with Mock HTTP and Live HTTP

slide-109
SLIDE 109

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; };

slide-110
SLIDE 110

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; };

slide-111
SLIDE 111

Plack::App::*

ready-to-use applications

slide-112
SLIDE 112

Plack::App::Directory

Static content file server

slide-113
SLIDE 113

Plack::App::Proxy

(non-blocking) proxy server Can be used as reverse proxy as well

slide-114
SLIDE 114

Plack::App::CGIBin

mount /cgi-bin as PSGI applications

slide-115
SLIDE 115

Plack::App::FCGIDispatcher

Connect to FCGI daemon (even in Ruby, Python, C)

slide-116
SLIDE 116

Plack::App::JSP

Runs JavaScript PSGI apps :)

slide-117
SLIDE 117

Testimonials

a.k.a. self-promotion

slide-118
SLIDE 118

“I love this! It’s exactly the right answer to what i was looking for.” - Benjamin Trott

slide-119
SLIDE 119

“Wow, this is nothing short of awesome.”

  • Stevan Little
slide-120
SLIDE 120

“Plack is so simple, easy and powerful.”

  • Jesse Vincent
slide-121
SLIDE 121

“Plack rocks. Miyagawa rocks.”

  • Piers Cawley
slide-122
SLIDE 122

“Is he on too many drugs or too few? Either way let’s make sure that never changes.”

  • Matt S. Trout
slide-123
SLIDE 123

Real World Plack/PSGI

slide-124
SLIDE 124
slide-125
SLIDE 125

You should join!

slide-126
SLIDE 126

> cpanm Plack > cpanm Task::Plack

slide-127
SLIDE 127

Cloud?

(Heroku, GAE)

slide-128
SLIDE 128

Sunaba

http://sunaba.plackperl.org/

slide-129
SLIDE 129
slide-130
SLIDE 130

Runs on dankogai’s Sandbox

slide-131
SLIDE 131

You can even try:

system(“rm ‐fr /”); while (1) { }

slide-132
SLIDE 132

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!
slide-133
SLIDE 133

Remember: Plack is < 1y old

slide-134
SLIDE 134

Lots of (exciting) things going on.

slide-135
SLIDE 135

http://blog.plackperl.org/

slide-136
SLIDE 136

http://github.com/miyagawa/Plack http://plackperl.org/ irc://irc.perl.org/#plack

slide-137
SLIDE 137

Questions?

slide-138
SLIDE 138

Thank you!

Slides: http://slideshare.net/miyagawa