Modern Perl Web Developement Dave Cross Magnum Solutions Ltd [email_address]
Web Development <ul><li>People have been developing web applications for over 15 years
Surely it is easy now
Lessons have been learned
Best practices have been worked out </li></ul>
History of Perl & Web <ul><li>Common Gateway Interface 1993
Defined the interaction between a web server and a program
Dynamic web pages </li></ul>
CGI <ul><li>Request includes parameters
Program processes parameters and produces response
Response includes program's output </li></ul>
Mid-Late 1990s <ul><li>Every web site gained dynamic pages
Form to email
Guestbook
Hit counter
Etc...
Most of them were written in Perl </li></ul>
CGI Problems <ul><li>CGI can be slow
Perl compiler starts up on every request
Can be very slow
Not useful for heavy traffic sites </li></ul>
mod_perl <ul><li>Everyone used Apache
Apache allowed loadable modules
mod_perl loads a Perl compiler
Persistent Perl processes
No more start-up costs
Huge performance improvements </li></ul>
Downsides <ul><li>Can't just use your CGI programs </li><ul><li>ModPerl::Registry </li></ul><li>Program is now called as a...
Global variable issues
Many programs needed rewrites
Different input and output methods </li></ul>
Other Environments <ul><li>FastCGI
Microsoft IIS
lighttpd
Etc...
Lack of portability
Hold that thought </li></ul>
CGI Programs <ul><li>CGI programs do three things
Read user input
Process data
Produce output
Let's look at input and output in more detail </li></ul>
Output <ul><li>CGI programs produce two types of output
Headers </li><ul><li>Content-type </li></ul><li>Body </li><ul><li>The actual data (HTML, etc) </li></ul></ul>
Simple CGI Output <ul><li>#!/usr/bin/perl print “Content-type: text/plainnn”; print 'The time is: ',   scalar localtime; <...
HTML <ul><li>#!/usr/bin/perl print “Content-type: text/htmlnn”; my $time = localtime; print <<END_HTML; <html><head><title...
Enter CGI.pm <ul><li>CGI.pm standard part of Perl distribution
Handles CGI processing for you
Input and output
Output in the form of CGI & HTML helper functions </li></ul>
HTML With CGI.pm <ul><li>#!/usr/bin/perl use CGI ':standard'; print header; # default text/html my $time = localtime; prin...
Downsides <ul><li>Mixing HTML and Perl code is nasty
What if you have a designer?
HTML experts don't always know Perl
Use a templating system instead </li></ul>
Template Toolkit <ul><li><html>   <head>   <title>Time</title>   </head>   <body>   <h1>Time</h1>   <p>The time is: [% tim...
Template Toolkit <ul><li><html>   <head>   <title>Time</title>   </head>   <body>   <h1>Time</h1>   <p>The time is:  [% ti...
Template Toolkit <ul><li>Separate the HTML into a separate file
Use tags where the variable output goes
Easier to edit by your HTML team </li></ul>
Template Toolkit & Perl <ul><li>#!/usr/bin/perl use Template; use CGI 'header'; print header; my $tt = Template->new; my $...
User Input <ul><li>Users send input to CGI programs
Parameters encoded in the URL
http://example.com/cgi-bin/stuff?name=davorg&lang=Perl
Need to access these parameters
N.B. I'm deliberately ignoring POST requests for simplicity </li></ul>
Old Style <ul><li>@pairs = split /&/, $ENV{QUERY_STRING}; foreach $pair (@pairs) {   ($k, $v) = split /=/, $pair;   $k =~ ...
CGI.pm Style <ul><li>use CGI ':standard'; my $name = param('name'); </li></ul>
However <ul><li>mod_perl has a different method for accessing parameters
Apache2::Request
Other environments have different methods
This is where PSGI comes in </li></ul>
PSGI & Plack
PSGI/Plack <ul><li>“ PSGI is an interface between Perl web applications and web servers, and Plack is a Perl module and to...
PSGI/Plack <ul><li>PSGI is a specification (based on Python's WSGI)
Plack is a reference implementation (based on Ruby's Rack) </li></ul>
The Problem <ul><li>There are many ways to write web applications
Upcoming SlideShare
Loading in...5
×

Modern Web Development with Perl

35,547

Published on

An introduction to PSGI and Plack that I gave at the London Perl Workshop in December 2010.

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
35,547
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
267
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Modern Web Development with Perl

  1. 1. Modern Perl Web Developement Dave Cross Magnum Solutions Ltd [email_address]
  2. 2. Web Development <ul><li>People have been developing web applications for over 15 years
  3. 3. Surely it is easy now
  4. 4. Lessons have been learned
  5. 5. Best practices have been worked out </li></ul>
  6. 6. History of Perl & Web <ul><li>Common Gateway Interface 1993
  7. 7. Defined the interaction between a web server and a program
  8. 8. Dynamic web pages </li></ul>
  9. 9. CGI <ul><li>Request includes parameters
  10. 10. Program processes parameters and produces response
  11. 11. Response includes program's output </li></ul>
  12. 12. Mid-Late 1990s <ul><li>Every web site gained dynamic pages
  13. 13. Form to email
  14. 14. Guestbook
  15. 15. Hit counter
  16. 16. Etc...
  17. 17. Most of them were written in Perl </li></ul>
  18. 18. CGI Problems <ul><li>CGI can be slow
  19. 19. Perl compiler starts up on every request
  20. 20. Can be very slow
  21. 21. Not useful for heavy traffic sites </li></ul>
  22. 22. mod_perl <ul><li>Everyone used Apache
  23. 23. Apache allowed loadable modules
  24. 24. mod_perl loads a Perl compiler
  25. 25. Persistent Perl processes
  26. 26. No more start-up costs
  27. 27. Huge performance improvements </li></ul>
  28. 28. Downsides <ul><li>Can't just use your CGI programs </li><ul><li>ModPerl::Registry </li></ul><li>Program is now called as a subroutine
  29. 29. Global variable issues
  30. 30. Many programs needed rewrites
  31. 31. Different input and output methods </li></ul>
  32. 32. Other Environments <ul><li>FastCGI
  33. 33. Microsoft IIS
  34. 34. lighttpd
  35. 35. Etc...
  36. 36. Lack of portability
  37. 37. Hold that thought </li></ul>
  38. 38. CGI Programs <ul><li>CGI programs do three things
  39. 39. Read user input
  40. 40. Process data
  41. 41. Produce output
  42. 42. Let's look at input and output in more detail </li></ul>
  43. 43. Output <ul><li>CGI programs produce two types of output
  44. 44. Headers </li><ul><li>Content-type </li></ul><li>Body </li><ul><li>The actual data (HTML, etc) </li></ul></ul>
  45. 45. Simple CGI Output <ul><li>#!/usr/bin/perl print “Content-type: text/plainnn”; print 'The time is: ', scalar localtime; </li></ul>
  46. 46. HTML <ul><li>#!/usr/bin/perl print “Content-type: text/htmlnn”; my $time = localtime; print <<END_HTML; <html><head><title>Time</title></head> <body><h1>Time</h1> <p>The time is: $time.</p></body></html> END_HTML </li></ul>
  47. 47. Enter CGI.pm <ul><li>CGI.pm standard part of Perl distribution
  48. 48. Handles CGI processing for you
  49. 49. Input and output
  50. 50. Output in the form of CGI & HTML helper functions </li></ul>
  51. 51. HTML With CGI.pm <ul><li>#!/usr/bin/perl use CGI ':standard'; print header; # default text/html my $time = localtime; print start_html(title => 'Time'), h1('Time'), p(“The time is: $time”); end_html; </li></ul>
  52. 52. Downsides <ul><li>Mixing HTML and Perl code is nasty
  53. 53. What if you have a designer?
  54. 54. HTML experts don't always know Perl
  55. 55. Use a templating system instead </li></ul>
  56. 56. Template Toolkit <ul><li><html> <head> <title>Time</title> </head> <body> <h1>Time</h1> <p>The time is: [% time %].</p> </body> </html> </li></ul>
  57. 57. Template Toolkit <ul><li><html> <head> <title>Time</title> </head> <body> <h1>Time</h1> <p>The time is: [% time %] .</p> </body> </html> </li></ul>
  58. 58. Template Toolkit <ul><li>Separate the HTML into a separate file
  59. 59. Use tags where the variable output goes
  60. 60. Easier to edit by your HTML team </li></ul>
  61. 61. Template Toolkit & Perl <ul><li>#!/usr/bin/perl use Template; use CGI 'header'; print header; my $tt = Template->new; my $time = localtime; $tt->process('time.tt', { time => $time } or die $tt->error; </li></ul>
  62. 62. User Input <ul><li>Users send input to CGI programs
  63. 63. Parameters encoded in the URL
  64. 64. http://example.com/cgi-bin/stuff?name=davorg&lang=Perl
  65. 65. Need to access these parameters
  66. 66. N.B. I'm deliberately ignoring POST requests for simplicity </li></ul>
  67. 67. Old Style <ul><li>@pairs = split /&/, $ENV{QUERY_STRING}; foreach $pair (@pairs) { ($k, $v) = split /=/, $pair; $k =~ tr/+/ /; $k =~ s/%([a-f0-9]{2})/pack 'C', hex($1)/ieg; $v =~ tr/+/ /; $v =~ s/%([a-f0-9]{2})/pack 'C', hex($1)/ieg; $form{$k} = $v; } # And then later... my $name = $form{name}; </li></ul><ul><li>@pairs = split /&/, $ENV{QUERY_STRING}; foreach $pair (@pairs) { ($k, $v) = split /=/, $pair; </li></ul>
  68. 68. CGI.pm Style <ul><li>use CGI ':standard'; my $name = param('name'); </li></ul>
  69. 69. However <ul><li>mod_perl has a different method for accessing parameters
  70. 70. Apache2::Request
  71. 71. Other environments have different methods
  72. 72. This is where PSGI comes in </li></ul>
  73. 73. PSGI & Plack
  74. 74. PSGI/Plack <ul><li>“ PSGI is an interface between Perl web applications and web servers, and Plack is a Perl module and toolkit that contains PSGI middleware, helpers and adapters to web servers.” </li><ul><li>http://plackperl.org/ </li></ul></ul>
  75. 75. PSGI/Plack <ul><li>PSGI is a specification (based on Python's WSGI)
  76. 76. Plack is a reference implementation (based on Ruby's Rack) </li></ul>
  77. 77. The Problem <ul><li>There are many ways to write web applications
  78. 78. There are many ways to write web applications in Perl
  79. 79. Each is subtly different
  80. 80. Hard to move an application between server architectures </li></ul>
  81. 81. Server Architectures <ul><li>CGI
  82. 82. FastCGI
  83. 83. mod_perl
  84. 84. etc... </li></ul>
  85. 85. Frameworks <ul><li>There are many Perl web application frameworks
  86. 86. Each creates applications in subtly different ways
  87. 87. Hard to port applications between them </li></ul>
  88. 88. The Goal <ul><li>What if we had a specification that allowed us to easily move web applications between server architectures and frameworks
  89. 89. PSGI is that specification </li></ul>
  90. 90. PSGI Application <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  91. 91. PSGI Application <ul><li>A code reference
  92. 92. Passed a reference to an environment hash
  93. 93. Returns a reference to a three-element array </li><ul><li>Status code
  94. 94. Headers
  95. 95. Body </li></ul></ul>
  96. 96. A Code Reference <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  97. 97. A Code Reference <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  98. 98. Environment Hash <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  99. 99. Environment Hash <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  100. 100. Return Array Ref <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  101. 101. Return Array Ref <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  102. 102. Return Array Ref <ul><li>my $app = sub { my $env = shift; return [ 200 , [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ], ]; }; </li></ul>
  103. 103. Return Array Ref <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ] , [ ‘Hello World’ ], ]; }; </li></ul>
  104. 104. Return Array Ref <ul><li>my $app = sub { my $env = shift; return [ 200, [ ‘Content-Type’, ‘text/plain’ ], [ ‘Hello World’ ] , ]; }; </li></ul>
  105. 105. Running PSGI App <ul><li>Put code in app.psgi
  106. 106. Drop in into a configured PSGI-aware web server
  107. 107. Browse to URL </li></ul>
  108. 108. PSGI-Aware Server <ul><li>Plack contains a simple test server called plackup
  109. 109. $ plackup app.psgi HTTP::Server::PSGI: Accepting connections at http://localhost:5000/ </li></ul>
  110. 110. More About $env <ul><li>use Data::Dumper; my $app = sub { my $env = shift; return [ 200, [ 'Content-type', 'text/plain' ], [ Dumper $env ], ]; } </li></ul>
  111. 111. Plack::Request <ul><li>Plack::Request turns the environment into a request object </li></ul>
  112. 112. Plack::Request <ul><li>use Plack::Request; use Data::Dumper; my $app = sub { my $req = Plack::Request->new(shift); return [ 200, [ 'Content-type', 'text/plain' ], [ Dumper $req ], ]; } </li></ul>
  113. 113. Plack::Response <ul><li>Plack::Response builds a PSGI response object </li></ul>
  114. 114. Plack::Response <ul><li>use Plack::Request; use Plack::Response; use Data::Dumper; my $app = sub { my $req = Plack::Request->new(shift); my $res = Plack::Response->new(200); $res->content_type('text/plain'); $res->body(Dumper $req); return $res->finalize; } </li></ul>
  115. 115. Time Example <ul><li>my $app = sub { my $env = shift; return [ 200, [ 'Content-type', 'text/plain' ], [ scalar localtime ], ] }; </li></ul>
  116. 116. Time With HTML <ul><li>my $app = sub { my $env = shift; my $now = localtime; return [ 200, [ 'Content-type', 'text/html' ], [&quot;<html><head><title>Time</title></head> <body><h1>Time</h1><p>The time is $now</p> </body></html>&quot; ] ] }; </li></ul>
  117. 117. Time With TT <ul><li>use Template; my $app = sub { my $tt = Template->new; my $out; $tt->process('time.tt', { time => scalar localtime }, $out) or die $tt->error; return [ 200, [ 'Content-type', 'text/html' ], [ $out ] ] }; </li></ul>
  118. 118. User Input <ul><li>Get user input from two places
  119. 119. Parse the query string from the $env hash
  120. 120. Ask the Plack::Request object </li></ul>
  121. 121. Input <ul><li>use Plack::Request; use Data::Dumper; my $app = sub { my $req = Plack::Request->new(shift); my $content; if (keys %{$req->parameters}) { $content = response($req); } else { $content = form(); } return [ 200, [ 'Content-type', 'text/html' ], [ $content ], ]; }; </li></ul>
  122. 122. Displaying a Form <ul><li>sub form { return <<END_OF_FORM; <html> ... stuff... <form> <input name=”name”> ... stuff ... </form> </html> END_OF_HTML } </li></ul>
  123. 123. Displaying the Response <ul><li>sub response { my $req = shift; my $name = $req->parameters->{name}; print <<END_OF_HTML <html> ... stuff ... <p>Name: $name</p> ... stuff ... </html> END_OF_HTML } </li></ul>
  124. 124. Using Templates <ul><li>Both form and response can be produced using TT
  125. 125. This is left as an exercise for the reader </li></ul>
  126. 126. Building Applications <ul><li>A PSGI program can be an entire application
  127. 127. The secret is in the 'path_info' input
  128. 128. $env->{PATH_INFO}
  129. 129. /
  130. 130. /person/1
  131. 131. /person/1/delete </li></ul>
  132. 132. Building Applications <ul><li>my $app = sub { my $env = shift; my $response = get_response_for( $env->{PATH_INFO} ); return $response; } </li></ul>
  133. 133. Frameworks <ul><li>At this point you should probably look at a framework
  134. 134. Catalyst
  135. 135. Dancer
  136. 136. Mojolicious
  137. 137. etc... </li></ul>
  138. 138. Advanced Plack
  139. 139. Middleware <ul><li>Middleware wraps around an application
  140. 140. Returns another PSGI application
  141. 141. Simple spec makes this easy
  142. 142. Plack::Middleware::*
  143. 143. Plack::Builder adds middleware configuration language </li></ul>
  144. 144. Middleware Example <ul><li>use Plack::Builder; use Plack::Middleware::Runtime; my $app = sub { my $env = shift; return [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world' ], ] }; builder { enable 'Runtime'; $app; } </li></ul>
  145. 145. Middleware Example <ul><li>$ HEAD http://localhost:5000 200 OK Date: Tue, 20 Jul 2010 20:25:52 GMT Server: HTTP::Server::PSGI Content-Length: 11 Content-Type: text/plain Client-Date: Tue, 20 Jul 2010 20:25:52 GMT Client-Peer: 127.0.0.1:5000 Client-Response-Num: 1 X-Runtime: 0.000050 </li></ul>
  146. 146. Middleware Example <ul><li>$ HEAD http://localhost:5000 200 OK Date: Tue, 20 Jul 2010 20:25:52 GMT Server: HTTP::Server::PSGI Content-Length: 11 Content-Type: text/plain Client-Date: Tue, 20 Jul 2010 20:25:52 GMT Client-Peer: 127.0.0.1:5000 Client-Response-Num: 1 X-Runtime: 0.000050 </li></ul>
  147. 147. Plack::App::* <ul><li>Ready-made solutions for common situations
  148. 148. Plack::App::CGIBin </li><ul><li>Cgi-bin replacement </li></ul><li>Plack::App::Directory </li><ul><li>Serve files with directory index </li></ul><li>Plack::App::URLMap </li><ul><li>Map apps to different paths </li></ul></ul>
  149. 149. Plack::App::* <ul><li>Many more bundled with Plack
  150. 150. Configured using Plack::Builder </li></ul>
  151. 151. Plack::App::CGIBin <ul><li>use Plack::App::CGIBin; use Plack::Builder; my $app = Plack::App::CGIBin->new( root => '/var/www/cgi-bin' )->to_app; builder { mount '/cgi-bin' => $app; }; </li></ul>
  152. 152. Plack::App::Directory <ul><li>use Plack::App::Directory; my $app = Plack::App::Directory->new( root => '/home/dave/Dropbox/psgi' )->to_app; </li></ul>
  153. 153. Framework Support <ul><li>Many modern Perl applications already support PSGI
  154. 154. Catalyst, CGI::Application, Dancer, Jifty, Mason, Maypole, Mojolicious, Squatting, Web::Simple
  155. 155. Many more </li></ul>
  156. 156. Catalyst Support <ul><li>Catalyst::Engine::PSGI
  157. 157. use MyApp; MyApp->setup_engine('PSGI'); my $app = sub { MyApp->run(@_) };
  158. 158. Also Catalyst::Helper::PSGI
  159. 159. script/myapp_create.pl PSGI </li></ul>
  160. 160. PSGI Server Support <ul><li>Many new web servers support PSGI
  161. 161. Starman, Starlet, Twiggy, Corona, HTTP::Server::Simple::PSGI
  162. 162. Perlbal::Plugin::PSGI </li></ul>
  163. 163. PSGI Server Support <ul><li>nginx support
  164. 164. mod_psgi
  165. 165. Plack::Handler::Apache2 </li></ul>
  166. 166. Plack::Handler::Apache2 <ul><li><Location /psgi> SetHandler perl-script PerlResponseHandler Plack::Handler::Apache2 PerlSetVar psgi_app /path/to/app.psgi </Location> </li></ul>
  167. 167. PSGI/Plack Summary <ul><li>PSGI is a specification
  168. 168. Plack is an implementation
  169. 169. PSGI makes your life easier
  170. 170. Most of the frameworks and server you use already support PSGI
  171. 171. No excuse not to use it </li></ul>
  172. 172. Further Information <ul><li>perldoc PSGI
  173. 173. perldoc Plack
  174. 174. http://plackperl.org/
  175. 175. http://blog.plackperl.org/
  176. 176. http://github.com/miyagawa/Plack
  177. 177. #plack on irc.perl.org </li></ul>
  178. 178. That's all folks <ul><li>Any questions? </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×