2 <html><head><meta charset=
"utf-8"><title>Introduction to PSGI
</title><link rel=
"stylesheet" href=
"css/common.css"><link rel=
"stylesheet" href=
"css/slides.css"></head><body><textarea id=
"source">
16 ![Bluehost](img/bluehost.png)
18 ### https://bluehost.com/careers
24 - Answer "What is PSGI?"
25 - Examine some alternatives to PSGI.
33 ### **P**erl [web] **S**erver **G**ateway **I**nterface
36 - It is an interface between Perl web applications and web servers.
39 - It is a *specification*, not code.
42 - First released to the CPAN on
13 Oct
2009.
45 - Originally written by Miyagawa.
47 .center[![Tatsuhiko Miyagawa](img/avatar-miyagawa.jpg)]
50 Written by **Tatsuhiko Miyagawa**, author of:
53 - way too many Perl modules on CPAN to list
56 - Inspired by WSGI (Python) and Rack (Ruby).
59 - PEP-
333 (WSGI
1.0) was released on
07 Dec
2003.
60 - Rack
0.1 was released on
03 Mar
2007.
62 Despite Perl's long history of powering the web, we were well behind the curve on this.
69 ## Extremely High-level Overview
72 ![Basic Flow](img/basic-flow1.svg)
76 - PSGI is the language your app speaks in order to communicate with user agents.
77 - User agents are browsers.
78 - I've glossed over some important details, like the fact that users don't speak PSGI.
85 ## Pretty High-level Overview
88 ![Basic Flow](img/basic-flow2.svg)
92 - In reality, your app speaks PSGI but user agents speak HTTP.
93 - You need software in the middle that can speak both, and that's usually a web server.
100 ## Somewhat High-level Overview
103 ![Basic Flow](img/basic-flow3.svg)
107 - In reality, most web servers don't speak PSGI. :-(
108 - There are "handlers" that speak both PSGI and another language that web servers do speak.
113 - Yes, HTTP. Many modern web servers speak HTTP not only as a server but also as a client.
114 - This allows them to *proxy* (act as middleman) between user agents and other servers.
115 - In the world of PSGI (and "Plack"), handlers are also called adapters or connectors.
116 - There are already adapters for every major web server.
123 class: center, middle
126 ## Somewhat High-level Overview
129 ![Basic Flow](img/basic-flow4.svg)
133 - Notice that as we've zoomed in, the interaction between the web app and the rest has remained the
135 - From a developer perspective, the etremely high-level overview is sufficient.
136 - This is one of the benefits of PSGI:
137 - Write your application once and leave deployment details to devops.
138 - The intrastructure details can change (swap in a different web server) and the app will still work.
139 - Maybe you're both developer and system architect, but the separation between developer and
141 - In fairness, this isn't a new concept.
142 - The way this has been achieved before is using a *web framework*.
146 class: center, middle
149 ## High-level Overview
152 ![Basic Flow](img/basic-flow5.svg)
156 - A web framework makes it so your app doesn't need to speak HTTP or CGI or even PSGI.
164 > Writing your web application directly using [PSGI/Plack] is certainly possible but not recommended.
168 > If you're writing a web application, not a framework, then you're encouraged to use one of the web
169 > application frameworks that support PSGI (http://plackperl.org/#frameworks), or see modules like
170 > HTTP::Engine to provide higher level Request and Response API on top of PSGI.
172 > -- [Plack::Request Documentation](https://search.cpan.org/~miyagawa/Plack/lib/Plack/Request.pm)
175 - When you start learning about Plack, you'll realize that it is actually pretty capable.
176 - You may start to think that everything should be developed on that level -- don't do it!
177 - For most stuff, you'll still want to use a web framework.
178 - Web frameworks often offer more convenient abstractions than raw PSGI.
185 If you're a developer writing a web app, you're probably asking why then you should care about PSGI.
189 - So that you can understand how things work.
192 - I'll never understood people who don't want to understand things.
194 - I recommend you learn and understand as much as you can about the entire request-response cycle of
195 your web app; it will help you troubleshoot when things go wrong or aren't behaving as expected.
199 - So that you can do DevOps (if you want).
202 - New skills make you more marketable.
205 - So that you understand it when you see PSGI exposed through your web framework.
208 - You can do cool things with PSGI!
211 - Even if you do most of your work using your framework, you can do some useful things with PSGI.
212 - We will get to some of those cool things, so hang tight.
223 ### **H**yper**t**ext **T**ransfer **P**rotocol
226 - Invented by Tim Berners-Lee in
1989, first specified as [HTTP
0.9](https://www.w3.org/Protocols/HTTP/AsImplemented.html) in
1991.
229 - The IETF and W3C took over standards development, resulting in [RFC
1945](https://tools.ietf.org/html/rfc1945) ("HTTP
1.0") in
1996.
232 - IETF = Internet Engineering Task Force
233 - W3C = World Wide Web Consortium
236 - [RFC
2068](https://tools.ietf.org/html/rfc2068) ("HTTP
1.1") happened in
1997, superceded by [RFC
2616](https://tools.ietf.org/html/rfc2616) in
1999.
239 RFC
2616 was then superceded in
2014 by:
240 - [RFC
7230](https://tools.ietf.org/html/rfc7230)
241 - [RFC
7231](https://tools.ietf.org/html/rfc7231)
242 - [RFC
7232](https://tools.ietf.org/html/rfc7232)
243 - [RFC
7233](https://tools.ietf.org/html/rfc7233)
244 - [RFC
7234](https://tools.ietf.org/html/rfc7234)
245 - [RFC
7235](https://tools.ietf.org/html/rfc7235)
248 - Oh yeah, and HTTP2 came out in
2015, defined in [RFC
7540](https://tools.ietf.org/html/rfc7540).
257 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
259 Accept-Language: en-us
260 Connection: Keep-Alive
269 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
272 Content-Type: text/plain
275 Your IP address is
127.0.0.1.
286 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
288 Accept-Language: en-us
289 Connection: Keep-Alive
298 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
301 Content-Type: text/plain
304 Your IP address is
127.0.0.1.
309 1. Method, path, protocol/version
313 - Methods defined in HTTP/
1.1: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT
314 - RFC
5789 defined PATCH in March
2010.
323 *User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
325 *Accept-Language: en-us
326 *Connection: Keep-Alive
335 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
338 Content-Type: text/plain
341 Your IP address is
127.0.0.1.
346 1. Method, path, protocol/version
347 2. Headers (key-value pairs)
357 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
359 Accept-Language: en-us
360 Connection: Keep-Alive
369 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
372 Content-Type: text/plain
375 Your IP address is
127.0.0.1.
380 1. Method, path, protocol/version
381 2. Headers (key-value pairs)
382 3. Optional document (or "body")
392 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
394 Accept-Language: en-us
395 Connection: Keep-Alive
404 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
407 Content-Type: text/plain
410 Your IP address is
127.0.0.1.
415 1. Method, path, protocol/version
416 2. Headers (key-value pairs)
417 3. Optional document (or "body")
421 1. Protocol/version, status code, reason phrase
431 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
433 Accept-Language: en-us
434 Connection: Keep-Alive
443 *Date: Thu,
07 Jul
2016 11:
56:
23 GMT
446 *Content-Type: text/plain
449 Your IP address is
127.0.0.1.
454 1. Method, path, protocol/version
455 2. Headers (key-value pairs)
456 3. Optional document (or "body")
460 1. Protocol/version, status code, reason phrase
461 2. Headers (key-value pairs)
471 User-Agent: Mozilla/
5.0 (X11; Linux x86_64)
473 Accept-Language: en-us
474 Connection: Keep-Alive
483 Date: Thu,
07 Jul
2016 11:
56:
23 GMT
486 Content-Type: text/plain
489 *Your IP address is
127.0.0.1.
494 1. Method, path, protocol/version
495 2. Headers (key-value pairs)
496 3. Optional document (or "body")
500 1. Protocol/version, status code, reason phrase
501 2. Headers (key-value pairs)
502 3. Optional document (or "body")
509 ## Alternatives to PSGI
523 - All of these still exist, and actually all of these are still in common use.
524 - We're going to take a closer look at three of these.
528 ## Alternatives to PSGI
531 - .highlight[mod_perl]
532 - .highlight[FastCGI]
553 ### **C**ommon **G**ateway **I**nterface
556 - Created by the NCSA in
1993.
559 - NCSA = National Center for Supercomputing Applications
562 - More formally defined in [RFC
3875](https://tools.ietf.org/html/rfc3875) ("CGI Version
1.1") in October
2004.
567 my $client_ip = $ENV{'REMOTE_ADDR'};
569 print "Content-Type: text/plain\n";
570 print "Status:
200 OK\n";
573 print "Your IP address is ${client_ip}.";
579 *my $client_ip = $ENV{'REMOTE_ADDR'};
581 print "Content-Type: text/plain\n";
582 print "Status:
200 OK\n";
585 print "Your IP address is ${client_ip}.";
588 1. Gateway sets information about the request in the environment.
590 .condensed.marginfix[
595 - `GATEWAY_INTERFACE`
611 - other "protocol-specific" variables
616 - In Perl, you can get these using %ENV.
617 - Or getenv from stdlib.
618 - If you've done some web programming before, you're probably familiar with at least a few of these.
623 my $client_ip = $ENV{'REMOTE_ADDR'};
625 *print "Content-Type: text/plain\n";
626 *print "Status:
200 OK\n";
629 print "Your IP address is ${client_ip}.";
632 1. Gateway sets information about the request in the environment.
633 2. Print response headers to `STDOUT`.
635 .condensed.marginfix[
640 - other "protocol-specific" header fields
647 my $client_ip = $ENV{'REMOTE_ADDR'};
649 print "Content-Type: text/plain\n";
650 print "Status:
200 OK\n";
653 print "Your IP address is ${client_ip}.";
656 1. Gateway sets information about the request in the environment.
657 2. Print response headers to `STDOUT`.
663 my $client_ip = $ENV{'REMOTE_ADDR'};
665 print "Content-Type: text/plain\n";
666 print "Status:
200 OK\n";
669 *print "Your IP address is ${client_ip}.";
672 1. Gateway sets information about the request in the environment.
673 2. Print response headers to `STDOUT`.
675 4. Print response document (if any).
680 my $client_ip = $ENV{'REMOTE_ADDR'};
682 print "Content-Type: text/plain\n";
683 print "Status:
200 OK\n";
686 print "Your IP address is ${client_ip}.";
689 1. Gateway sets information about the request in the environment.
690 2. Print response headers to `STDOUT`.
692 4. Print response document (if any).
693 5. Read request document from `STDIN` (if any).
696 - CGI.pm helps cut down boilerplate by helping parse things like `QUERY_STRING` and `HTTP_COOKIE`,
697 producing correctly-formatted headers, and even producing HTML.
698 - CGI.pm was deprecated in perl
5.20 and remove from core in perl
5.22.
701 - Conceptually simple.
702 - Only requires the use of the most basic and primitive program constructs (stdin, stdout, env).
703 - Only other primitive construct that could have been used is that of passing program arguments.
704 - Actually, the spec does specify behavior for "search-strings" as program arguments.
707 - Details can get complicated.
708 - Although the de facto standard for years, modern web servers are choosing to not support it
710 - There is too much overhead in forking and execing.
718 ![FastCGI](img/fastcgi.png)
725 ### a low-overhead variation on CGI
728 - Binary protocol with support for pipelining and multiplexing.
731 - Open Market wrote the [specification](http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html) on
29 Apr
1996.
734 - Open Market was an ecommerce startup based in Massachusetts.
735 - Developed one of the first HTTP servers.
742 my $request = FCGI::Request();
744 while (
0 <= $request-
>Accept()) {
745 my $client_ip = $ENV{'REMOTE_ADDR'};
747 print "Content-Type: text/html\n\n";
748 print "Your IP address is ${client_ip}.";
757 *my $request = FCGI::Request();
759 while (
0 <= $request-
>Accept()) {
760 my $client_ip = $ENV{'REMOTE_ADDR'};
762 print "Content-Type: text/html\n\n";
763 print "Your IP address is ${client_ip}.";
767 1. Use `FCGI` and instantiate an object.
774 my $request = FCGI::Request();
776 *while (
0 <= $request-
>Accept()) {
777 my $client_ip = $ENV{'REMOTE_ADDR'};
779 print "Content-Type: text/html\n\n";
780 print "Your IP address is ${client_ip}.";
784 1. Use `FCGI` and instantiate an object.
785 2. Loop on `Accept()` which blocks until the next request is received.
792 my $request = FCGI::Request();
794 while (
0 <= $request-
>Accept()) {
795 * my $client_ip = $ENV{'REMOTE_ADDR'};
797 * print "Content-Type: text/html\n\n";
798 * print "Your IP address is ${client_ip}.";
802 1. Use `FCGI` and instantiate an object.
803 2. Loop on `Accept()` which blocks until the next request is received.
804 3. Otherwise appears similar to a CGI program.
811 my $request = FCGI::Request();
813 while (
0 <= $request-
>Accept()) {
814 my $client_ip = $ENV{'REMOTE_ADDR'};
816 print "Content-Type: text/html\n\n";
817 print "Your IP address is ${client_ip}.";
821 1. Use `FCGI` and instantiate an object.
822 2. Loop on `Accept()` which blocks until the next request is received.
823 3. Otherwise appears similar to a CGI program.
825 * IPC actually happens over a socket!
828 - Can be run unmodified as a CGI script by detecting that stdin is not a socket.
829 - Can read from stdin and write to stdout via the miracle of tied filehandles.
837 ![mod_perl](img/mod_perl.gif)
845 - First released on March
25,
1996.
848 - Unlike the interfaces we have examined so far, mod_perl is code.
849 - About the same time as FastCGI.
852 - Became an Apache Software Foundation project at ApacheCon
1999 in Orlando.
859 use Apache::RequestRec ();
860 use Apache::Connection ();
861 use Apache::Const -compile =
> qw(OK);
865 my $client_ip = $r-
>connection-
>remote_addr;
867 $r-
>content_type('text/plain');
868 $r-
>print("Your IP address is ${client_ip}.");
869 return Apache::Const::OK;
876 - Notice how we're not using STDOUT (or even pretending to).
877 - This program actually runs on a perl interpreter inside the web server.
878 - It also has access to more information through the exposed API.
881 - Can run CGI programs as-is.
884 - Can tie you to specific web servers.
885 - There's a separate mod_perl for nginx.
886 - Code runs in the same process as the HTTP server -- kinda scary.
887 - Using Apache's API feels heavy.
901 my $client_id = $env-
>{'REMOTE_ADDR'};
905 [ 'Content-Type' =
> 'text/plain' ],
906 [ "Your IP address is ${client_id}." ], # or IO::Handle-like object
912 - I think it's good to understand CGI et al. so that you can understand why it was designed the way
914 - Hopefully the ideas behind PSGI are based off of the best that CGI et al. had to offer without any
918 - Notice how the program is a subroutine.
919 - By being a subrouting rather than a script that is executed, we're already in a form that can be
920 called repeatedly without incurring fork-exec overhead. Nice!
927 * my $client_id = $env-
>{'REMOTE_ADDR'};
931 [ 'Content-Type' =
> 'text/plain' ],
932 [ "Your IP address is ${client_id}." ], # or IO::Handle-like object
940 1. Hashref of request information.
944 - Oh, look! The variable is the same as is specified by CGI.
945 - Why throw away over a decade of convention?
952 my $client_id = $env-
>{'REMOTE_ADDR'};
956 [ 'Content-Type' =
> 'text/plain' ],
957 [ "Your IP address is ${client_id}." ], # or IO::Handle-like object
965 1. Hashref of request information.
975 - Then you'll notice that instead of printing anything, we return an arrayref as the response.
982 my $client_id = $env-
>{'REMOTE_ADDR'};
986 * [ 'Content-Type' =
> 'text/plain' ],
987 [ "Your IP address is ${client_id}." ], # or IO::Handle-like object
995 1. Hashref of request information.
1001 1. HTTP status code.
1002 2. Arrayref of response headers.
1006 - Why not a hashref?
1007 - To support multiple headers (e.g. Set-Cookie)
1008 - It more closely resembles how the WSGI folks did it (i.e. list of tuples).
1015 my $client_id = $env-
>{'REMOTE_ADDR'};
1019 [ 'Content-Type' =
> 'text/plain' ],
1020 * [ "Your IP address is ${client_id}." ], # or IO::Handle-like object
1028 1. Hashref of request information.
1034 1. HTTP status code.
1035 2. Arrayref of response headers.
1036 3. Response document.
1040 - Body may be a list of chunks that are concatenated together or a handle to read from.
1051 .condensed.marginfix[
1054 - `HTTP_ACCEPT_ENCODING`
1055 - `HTTP_ACCEPT_LANGUAGE`
1056 - `HTTP_CACHE_CONTROL`
1075 - `psgi.multiprocess`
1076 - `psgi.multithread`
1077 - `psgi.nonblocking`
1083 - `psgix.input.buffered`
1090 .condensed.marginfix[
1092 - .highlight[`HTTP_ACCEPT`]
1093 - .highlight[`HTTP_ACCEPT_ENCODING`]
1094 - .highlight[`HTTP_ACCEPT_LANGUAGE`]
1095 - .highlight[`HTTP_CACHE_CONTROL`]
1096 - .highlight[`HTTP_CONNECTION`]
1097 - .highlight[`HTTP_DNT`]
1098 - .highlight[`HTTP_HOST`]
1099 - .highlight[`HTTP_USER_AGENT`]
1100 - .highlight[`PATH_INFO`]
1101 - .highlight[`QUERY_STRING `]
1102 - .highlight[`REMOTE_ADDR`]
1103 - .highlight[`REMOTE_PORT`]
1104 - .highlight[`REQUEST_METHOD`]
1105 - .highlight[`REQUEST_URI`]
1106 - .highlight[`SCRIPT_NAME`]
1109 - .highlight[`SERVER_NAME`]
1110 - .highlight[`SERVER_PORT`]
1111 - .highlight[`SERVER_PROTOCOL`]
1114 - `psgi.multiprocess`
1115 - `psgi.multithread`
1116 - `psgi.nonblocking`
1122 - `psgix.input.buffered`
1129 .condensed.marginfix[
1132 - `HTTP_ACCEPT_ENCODING`
1133 - `HTTP_ACCEPT_LANGUAGE`
1134 - `HTTP_CACHE_CONTROL`
1151 - .highlight[`psgi.errors`]
1152 - .highlight[`psgi.input`]
1153 - .highlight[`psgi.multiprocess`]
1154 - .highlight[`psgi.multithread`]
1155 - .highlight[`psgi.nonblocking`]
1156 - .highlight[`psgi.run_once`]
1157 - .highlight[`psgi.streaming`]
1158 - .highlight[`psgi.url_scheme`]
1159 - .highlight[`psgi.version`]
1160 - .highlight[`psgix.harakiri`]
1161 - .highlight[`psgix.input.buffered`]
1162 - .highlight[`psgix.io`]
1167 - Harakiri is a form of Japanese ritual suicide by disembowelment.
1175 - Everything is a data structure (almost).
1178 - Makes it easier to write tests because mocking either the app or server is clear.
1179 - Don't necessarily need to parse a bytestream to check stuff.
1182 - No global data or shared IO handles.
1185 - This lets you service multiple requests asynchronously in the same process/thread.
1188 - Takes deployment details out of web frameworks.
1191 - Web frameworks only need to target PSGI.
1192 - No need to worry about the boring stuff; they can focus on the abstractions that make them unique
1196 - End-users of your app have many deployment options for free.
1202 - [Catalyst](http://www.catalystframework.org/)
1203 - [Mojolicious](http://mojolicious.org/)
1204 - [Dancer](http://perldancer.org/)
1205 - [CGI::Application](http://cgi-app.org/)
1206 - [CGI::Ex](https://github.com/chazmcgarvey/CGI-Ex/tree/psgi-
2)
1207 - [Web::Simple](https://metacpan.org/pod/Web::Simple)
1208 - [Amon2](https://metacpan.org/pod/Amon2)
1209 - [Poet](https://metacpan.org/pod/Poet)
1210 - [Kelp](https://metacpan.org/pod/Kelp)
1211 - [Raisin](https://metacpan.org/pod/Raisin)
1220 - Provides tools for building, running, and testing PSGI apps.
1223 - [Plack::Handler](https://metacpan.org/pod/Plack::Handler)
1226 - Connects PSGI apps and web servers.
1227 - Takes a request from the server,
1228 - converts it to the PSGI-specified environment,
1230 - converts the response back to a format the server understands.
1233 - [Plack::Loader](https://metacpan.org/pod/Plack::Loader)
1236 - Picks an appropriate Plack::Handler (based on ENV, loaded modules, or arguments) and loads it.
1237 - Can also do stuff like restart the loader when files change.
1240 - [Plack::Runner](https://metacpan.org/pod/Plack::Runner), [plackup](https://metacpan.org/pod/plackup)
1243 - Run PSGI apps from the command-line.
1246 - [Plack::Middleware](https://metacpan.org/pod/Plack::Middleware)
1249 - Create subroutines that run between the handler and your app.
1250 - Can alter the request your app receives and modify the response your app returns.
1253 - [Plack::Request](https://metacpan.org/pod/Plack::Request), [Plack::Response](https://metacpan.org/pod/Plack::Response)
1256 - Request and response wrappers can help simplify writing middleware.
1259 - [Plack::Builder](https://metacpan.org/pod/Plack::Builder)
1262 - Provides DSL for composing apps and middleware.
1265 - [Plack::Test](https://metacpan.org/pod/Plack::Test), [Plack::Test::Suite](https://metacpan.org/pod/Plack::Test::Suite)
1268 - Use Plack::Test for testing apps.
1269 - Plack::Test::Suite is a series of tests for testing handlers.
1272 - [Plack::Util](https://metacpan.org/pod/Plack::Util)
1275 - Provides random useful stuff for handler and middleware developers.
1276 - Stuff like determing the length of a document or getting PSGI response headers from the arrayref.
1284 - Run PSGI apps from the command-line.
1287 # read your app from app.psgi file
1290 # choose .psgi file from ARGV[
0] (or with -a option)
1293 # switch server implementation with --server (or -s)
1294 plackup --server HTTP::Server::Simple --port
9090 --host
127.0.0.1 test.psgi
1296 # use UNIX socket to run FCGI daemon
1297 plackup -s FCGI --listen /tmp/fcgi.sock myapp.psgi
1299 # launch FCGI external server on port
9090
1300 plackup -s FCGI --port
9090
1317 my $client_id = $env-
>{'REMOTE_ADDR'};
1321 [ 'Content-Type' =
> 'text/plain' ],
1322 [ "Your IP address is ${client_id}." ],
1332 *use Plack::Builder;
1336 my $client_id = $env-
>{'REMOTE_ADDR'};
1340 [ 'Content-Type' =
> 'text/plain' ],
1341 [ "Your IP address is ${client_id}." ],
1347 * mount '/' =
> $app;
1352 - The `Runtime` middleware adds an `X-Runtime` header to the response with the number of seconds it
1353 took to process the request.
1361 - Can be found on the CPAN in the `Plack::Handler::` namespace.
1362 - [Apache1](https://metacpan.org/pod/Plack::Handler::Apache1), [Apache2](https://metacpan.org/pod/Plack::Handler::Apache2)
1363 - [CGI](https://metacpan.org/pod/Plack::Handler::CGI)
1364 - [FCGI](https://metacpan.org/pod/Plack::Handler::FCGI)
1365 - [HTTP::Server::PSGI](https://metacpan.org/pod/Plack::Handler::HTTP::Server::PSGI)
1366 - [SCGI](https://metacpan.org/pod/Plack::Handler::SCGI)
1367 - [Starman](https://metacpan.org/pod/Plack::Handler::Starman)
1368 - [Twiggy](https://metacpan.org/pod/Plack::Handler::Twiggy)
1369 - [AnyEvent::HTTPD](https://metacpan.org/pod/Plack::Handler::AnyEvent::HTTPD)
1370 - [Thrall](https://metacpan.org/pod/Plack::Handler::Thrall)
1382 name: middleware-debug
1384 ### [`Debug`](https://metacpan.org/pod/Plack::Middleware::Debug)
1392 ### [`ReverseProxy`](https://metacpan.org/pod/Plack::Middleware::ReverseProxy)
1395 enable 'ReverseProxy';
1398 - Fixes `REMOTE_ADDR`, `HTTP_HOST`, `SERVER_PORT`, and `psgi.url_scheme` in the environment.
1402 ### [`LogDispatch`](https://metacpan.org/pod/Plack::Middleware::LogDispatch)
1407 my $logger = Log::Dispatch-
>new(
1411 min_level =
> 'debug',
1417 enable 'LogDispatch', logger =
> $logger;
1422 ### [`XSRFBlock`](https://metacpan.org/pod/Plack::Middleware::XSRFBlock)
1425 enable 'XSRFBlock', cookie_options =
> { httponly =
> 1 };
1428 - Blocking cross-site request forgery couldn't be easier.
1432 ### [`RedirectSSL`](https://metacpan.org/pod/Plack::Middleware::RedirectSSL)
1435 enable 'RedirectSSL';
1438 - Redirects from http to https (or backwards, if configured).
1439 - Can also set HSTS header with configurable `max-age`.
1442 - HSTS = HTTP Strict Transport Security
1449 ![CPAN](img/cpan.png)
1452 ## Plack modules in July
2016
1454 **
10** `Plack-Handler-*` distributions
1456 **
55** `Plack-App-*` distributions
1458 **
253** `Plack-Middleware-*` distributions
1464 - PSGI also specifies a way to delay or stream responses to the server.
1467 - It's kind of complicated, but you can read the spec to learn more.
1468 - Read the source code of various apps and middlewares to see how it works in practice.
1471 - There are tons of great apps and middleware on the CPAN.
1474 - Consider writing some of your app as a middleware.
1477 - The concept and implementation of middleware is cool.
1478 - You should consider writing parts of your app as middleware so that functionality is available
1479 under different web frameworks.
1480 - Stuff that makes sense as middleware:
1489 class: center, middle
1494 ### Understand PSGI & Plack, and use them!
1498 class: center, middle
1506 class: center, middle
1512 Email me: Charles McGarvey
1513 <chazmcgarvey@brokenzipper.com
>
1516 Leave me feedback, if you want:
1518 ![Page on Joind.in](img/talkqr.svg)
1520 <https://joind.in/talk/
6e4d2
>
1528 - Thank you [Tatsuhiko Miyagawa](http://weblog.bulknews.net/) and other contributors for creating PSGI and Plack.
1532 </textarea><script src=
"https://gnab.github.io/remark/downloads/remark-latest.min.js"></script><script>var slideshow = remark.create({countIncrementalSlides: true, highlightLanguage: 'perl', highlightLines: true, ratio: '
16:
9', /*slideNumberFormat: '',*/ navigation: {scroll: false, touch: false, click: false}})
</script><script src=
"js/common.js"></script><script src=
"js/slides.js"></script></body></html>
1533 <!-- vim: set ts=4 sts=4 sw=4 tw=120 et ft=markdown nowrap: -->