Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote-tracking branch 'upstream/master'

  • Loading branch information...
commit ca4e85a827b23886bbd1f61f59218a1f1d042596 2 parents 2bc1fe3 + 11abc24
@zdk zdk authored
Showing with 1,583 additions and 328 deletions.
  1. +3 −1 .gitignore
  2. +0 −12 00_intro.md
  3. +0 −21 01_getting_plack.md
  4. +0 −53 02_hello_world.md
  5. +0 −39 03_using_plackup.md
  6. +0 −41 04_reloading_applications.md
  7. +0 −28 05_run_a_static_web_server_with_plack.md
  8. +0 −30 06_convert_cgi_apps_to_psgi.md
  9. +0 −24 07_use_web_application_framework_in_psgi.md
  10. +0 −17 Makefile
  11. +0 −25 bin/export_html.rb
  12. +11 −0 en/00_intro.md
  13. +21 −0 en/01_getting_plack.md
  14. +53 −0 en/02_hello_world.md
  15. +38 −0 en/03_using_plackup.md
  16. +41 −0 en/04_reloading_applications.md
  17. +28 −0 en/05_run_a_static_web_server_with_plack.md
  18. +30 −0 en/06_convert_cgi_apps_to_psgi.md
  19. +24 −0 en/07_use_web_application_framework_in_psgi.md
  20. +25 −25 { → en}/08_adapting_web_frameworks_to_psgi.md
  21. 0  { → en}/09_running_cgi_scripts_on_plack.md
  22. 0  { → en}/10_using_plack_middleware.md
  23. 0  { → en}/11_using_plack_builder.md
  24. +1 −3 { → en}/12_maps_multiple_apps_with_mount_and_urlmap.md
  25. +2 −3 { → en}/13_use_plack_test_to_test_your_application.md
  26. +1 −1  { → en}/14_use_plack_request.md
  27. 0  { → en}/15_authenticate_your_app_with_middleware.md
  28. +1 −2  { → en}/16_adding_jsonp_support_to_your_app.md
  29. 0  { → en}/17_serving_static_files_from_your_application.md
  30. 0  { → en}/18_load_middleware_conditionally.md
  31. 0  { → en}/19_cascade_multiple_applications.md
  32. 0  { → en}/20_access_your_local_app_from_the_internet.md
  33. +1 −1  { → en}/21_lint_your_application_and_middleware.md
  34. +1 −1  { → en}/22_discover_more_middleware.md
  35. 0  { → en}/23_write_your_own_middleware.md
  36. +1 −1  { → en}/24_wrap_up.md
  37. +13 −0 ja/00_intro.md
  38. +22 −0 ja/01_getting_plack.md
  39. +53 −0 ja/02_hello_world.md
  40. +38 −0 ja/03_using_plackup.md
  41. +41 −0 ja/04_reloading_applications.md
  42. +28 −0 ja/05_run_a_static_web_server_with_plack.md
  43. +30 −0 ja/06_convert_cgi_apps_to_psgi.md
  44. +24 −0 ja/07_use_web_application_framework_in_psgi.md
  45. +123 −0 ja/08_adapting_web_frameworks_to_psgi.md
  46. +26 −0 ja/09_running_cgi_scripts_on_plack.md
  47. +68 −0 ja/10_using_plack_middleware.md
  48. +43 −0 ja/11_using_plack_builder.md
  49. +86 −0 ja/12_maps_multiple_apps_with_mount_and_urlmap.md
  50. +88 −0 ja/13_use_plack_test_to_test_your_application.md
  51. +36 −0 ja/14_use_plack_request.md
  52. +77 −0 ja/15_authenticate_your_app_with_middleware.md
  53. +66 −0 ja/16_adding_jsonp_support_to_your_app.md
  54. +42 −0 ja/17_serving_static_files_from_your_application.md
  55. +49 −0 ja/18_load_middleware_conditionally.md
  56. +54 −0 ja/19_cascade_multiple_applications.md
  57. +39 −0 ja/20_access_your_local_app_from_the_internet.md
  58. +43 −0 ja/21_lint_your_application_and_middleware.md
  59. +77 −0 ja/22_discover_more_middleware.md
  60. +111 −0 ja/23_write_your_own_middleware.md
  61. +23 −0 ja/24_wrap_up.md
  62. +1 −0  ja/README.md
View
4 .gitignore
@@ -1,2 +1,4 @@
-book.*
+book*
+plack-handbook*
_site
+bin/export_html.rb
View
12 00_intro.md
@@ -1,12 +0,0 @@
-## Introduction
-
-This little handbook is based on the content of website [Plack Advent Calendar](http://advent.plackperl.org/). The calendar had 24 useful short posts explaining the concept of PSGI and tutorials how to adapt Plack to the existing web applications.
-
-The calendar was so successful and it's been considered a canonical reference for many beginners trying to learn Plack and also web framework authors trying to adapt PSGI.
-
-The content is written 3 years ago, and some are a little dated, but I tried to correct it to get up-to-date, and it will be updated as we find errata and get feedbacks from the readers community.
-
-Raw source code of the book, in Markdown format, is available on [github repository](https://github.com/miyagawa/plack-handbook) under the Creative Commons license. See LICENSE file for details.
-
-2012 September, Tatsuhiko Miyagawa
-
View
21 01_getting_plack.md
@@ -1,21 +0,0 @@
-## Day 1: Getting Plack
-
-The most important step to get started is to install [Plack](http://search.cpan.org/dist/Plack) and other utilities. Because PSGI and Plack are just like normal Perl module distributions, the installation is as easy: just launch your CPAN shell and type
-
-```
-cpan> install PSGI Plack
-```
-
-[PSGI](http://search.cpan.org/dist/PSGI) is a specification document for PSGI interface, so by installing the distribution you can read the documents on your shell with `perldoc PSGI` or `perldoc PSGI::FAQ` command. Plack gives you the standard server implementations, core middleware components and utilities like plackup or Plack::Test.
-
-Plack doesn't depend on any non-core XS modules, so with any Perl distribution later than 5.8.1 (which was released more than 6 years ago!) it can be installed very easily, even on platforms like Win32 or Mac OS X without developer tools (i.e. C compilers).
-
-If you're a developer of web applications or frameworks (I suppose you are!), you're highly recommended to install optional module bundle [Task::Plack](http://search.cpan.org/dist/Task-Plack) as well. The installation is equally easy as just typing:
-
-```
-cpan> install Task::Plack
-```
-
-It will prompt you a couple of questions depending on your environment. If you're unsure whether you should or should not install, just type return to pick the default. You'll get optional XS speedups by default, while other servers like non-blocking environments are disabled by default.
-
-Start reading docs with `perldoc Plack` to get prepared.
View
53 02_hello_world.md
@@ -1,53 +0,0 @@
-## Day 2: Hello World
-
-The first program you write with any of the programming language is the one that prints "Hello World". Let's follow the tradition for PSGI as well.
-
-**Note:** today's code is written in a raw PSGI interface to understand what's going on, but in reality you should never have to do this unless you're a web application framework developer. Otherwise you should use one of [existing frameworks that supports PSGI](http://plackperl.org/#frameworks).
-
-### Hello, World
-
-Here's the minimal code that prints "Hello World" to the client.
-
- my $app = sub {
- return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
- };
-
-PSGI application is a Perl subroutine reference (a coderef) and usually referenced as `$app` (but could be anything else obviously). It takes exactly one argument `$env` (which is not used in this code) and return an array ref containing status, headers and body. That's it.
-
-Save this code in a file named `hello.psgi` and then use plackup command to run it:
-
- > plackup hello.psgi
- HTTP::Server::PSGI: Accepting connections at http://0:5000/
-
-plackup runs your application with the default HTTP server HTTP::Server::PSGI on localhost port 5000. Open the URL http://127.0.0.1:5000/ and you see the "Hello World" page?
-
-### Give me something different
-
-Hello World is the simplest code you could imagine, so we could do something else here. Let's read and display the client information using the PSGI environment hash.
-
- my $app = sub {
- my $env = shift;
- return [
- 200,
- ['Content-Type' => 'text/plain'],
- [ "Hello stranger from $env->{REMOTE_ADDR}!"],
- ];
- };
-
-This code would display the remote address using the PSGI environment hash. Normally it should be 127.0.0.1 if you're running the server on your localhost. The PSGI environment hash contains lots of information about an HTTP connection, like incoming HTTP headers and request paths, much like the CGI environment variables.
-
-Want to display something not text by reading a file? Do this.
-
- my $app = sub {
- my $env = shift;
- if ($env->{PATH_INFO} eq '/favicon.ico') {
- open my $fh, "<:raw", "/path/to/favicon.ico" or die $!;
- return [ 200, ['Content-Type' => 'image/x-icon'], $fh ];
- } elsif ($env->{PATH_INFO} eq '/') {
- return [ 200, ['Content-Type' => 'text/plain'], [ "Hello again" ] ];
- } else {
- return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ];
- }
- };
-
-This app would serve favicon.ico if the request path looks like /favicon.ico, the "Hello World" page with requests to the root (/) and otherwise 404. You can see that a perl filehandle (`$fh`) is a valid PSGI response, and you can use whatever valid HTTP status code to return something different.
View
39 03_using_plackup.md
@@ -1,39 +0,0 @@
-## Day 3: Using plackup
-
-In [day 2](http://advent.plackperl.org/2009/12/day-2-hello-world.html) article I used the plackup command to run the Hello World PSGI application.
-
-Plackup is a command line launcher of PSGI applications, inspired by Rack's rackup command. It can be used to run any PSGI applications saved in .psgi file with one of PSGI web server backends using Plack handlers. The usage is simple, just give a .psgi file path to the command:
-
- > plackup hello.psgi
- HTTP::Server::PSGI: Accepting connections at http://0:5000/
-
-You can actually omit the filename as well if you're trying to run the file called `app.psgi` in the current directory.
-
-The default backend is chosen using one of the following methods.
-
-* If the environment variable `PLACK_SERVER` is set, it is used
-* If some environment specific variable like `GATEWAY_INTERFACE` or `FCGI_ROLE` is set, the backends for CGI or FCGI is used accordingly.
-* If loaded `.psgi` file uses specific event modules like AnyEvent, Coro or POE, the equivalent and most appropriate backend is chosen automatically.
-* Otherwise, fallback to the default "Standalone" backend, implemented as HTTP::Server::PSGI module.
-
-You can also specify the backend yourself from the command line using `-s` or `--server` switch, like:
-
- > plackup -s Starman hello.psgi
-
-plackup command would by default enable three middleware components: Lint, AccessLog and StackTrace to help aid the development, but you can disable them with the `-E` (or `--environment`) switch:
-
- > plackup -E production -s Starman hello.psgi
-
-In case you really want to use `development` Plack environment but want to disable the default middleware, there is `--
-no-default-middleware` option too.
-
-Other command line switches would also be passed to the server, so you can specify the Server listen port with:
-
- > plackup -s Starlet --host 127.0.0.1 --port 8080 hello.psgi
- Plack::Handler::Starlet: Accepting connections at http://127.0.0.1:8080/
-
-or specify the unix domain socket the FCGI backend would listen:
-
- > plackup -s FCGI --listen /tmp/fcgi.sock app.psgi
-
-For more options for plackup, run `perldoc plackup` from the command line. You'll see more plackup options and hacks tomorrow as well.
View
41 04_reloading_applications.md
@@ -1,41 +0,0 @@
-## Day 4: Reloading applications
-
-[Yesterday](http://advent.plackperl.org/2009/12/day-3-using-plackup.html) I introduced the basics of plackup and its command line options. Today I'll show you more!
-
-### Reload the application as necessary
-
-During the development you often change your perl code, saved in `.psgi` or `.pm` files. Because Plack servers launched by plackup command is a persistent process, your Perl code (PSGI application) is compiled and runs multiple times. So you need to restart your server whenever needed, and it's a little painful.
-
-So there's an option to watch changes for files under your working directory and reloads the application as needed: `-r` (or `--reload`).
-
- plackup -r hello.psgi
-
-It will watch files under the current directory by default, but you can change that to somewhere else by using `-R` (note the upper case) option:
-
- plackup -R lib,/path/to/scripts hello.psgi
-
-as you can see, multiple paths can be monitored by combining them with `,` (comma).
-
-By default it uses a dumb timer to scan the whole directory, but if you're on Linux and have Linux::Inotify2, or on Mac and have Mac::FSEvents installed, these filesystem notification is used, so it's more efficient.
-
-### -r vs Server auto-detection
-
-In Day 3 I told you that the plackup's server automatic detection is smart, so if your PSGI application uses one of the event modules AnyEvent or Coro, the correct backend would be chosen. Beware this automatic selection doesn't work if you use `-r` option, because plackup will now use the delayed loading technique to reload apps in the forked processes. You're recommended to explicitly set the server with `-s` option when combined with `-r` option.
-
-### Reloading sucks? Shotgun!
-
-Reloading a module or application on a persistent perl process could cause problems, like some module package variables are redefined or overwritten and then stuck in a bad state.
-
-Plack now has Shotgun loader, which is inspired by [Rack's shotgun](http://github.com/rtomayko/shotgun) and solves the reloading problem by loading the app on *every request* in a forked child environment.
-
-Using Shotgun loader is easy:
-
- > plackup -L Shotgun myapp.psgi
-
-This will delay load the compilation of your application until the runtime, and when a request comes, it forks off a new child process to compile your app and returns the PSGI response over the pipe. You can also preload the modules that are not likely to be updated in the parent process to reduce the time needed to compile your application.
-
-For instance, if your application uses Moose and DBIx::Class, then you can say:
-
- > plackup -MMoose -MDBIx::Class -L Shotgun myapp.psgi
-
-would speed up the time required to compile your application in the runtime.
View
28 05_run_a_static_web_server_with_plack.md
@@ -1,28 +0,0 @@
-## Day 5: Run a static web server with Plack
-
-Plack distribution comes with some readymade PSGI applications in Plack::App namespace. Some of them might be pretty handy, and one example for that would be [Plack::App::File](http://search.cpan.org/perldoc?Plack::App::File) and [Plack::App::Directory](http://search.cpan.org/perldoc?Plack::App::Directory).
-
-Plack::App::File is to translate the request path, like `/foo/bar.html` into the local file, like `/path/to/htdocs/foo/bar.html` and opens the file handle and passes it back as a PSGI response. So that's basically what a static web server like lighttpd, nginx or Apache does.
-
-Plack::App::Directory is a wrapper around Plack::App::File to give a directory index, just like [Apache's mod_autoindex](http://httpd.apache.org/docs/2.0/mod/mod_autoindex.html) does.
-
-Using those applications is pretty easy. Just write a .psgi file like this:
-
- use Plack::App::File;
- my $app = Plack::App::File->new(root => "$ENV{HOME}/public_html");
-
-and run it with the plackup:
-
- > plackup file.psgi
-
-now you can get any files under your `~/public_html` with the URL http://localhost:5000/somefile.html
-
-You can also use Plack::App::Directory but this time with just the plackup command line, without a .psgi file, like this:
-
- > plackup -MPlack::App::Directory \
- -e 'Plack::App::Directory->new(root => "$ENV{HOME}/Sites");
- HTTP::Server::PSGI: Accepting connections at http://0:5000/
-
-plackup command, like the perl command itself, accepts flags like `-I` (include path) `-M` (modules to load) and `-e` (the code to eval), so it's easy to load these Plack::App::* applications without even touching a .psgi file!
-
-There is a couple other Plack::App applications in the Plack distribution.
View
30 06_convert_cgi_apps_to_psgi.md
@@ -1,30 +0,0 @@
-## Day 6: Convert CGI apps to PSGI
-
-The most popular web server environments to run web applications, for Perl, has been CGI, FastCGI and mod_perl. CGI.pm is one of the Perl core module that happens to runs fine on any of those environments (with some tweaks). That means most web applications and frameworks somehow uses CGI.pm to deal with the environment differences because it's the easiest.
-
-[CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI) is a CGI module subclass that makes it easy to migrate existing CGI.pm based applications to PSGI. Imagine you have the following CGI application:
-
- use CGI;
-
- my $q = CGI->new;
- print $q->header('text/plain'),
- "Hello ", $q->param('name');
-
-This is a very simple CGI application, and converting this to PSGI is easy using the CGI::PSGI module:
-
- use CGI::PSGI;
-
- my $app = sub {
- my $env = shift;
- my $q = CGI::PSGI->new($env);
- return [
- $q->psgi_header('text/plain'),
- [ "Hello ", $q->param('name') ],
- ];
- };
-
-`CGI::PSGI->new($env)` takes the PSGI environment hash and creates an instance of CGI::PSGI, which is a subclass of CGI.pm. All methods including `param()`, `query_string` etc. do the right thing to get the values from PSGI environment rather than CGI's ENV values.
-
-`psgi_header` is an utility method to work just like CGI's `header` method, and returns the status code and an array reference containing the list of HTTP headers.
-
-Tomorrow, I'll talk about how to convert existing web frameworks that uses CGI.pm, using CGI::PSGI.
View
24 07_use_web_application_framework_in_psgi.md
@@ -1,24 +0,0 @@
-## Day 7: Use web application framework in PSGI
-
-Since we started this Plack and PSGI project in September 2009, there have been lots of feedbacks from the authors of most popular frameworks, like Catalyst, Jifty and CGI::Application.
-
-[CGI::Application](http://cgi-app.org/) is one of the most "traditional" CGI-based web application framework, and it's using CGI.pm exclusively to handle web server environments just like we [discussed yesterday](http://advent.plackperl.org/2009/12/day-6-convert-cgi-apps-to-psgi.html).
-
-Mark Stosberg, the current maintainer of CGI::Application and I have been collaborating on adding PSGI support to CGI::Application. We thought of multiple approaches, including adding a native PSGI support to CGI.pm, but we ended up implementing [CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI) as a CGI.pm wrapper and then [CGI::Application::PSGI](http://search.cpan.org/perldoc?CGI::Application::PSGI) to run existing CGI::Application *unmodified* in a PSGI compatible mode.
-
-All you have to do is to install CGI::Application::PSGI from CPAN and write a .psgi file that looks like this:
-
- use CGI::Application::PSGI;
- use WebApp;
-
- my $app = sub {
- my $env = shift;
- my $app = WebApp->new({ QUERY => CGI::PSGI->new($env) });
- CGI::Application::PSGI->run($app);
- };
-
-and use [plackup](http://advent.plackperl.org/2009/12/day-3-using-plackup.html) to run the application with a standalone server or any other backends.
-
-Similarly, most web frameworks that "supports" PSGI provides a plugin, engine or adapter to make the framework run on PSGI mode. For instance, [Catalyst](http://www.catalystframework.org/) has a Catalyst::Engine::* web server abstraction and [Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) is the engine to adapt Catalyst to run on PSGI. (**EDIT**: As of Catalyst 5.8 released in 2011, Catalyst supports PSGI by default and there's no need to install separate engine)
-
-The point is that with "PSGI support" from web frameworks, your application doesn't need to be modified, most of the times any single lines of code. And then by switching to PSGI you'll have lots of benefits like being able to use toolchain like plackup, Plack::Test and middleware which we'll discuss later in the future advent entries.
View
17 Makefile
@@ -1,17 +0,0 @@
-all: book.mobi book.epub book.zip
-
-book.html: *.md
- ./bin/export_html.rb *.md
-
-book.mobi: book.html
-# kindlegen book.html || true
- ebook-convert book.html book.mobi
-
-book.epub:
- ebook-convert book.html book.epub --no-default-epub-cover
-
-book.zip:
- zip book.zip book.epub book.mobi README.md
-
-clean:
- rm book.*
View
25 bin/export_html.rb
@@ -1,25 +0,0 @@
-#!/usr/bin/env ruby
-require 'redcarpet'
-
-HEADER = <<HEAD
-<html>
-<head>
-<title>Plack Handbook</title>
-<meta name="Author" content="Tatsuhiko Miyagawa">
-<meta name="DC.date.publication" content="2012-09">
-<meta name="DC.rights" content="(c) 2009-2012 Tatsuhiko Miyagawa">
-</head>
-<body>
-HEAD
-
-def munge(html)
- html.gsub /<h2>/, '<h2 class="chapter">'
-end
-
-markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
-File.open('book.html', 'w') do |io|
- io.write HEADER
- io.write munge(markdown.render(ARGF.readlines.join ''))
- io.write "</body></html>\n"
-end
-
View
11 en/00_intro.md
@@ -0,0 +1,11 @@
+## Introduction
+
+This little handbook is based on the content of the [Plack Advent Calendar](http://advent.plackperl.org/) website. The calendar had 24 useful short posts explaining the concept of PSGI and how to adapt existing web applications to Plack.
+
+The calendar was so successful it's been considered a canonical reference for many beginners trying to learn Plack and for web framework authors trying to adapt their code to work with PSGI.
+
+But the content was written 3 years ago and some of it is a little dated. In this book I tried to get it correct and up-to-date, and it will continue to be updated as we find errata and get feedback from the reader community.
+
+Raw source code of the book, in Markdown format, is available on [GitHub repository](https://github.com/miyagawa/plack-handbook) under the Creative Commons license. See the LICENSE file for details.
+
+2012 September, Tatsuhiko Miyagawa
View
21 en/01_getting_plack.md
@@ -0,0 +1,21 @@
+## Day 1: Getting Plack
+
+The most important step to get started is to install [Plack](http://search.cpan.org/dist/Plack) and other utilities. Because PSGI and Plack are just normal Perl module distributions the installation is easy: just launch your CPAN shell and type:
+
+```
+cpan> install PSGI Plack
+```
+
+[PSGI](http://search.cpan.org/dist/PSGI) is a specification document for the PSGI interface. By installing the distribution you can read the documents in your shell with the `perldoc PSGI` or `perldoc PSGI::FAQ` commands. Plack gives you the standard server implementations, core middleware components, and utilities like plackup and Plack::Test.
+
+Plack doesn't depend on any non-core XS modules so with any Perl distribution later than 5.8.1 (which was released more than 6 years ago!) it can be installed very easily, even on platforms like Win32 or Mac OS X without developer tools (i.e. C compilers).
+
+If you're a developer of web applications or frameworks (I suppose you are!), it's highly recommended you install the optional module bundle [Task::Plack](http://search.cpan.org/dist/Task-Plack) as well. The installation is as easy as typing:
+
+```
+cpan> install Task::Plack
+```
+
+You will be prompted with a couple of questions depending on your environment. If you're unsure whether you should or should not install, just type return to select the default. You'll get optional XS speedups by default, while other options like non-blocking environments are disabled by default.
+
+Start reading the documentation with `perldoc Plack` to get prepared.
View
53 en/02_hello_world.md
@@ -0,0 +1,53 @@
+## Day 2: Hello World
+
+The first program you write in any programming language is the one that prints "Hello World". Let's follow that tradition for PSGI as well.
+
+**Note:** Today's code is written to a raw PSGI interface to help you understand what's going on. In reality you should never have to do this unless you're a web application framework developer. Instead you should use one of the [existing frameworks that supports PSGI](http://plackperl.org/#frameworks).
+
+### Hello, World
+
+Here's the minimal code that prints "Hello World" to the client:
+
+ my $app = sub {
+ return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
+ };
+
+A PSGI application is a Perl subroutine reference (a coderef) and is usually referenced as `$app` (it could be named anything obviously). It takes exactly one argument `$env` (which is not used in this code) and returns an array ref containing status, headers, and body. That's it.
+
+Save this code in a file named `hello.psgi` and then use the plackup command to run it:
+
+ > plackup hello.psgi
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+plackup runs your application with the default HTTP server HTTP::Server::PSGI on localhost port 5000. Open the URL http://127.0.0.1:5000/ and you should see the "Hello World" page.
+
+### Give me something different
+
+Hello World is the simplest code imaginable. We can do more here. Let's read and display the client information using the PSGI environment hash.
+
+ my $app = sub {
+ my $env = shift;
+ return [
+ 200,
+ ['Content-Type' => 'text/plain'],
+ [ "Hello stranger from $env->{REMOTE_ADDR}!"],
+ ];
+ };
+
+This code will display the remote address using the PSGI environment hash. It will normally be 127.0.0.1 if you're running the server on your localhost. The PSGI environment hash contains lots of information about an HTTP connection like incoming HTTP headers and request paths, much like the CGI environment variables.
+
+Want to display something that isn't just text? We can do this by reading a file:
+
+ my $app = sub {
+ my $env = shift;
+ if ($env->{PATH_INFO} eq '/favicon.ico') {
+ open my $fh, "<:raw", "/path/to/favicon.ico" or die $!;
+ return [ 200, ['Content-Type' => 'image/x-icon'], $fh ];
+ } elsif ($env->{PATH_INFO} eq '/') {
+ return [ 200, ['Content-Type' => 'text/plain'], [ "Hello again" ] ];
+ } else {
+ return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ];
+ }
+ };
+
+This app would serve favicon.ico if the request path looks like /favicon.ico, the "Hello World" page for requests to the root (/) and otherwise a 404. You can see that a Perl filehandle (`$fh`) is a valid PSGI response, and you can use any valid HTTP status code for a response.
View
38 en/03_using_plackup.md
@@ -0,0 +1,38 @@
+## Day 3: Using plackup
+
+In the [Day 2](http://advent.plackperl.org/2009/12/day-2-hello-world.html) article I used the plackup command to run the Hello World PSGI application.
+
+plackup is a command line launcher of PSGI applications inspired by Rack's rackup command. It can be used to run any PSGI application saved in a .psgi file with one of the PSGI web server backends using Plack handlers. The usage is simple: just pass a .psgi file path to the command:
+
+ > plackup hello.psgi
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+You can actually omit the filename if you're trying to run the file named `app.psgi` in the current directory.
+
+The default backend is chosen using one of the following methods:
+
+* If the environment variable `PLACK_SERVER` is set it is used.
+* If some environment specific variable like `GATEWAY_INTERFACE` or `FCGI_ROLE` is set the backend for CGI or FCGI is used accordingly.
+* If the loaded `.psgi` file uses a specific event module like AnyEvent, Coro or POE the equivalent and most appropriate backend is chosen automatically.
+* Otherwise, fallback to the default "Standalone" backend implemented in the HTTP::Server::PSGI module.
+
+You can also specify the backend yourself from the command line using the `-s` or `--server` switch:
+
+ > plackup -s Starman hello.psgi
+
+By default the plackup command enables three middleware components to aid development: Lint, AccessLog, and StackTrace. You can disable them with the `-E` (or `--environment`) switch:
+
+ > plackup -E production -s Starman hello.psgi
+
+In the case that you really want to use the `development` Plack environment but want to disable the default middleware there is the `--no-default-middleware` option.
+
+Other command line switches can be passed to the server. You can specify the server listen port with:
+
+ > plackup -s Starlet --host 127.0.0.1 --port 8080 hello.psgi
+ Plack::Handler::Starlet: Accepting connections at http://127.0.0.1:8080/
+
+or specify the unix domain socket the FCGI backend should listen on with:
+
+ > plackup -s FCGI --listen /tmp/fcgi.sock app.psgi
+
+For more options for plackup, run `perldoc plackup` from the command line. You'll see more plackup options and hacks tomorrow as well.
View
41 en/04_reloading_applications.md
@@ -0,0 +1,41 @@
+## Day 4: Reloading applications
+
+[Yesterday](http://advent.plackperl.org/2009/12/day-3-using-plackup.html) I introduced the basics of plackup and its command line options. Today I'll show you more!
+
+### Reload the application as necessary
+
+During development you often change your Perl code, saved in `.psgi` or `.pm` files. Because the Plack server launched by the plackup command is a persistent process you need to restart your server whenever your code changes. This is a little painful.
+
+So there's an option to watch for changes to files under your working directory and reload the application as needed: `-r` (or `--reload`).
+
+ plackup -r hello.psgi
+
+It will watch files under the current directory by default, but you can change it to watch additional locations by using the `-R` option (note the uppercase).
+
+ plackup -R lib,/path/to/scripts hello.psgi
+
+As you can see, multiple paths can be monitored by combining them with `,` (comma).
+
+By default plackup uses a dumb timer to scan the whole directory, but if you're on Linux and have Linux::Inotify2 installed or on Mac OS and have Mac::FSEvents installed filesystem notification is used so it's more efficient.
+
+### -r vs Server auto-detection
+
+In Day 3 I told you that plackup's automatic server detection is smart enough to tell if PSGI application uses an event modules such as AnyEvent or Coro and choose the correct backend. Be aware that this automatic selection doesn't work if you use the `-r` option because plackup uses a delayed loading technique to reload apps in forked processes. It's recommended that you explicitly set the server with the `-s` option when using the `-r` option.
+
+### Reloading sucks? Shotgun!
+
+Reloading a module or application in a persistent Perl process can cause problems. For instance, module package variables could be redefined or overwritten and then get stuck in a bad state.
+
+Plack now has the Shotgun loader, inspired by [Rack's shotgun](http://github.com/rtomayko/shotgun), which solves the reloading problem by loading the app on *every request* in a forked child environment.
+
+Using the Shotgun loader is easy:
+
+ > plackup -L Shotgun myapp.psgi
+
+This will delay the compilation of your application to runtime. When a request is received it will fork off a new child process to compile your app and return the PSGI response over the pipe. You can also preload modules in the parent process that are not likely to be updated to reduce the time needed to compile your application.
+
+For instance, if your application uses Moose and DBIx::Class then use the following options:
+
+ > plackup -MMoose -MDBIx::Class -L Shotgun myapp.psgi
+
+This speeds up the time required to compile your application in the runtime.
View
28 en/05_run_a_static_web_server_with_plack.md
@@ -0,0 +1,28 @@
+## Day 5: Run a static web server with Plack
+
+The Plack distribution comes with some ready made PSGI applications in the Plack::App namespace. Some of them are pretty handy, for instance [Plack::App::File](http://search.cpan.org/perldoc?Plack::App::File) and [Plack::App::Directory](http://search.cpan.org/perldoc?Plack::App::Directory).
+
+Plack::App::File translates a request path like `/foo/bar.html` into a local file like `/path/to/htdocs/foo/bar.html`, opens the file handle, and passes it back as a PSGI response. It basically does what a static web server like lighttpd, nginx or Apache does.
+
+Plack::App::Directory is a wrapper around Plack::App::File that gives a directory index, just like [Apache's mod_autoindex](http://httpd.apache.org/docs/2.0/mod/mod_autoindex.html) does.
+
+Using these applications is easy. Just write a .psgi file like this:
+
+ use Plack::App::File;
+ my $app = Plack::App::File->new(root => "$ENV{HOME}/public_html");
+
+and run it with plackup:
+
+ > plackup file.psgi
+
+Now you can access any file under your `~/public_html` with the URL http://localhost:5000/somefile.html
+
+You can also use Plack::App::Directory. This time let's run it with just the plackup command without a .psgi file:
+
+ > plackup -MPlack::App::Directory \
+ -e 'Plack::App::Directory->new(root => "$ENV{HOME}/Sites");
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+The plackup command, like the perl command, accepts flags like `-I` (include path), `-M` (modules to load), and `-e` (the code to eval), so it's easy to load these Plack::App::* applications without ever touching a .psgi file!
+
+There are a couple of other Plack::App applications in the Plack distribution.
View
30 en/06_convert_cgi_apps_to_psgi.md
@@ -0,0 +1,30 @@
+## Day 6: Convert CGI apps to PSGI
+
+The most popular web server environments to run web applications for Perl have been CGI, FastCGI, and mod_perl. CGI.pm is one of the Perl core modules that happens to run fine in any of these environments (with some tweaks). This means many web applications and frameworks use CGI.pm to deal with environment differences because it's the easiest.
+
+[CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI) is a CGI module subclass that makes it easy to migrate existing CGI.pm based applications to PSGI. Imagine you have the following CGI application:
+
+ use CGI;
+
+ my $q = CGI->new;
+ print $q->header('text/plain'),
+ "Hello ", $q->param('name');
+
+This is a very simple CGI application and converting this to PSGI is easy using the CGI::PSGI module:
+
+ use CGI::PSGI;
+
+ my $app = sub {
+ my $env = shift;
+ my $q = CGI::PSGI->new($env);
+ return [
+ $q->psgi_header('text/plain'),
+ [ "Hello ", $q->param('name') ],
+ ];
+ };
+
+`CGI::PSGI->new($env)` takes the PSGI environment hash and creates an instance of CGI::PSGI, which is a subclass of CGI.pm. All methods including `param()`, `query_string`, etc. do the right thing to get the values from the PSGI environment rather than CGI's ENV values.
+
+`psgi_header` is a utility method that works just like CGI's `header` method and returns the status code and an array reference containing the list of HTTP headers.
+
+Tomorrow I'll talk about how to convert existing web frameworks that use CGI.pm to PSGI using CGI::PSGI.
View
24 en/07_use_web_application_framework_in_psgi.md
@@ -0,0 +1,24 @@
+## Day 7: Use web application framework in PSGI
+
+Since we started the Plack and PSGI project in September 2009 there has been a lot of feedback from the authors of popular frameworks such as Catalyst, Jifty, and CGI::Application.
+
+[CGI::Application](http://cgi-app.org/) is one of the most "traditional" CGI-based web application framework and it uses CGI.pm exclusively to handle web server environments just like we [discussed yesterday](http://advent.plackperl.org/2009/12/day-6-convert-cgi-apps-to-psgi.html).
+
+Mark Stosberg, the current maintainer of CGI::Application, and I have been collaborating on adding PSGI support to CGI::Application. We thought of multiple approaches including adding native PSGI support to CGI.pm, but we ended up implementing [CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI) as a CGI.pm wrapper and then using [CGI::Application::PSGI](http://search.cpan.org/perldoc?CGI::Application::PSGI) to run existing CGI::Application code *unmodified* in a PSGI compatible mode.
+
+All you have to do is install CGI::Application::PSGI from CPAN and write a .psgi file that looks like this:
+
+ use CGI::Application::PSGI;
+ use WebApp;
+
+ my $app = sub {
+ my $env = shift;
+ my $app = WebApp->new({ QUERY => CGI::PSGI->new($env) });
+ CGI::Application::PSGI->run($app);
+ };
+
+Then use [plackup](http://advent.plackperl.org/2009/12/day-3-using-plackup.html) to run the application with a standalone server or any of the other backends.
+
+Similarly, most web frameworks that support PSGI provide a plugin, engine, or adapter to make the framework run in PSGI mode. For instance, [Catalyst](http://www.catalystframework.org/) has a Catalyst::Engine::* web server abstraction and [Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) is the engine to adapt Catalyst to run on PSGI. (**EDIT**: As of Catalyst 5.8 released in 2011, Catalyst supports PSGI by default and there's no need to install a separate engine.)
+
+The point is that with support from web frameworks you often won't need to modify a single line of code in your application to use PSGI. And by switching to PSGI there are lots of benefits like being able to use the toolchain of plackup, Plack::Test, and middleware which we'll discuss in future advent entries.
View
50 08_adapting_web_frameworks_to_psgi.md → en/08_adapting_web_frameworks_to_psgi.md
@@ -1,14 +1,14 @@
## Day 8: Adapting web frameworks to PSGI
-The biggest benefit of PSGI in terms of web application framework developers is that, once you adapt your framework to run on PSGI, you forget and throw away everything else that you needed to deal with, say, handle the differences between bunch of FastCGI servers or CGI.
+The biggest benefit of PSGI for web application framework developers is that once you adapt your framework to run on PSGI you can forget and throw away everything else that you needed to deal with to, say, handle the differences between a bunch of FastCGI servers.
-Similarly, if you have a large scale web application, open source or proprietary, you probably have your own web application framework (or a base class or whatever).
+Similarly, if you have a large scale web application, open source or proprietary, you probably have your own web application framework (or a base class or the like).
-Today's entry discusses how to convert existing web application framework to adapt to the PSGI interface.
+Today's entry discusses how to convert existing web application frameworks to the PSGI interface.
### CGI.pm based framework
-In Day 7 we saw how to run CGI::Application based application in PSGI, using CGI::Application::PSGI. CGI::Application, as the name suggests, uses CGI.pm, so using CGI::PSGI instead and define a new runner class is the easiest to go.
+In Day 7 we saw how to run a CGI::Application based application in PSGI using CGI::Application::PSGI. CGI::Application, as the name suggests, uses CGI.pm, so using CGI::PSGI instead and defining a new runner class is the easiest way to go.
package CGI::Application::PSGI;
use strict;
@@ -25,7 +25,7 @@ In Day 7 we saw how to run CGI::Application based application in PSGI, using CGI
local $ENV{CGI_APP_RETURN_ONLY} = 1;
$app->run;
};
-
+
my $q = $app->query;
my $type = $app->header_type;
@@ -33,26 +33,26 @@ In Day 7 we saw how to run CGI::Application based application in PSGI, using CGI
return [ @headers, [ $body ] ];
}
-This is quite simple, isn't it? CGI::Application's `run()` method usually returns the whole output, including HTTP headers and content body. As you can see, the module does some gross hack to disable the header generation since you can use `psgi_header` method of CGI::PSGI to generate the status code and HTTP headers as an array ref.
+That's quite simple, isn't it? CGI::Application's `run()` method usually returns the whole output, including HTTP headers and content body. As you can see, the module has a gross hack to disable the header generation since you can use the `psgi_header` method of CGI::PSGI to generate the status code and HTTP headers as an array ref.
-I've implemented PSGI adapters for [Mason](http://search.cpan.org/perldoc?HTML::Mason) and [Maypole](http://search.cpan.org/perldoc?Maypole) and the code was pretty much look alike.
+I've implemented PSGI adapters for [Mason](http://search.cpan.org/perldoc?HTML::Mason) and [Maypole](http://search.cpan.org/perldoc?Maypole) and the code pretty much all looked alike:
-* Create CGI::PSGI out of `$env` and set that instead of the default CGI.pm instance
-* Disable HTTP header generation if needed
-* Runs the app main dispatcher
-* Extracts the HTTP headers to be sent, use `psgi_header` to generate the status and headers
-* Extracts the response body (content)
+* Create CGI::PSGI out of `$env` and set that instead of the default CGI.pm instance.
+* Disable HTTP header generation if needed.
+* Run the app main dispatcher.
+* Extract the HTTP headers to be sent, use `psgi_header` to generate the status and headers.
+* Extract the response body (content).
### Adapter based framework
-If the framework in question already uses adapter based approaches to abstract server environments, it'd be much easier to adapt to PSGI, by reusing most of the CGI adapter code. Here's the code to adapt [Squatting](http://search.cpan.org/perldoc?Squatting) to PSGI. Squatting uses Squatting::On::* namespace to adapt to environments like mod_perl, FastCGI or even other frameworks like Catalyst or HTTP::Engine. It was extremely easy to write [Squatting::On::PSGI](http://search.cpan.org/perldoc?Squatting::On::PSGI):
+If the framework in question already uses adapter based approaches to abstract server environments it should be much easier to adapt to PSGI by reusing most of the CGI adapter code. Here's the code to adapt [Squatting](http://search.cpan.org/perldoc?Squatting) to PSGI. Squatting uses the Squatting::On::* namespace to adapt to environments like mod_perl, FastCGI, or even other frameworks like Catalyst or HTTP::Engine. It was extremely easy to write [Squatting::On::PSGI](http://search.cpan.org/perldoc?Squatting::On::PSGI):
package Squatting::On::PSGI;
use strict;
use CGI::Cookie;
use Plack::Request;
use Squatting::H;
-
+
my %p;
$p{init_cc} = sub {
my ($c, $env) = @_;
@@ -65,22 +65,22 @@ If the framework in question already uses adapter based approaches to abstract s
$cc->status = 200;
$cc;
};
-
+
# \%input = i($env) # Extract CGI parameters from an env object
$p{i} = sub {
my $r = Plack::Request->new($_[0]);
my $p = $r->params;
+{%$p};
};
-
+
# \%cookies = $p{c}->($cookie_header) # Parse Cookie header(s).
$p{c} = sub {
+{ map { ref($_) ? $_->value : $_ } CGI::Cookie->parse($_[0]) };
};
-
+
sub psgi {
my ($app, $env) = @_;
-
+
$env->{PATH_INFO} ||= "/";
$env->{REQUEST_PATH} ||= do {
my $script_name = $env->{SCRIPT_NAME};
@@ -92,32 +92,32 @@ If the framework in question already uses adapter based approaches to abstract s
? "$env->{REQUEST_PATH}?$env->{QUERY_STRING}"
: $env->{REQUEST_PATH};
};
-
+
my $res;
eval {
no strict 'refs';
my ($c, $args) = &{ $app . "::D" }($env->{REQUEST_PATH});
my $cc = $p{init_cc}->($c, $env);
my $content = $app->service($cc, @$args);
-
+
$res = [
$cc->status,
[ %{ $cc->{headers} } ],
[ $content ],
];
};
-
+
if ($@) {
$res = [ 500, [ 'Content-Type' => 'text/plain' ], [ "<pre>$@</pre>" ] ];
}
-
+
return $res;
}
-This is very straightforward, especially when compared with [Squatting::On::CGI](http://cpansearch.perl.org/src/BEPPU/Squatting-0.70/lib/Squatting/On/CGI.pm). It's almost line-by-line copy and some adjustment to use Plack::Request to parse parameters instead of CGI.pm.
+That's very straightforward, especially when compared with [Squatting::On::CGI](http://cpansearch.perl.org/src/BEPPU/Squatting-0.70/lib/Squatting/On/CGI.pm). It's almost a line-by-line copy (with some adjustment) using Plack::Request to parse parameters instead of CGI.pm.
-Similarly Catalyst uses Catalyst::Engine abstraction and [Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) is the adapter to run Catlayst on PSGI, which most of the code is copied from CGI.
+Similarly, Catalyst uses the Catalyst::Engine abstraction and [Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) is the adapter to run Catalyst on PSGI, where most of the code is copied from CGI.
### mod_perl centric frameworks
-Some frameworks are centered around mod_perl's API, in which case we can't take the approaches like we've seen here. Instead, you should probably start by mocking Apache::Request APIs using a fake/mock object. Patric Donelan, a WebGUI developer explains his approach to make mod_perl-like API in [his blog post](http://blog.patspam.com/2009/plack-roundup-at-sf-pm) that you might be interested in, and the [mock request class linked](http://github.com/pdonelan/webgui/blob/plebgui/lib/WebGUI/Session/Plack.pm) would be a good start.
+Some frameworks are centered around mod_perl's API, in which case we can't use the approaches we've seen here. Instead, you should probably start by mocking Apache::Request APIs using a fake/mock object. Patric Donelan, a WebGUI developer, explains his approach to make a mod_perl-like API in [his blog post](http://blog.patspam.com/2009/plack-roundup-at-sf-pm). The [mock request class linked](http://github.com/pdonelan/webgui/blob/plebgui/lib/WebGUI/Session/Plack.pm) is a good place to start.
View
0  09_running_cgi_scripts_on_plack.md → en/09_running_cgi_scripts_on_plack.md
File renamed without changes
View
0  10_using_plack_middleware.md → en/10_using_plack_middleware.md
File renamed without changes
View
0  11_using_plack_builder.md → en/11_using_plack_builder.md
File renamed without changes
View
4 ...ps_multiple_apps_with_mount_and_urlmap.md → ...ps_multiple_apps_with_mount_and_urlmap.md
@@ -62,9 +62,7 @@ Of course you can use this URLMap and mount API to run multiple framework applic
# Catalyst
use Foo;
- Foo->setup_engine('PSGI');
-
- my $app1 = sub { Foo->new->run(@_) };
+ my $app1 = Foo->psgi_app;
# CGI::Application
use Bar;
View
5 ...se_plack_test_to_test_your_application.md → ...se_plack_test_to_test_your_application.md
@@ -4,7 +4,7 @@
There are many ways to test web applications, either with a live server or using a mock request technique. Some web application frameworks allow you to write an unit test using one of those methods, but the way you write tests differ per framework of your choice.
-Plack::Test gives you *an unified interface* to test *any* web applications and frameworks that is compatible to PSGI using *both* mock request and live HTTP server.
+Plack::Test gives you *a unified interface* to test *any* web applications and frameworks that is compatible to PSGI using *both* mock request and live HTTP server.
### Using Plack::Test
@@ -78,8 +78,7 @@ Once again, the beauty of PSGI and Plack is that everything written to run for t
use Plack::Test;
use MyCatalystApp;
- MyCatalystApp->setup_engine('PSGI');
- my $app = sub { MyCatalystApp->run(@_) };
+ my $app = MyCatalystApp->psgi_app;
test_psgi $app, sub {
my $cb = shift;
View
2  14_use_plack_request.md → en/14_use_plack_request.md
@@ -23,7 +23,7 @@ Plack::Request is a wrapper around PSGI environment, and the code goes like this
The only thing you need to change, if you're migrating from HTTP::Engine, is the first line of the application to create a Plack::Request out of PSGI env (`shift`) and then call `finalize` to get an array reference out of Response object.
-All other methods like `path_info`, `uri`, `param`, `redirect` etc. work like HTTP::Engine::Request and Response object which is very similar to [Catalyst](http://search.cpan.org/dist/Catalyst-Runtime) 's Request and Response object.
+Many other methods like `path_info`, `uri`, `param`, `redirect` etc. work like HTTP::Engine::Request and Response object which is very similar to [Catalyst](http://search.cpan.org/dist/Catalyst-Runtime) 's Request and Response object.
### Plack::Request and Plack
View
0  15_authenticate_your_app_with_middleware.md → ..._authenticate_your_app_with_middleware.md
File renamed without changes
View
3  16_adding_jsonp_support_to_your_app.md → en/16_adding_jsonp_support_to_your_app.md
@@ -55,8 +55,7 @@ And of course, this JSONP middleware should work with any existing web framework
And then using Catalyst::Engine::PSGI and Plack::Builder, you can add a JSONP support to this controller.
use MyApp;
- MyApp->setup_engine('PSGI');
- my $app = sub { MyApp->run(@_) };
+ my $app = MyApp->psgi_app;
use Plack::Builder;
builder {
View
0  ...ing_static_files_from_your_application.md → ...ing_static_files_from_your_application.md
File renamed without changes
View
0  18_load_middleware_conditionally.md → en/18_load_middleware_conditionally.md
File renamed without changes
View
0  19_cascade_multiple_applications.md → en/19_cascade_multiple_applications.md
File renamed without changes
View
0  ...ccess_your_local_app_from_the_internet.md → ...ccess_your_local_app_from_the_internet.md
File renamed without changes
View
2  21_lint_your_application_and_middleware.md → ...1_lint_your_application_and_middleware.md
@@ -38,4 +38,4 @@ When you develop a new framework adapter or a middleware component, be sure to c
Middleware::Lint validates both request and response interface, so this can be used when you develop a new PSGI web server as well. However if you are a server developer there's a more comprehensive testing tool to make sure your server behaves correctly, and that is Plack::Test::Suite.
-You can look at the existing tests in the `t/Plack-Server` directory for how to use this utility, but it defines lots of expected requests and responses pairs to test a new PSGI server backend. Existing Plack::Handler backends included in Plack core distribution as well as other CPAN distributions all pass this test suite.
+You can look at the existing tests in the `t/Plack-Handler` directory for how to use this utility, but it defines lots of expected requests and responses pairs to test a new PSGI server backend. Existing Plack::Handler backends included in Plack core distribution as well as other CPAN distributions all pass this test suite.
View
2  22_discover_more_middleware.md → en/22_discover_more_middleware.md
@@ -26,7 +26,7 @@ Actually this is (again) a steal from [Rack](http://rack.rubyforge.org/). Rack d
By default Session will save the session in on-memory hash, which wouldn't work with the prefork (or multi process) servers. It's shipped with a couple of default store engines such as [CHI](http://search.cpan.org/perldoc?CHI), so it's so easy to adapt to other storage engines, exactly like we see with other middleware components such as Auth.
-Session object has standard methods like `get` and `set` and can be accessed with `plack.session` key in the PSGI env hash. Application and frameworks with access to PSGI env hash can use this Session freely in the app, like in Tatsumaki:
+Session data is stored as a plain hash reference in `psgix.session` key in the PSGI env hash. Application and frameworks with access to PSGI env hash can use this Session freely in the app by wrapping it with Plack::Session module, like in Tatsumaki:
# Tatsumaki app
sub get {
View
0  23_write_your_own_middleware.md → en/23_write_your_own_middleware.md
File renamed without changes
View
2  24_wrap_up.md → en/24_wrap_up.md
@@ -20,7 +20,7 @@ Most of the Plack gangs use [github](http://github.com/) for the source control
Again, Plack is a fairly young project. It's just been 3 months since we gave this project a birth. There are many things that could get more improvements, so if you come across one of them, don't stop there. Let us know what you think is a problem, give us an insight how it could be improved, or if you're impatient, fork the project on github and send us patches.
-We're chatting on IRC channel #plack on irc.perl.org and there's a [mailing list](http://groups.google.com/group/psgi-plack) and [an issue tracker on github](http://github.com/miyagawa/Plack/issues) to communicate with us.
+We're chatting on IRC channel #plack on irc.perl.org and there's a [mailing list](http://groups.google.com/group/psgi-plack) and [an issue tracker on github](http://github.com/plack/Plack/issues) to communicate with us.
### On a final note...
View
13 ja/00_intro.md
@@ -0,0 +1,13 @@
+## イントロダクション
+
+この本は[Plack Advent Calendar](http://advent.plackperl.org/)の内容をベースにしています。このカレンダーでは24個の短いポストでPSGIのコンセプトやPlackをプロジェクトに導入するTipsを紹介しました。
+
+カレンダーの内容は人気となり、しばらくの間、Plackを導入しようとするビギナーやPSGIに対応したいフレームワーク作者のためのリファレンスとして参照されてきました。
+
+本書の中身は3年前に書かれたもので、少し古くなっているものもありますが、内容については最新に追随するよう書き換えました。また読者からのフィードバックによってさらに最新に更新していく予定です。
+
+本のソースコードはMarkdownフォーマットで[github レポジトリ](https://github.com/miyagawa/plack-handbook)ダウンロードでき、Creative Commonsでライセンスされます。詳細はLICENSEファイルを参照してください。
+
+2012年9月 宮川達彦
+
+
View
22 ja/01_getting_plack.md
@@ -0,0 +1,22 @@
+## Day 1: Plackを入手
+
+まずはじめに、[Plack](http://search.cpan.org/dist/Plack)とその他ユーティリティをインストールしましょう。PSGIやPlackは通常のPerlモジュールとして配布されているので、インストールはCPANシェルをたちあげて以下のようにタイプするだけです。
+
+```
+cpan> install PSGI Plack
+```
+
+[PSGI](http://search.cpan.org/dist/PSGI) はPSGIインタフェースの仕様を記述したドキュメントをモジュール化したものです。インストールすることによってシェルから`perldoc PSGI``perldoc PSGI::FAQ`としてドキュメントを参照することができます。Plackは標準のサーバ実装、コアのミドルウェアやplackup, Plack::Testといったユーティリティが付属します。
+
+PlackはコアではないXSモジュールに依存していないため、Perl 5.8.1 以上のバージョンであれば特に問題なくリリースできるはずですし、CコンパイラのないWin32やDeveloper ToolsのないMac OS X環境でも利用が可能です (*とはいえ、makeなどのツールがないとCPANからのインストールが実行できないかもしれません)。
+
+Webアプリケーションやフレームワークのデベロッパーであれば、オプションのバンドル [Task::Plack](http://search.cpan.org/dist/Task-Plack)もインストールすることをおすすめします。こちらも、以下のコマンドでインストールが可能です。
+
+```
+cpan> install Task::Plack
+```
+
+CPANシェルを対話モードで起動している場合、いくつかの質問を聞かれるかもしれません。不明な場合はデフォルトを選択して問題ありません。オプションのXSモジュールについてはデフォルトでインストールされますが、非同期用のサーバなどは標準ではインストールされません。
+
+`perldoc Plack` としてドキュメントの概観を読むことができます。
+
View
53 ja/02_hello_world.md
@@ -0,0 +1,53 @@
+## Day 2: Hello World
+
+プログラミング言語の学習で最初に書くプログラムは "Hello World" を表示することです。PSGIでもそうしてみましょう。
+
+**注意:** 今日のコードは理解のためにPSGIの生インタフェースを利用して書かれていますが、あなたがWebアプリケーションフレームワークの作者でない限り、実際にはこうしたコードを書く必要はありません。[PSGIをサポートしているフレームワーク](http://plackperl.org/#frameworks)を参照してください。
+
+### Hello, World
+
+"Hello World" を表示するための最小限のコードは以下のようになります。
+
+ my $app = sub {
+ return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
+ };
+
+PSGIアプリケーションはPerlのサブルーチンリファレンス(コードリファレンス)を利用して記述し、ここでは`$app`という変数名に格納しています(が、名前はなんでも構いません)。このサブルーチンは1つの引数`$env`を受け取り(今回のコードでは省略されています)、ステータス、ヘッダとボディを格納した配列リファレンスを返します。
+
+このコードを`hello.psgi`というファイルに保存し、plackupコマンドで起動しましょう:
+
+ > plackup hello.psgi
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+plackup はアプリケーションをデフォルトのHTTPサーバ HTTP::Server::PSGI を利用して localhost の5000番ポートで起動します。http://127.0.0.1:5000/ をブラウザで開くと、Hello Worldが表示されましたか?
+
+### 違うものを表示
+
+Hello Worldはとてもシンプルなものですが、もう少し違ったことをやってみましょう。クライアント情報をPSGI環境変数から取得し、表示します。
+
+ my $app = sub {
+ my $env = shift;
+ return [
+ 200,
+ ['Content-Type' => 'text/plain'],
+ [ "Hello stranger from $env->{REMOTE_ADDR}!"],
+ ];
+ };
+
+このコードはクライアントのリモートアドレスをPSGI環境変数ハッシュから表示します。ローカルホストで起動している場合、値は127.0.0.1 になるはずです。PSGI環境変数にはHTTPの接続やクライアントに関する情報、たとえばHTTPヘッダやリクエストパスなどが格納されていて、CGIの環境変数によく似ています。
+
+テキスト以外のデータをファイルから表示するには、以下のようにします。
+
+ my $app = sub {
+ my $env = shift;
+ if ($env->{PATH_INFO} eq '/favicon.ico') {
+ open my $fh, "<:raw", "/path/to/favicon.ico" or die $!;
+ return [ 200, ['Content-Type' => 'image/x-icon'], $fh ];
+ } elsif ($env->{PATH_INFO} eq '/') {
+ return [ 200, ['Content-Type' => 'text/plain'], [ "Hello again" ] ];
+ } else {
+ return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ];
+ }
+ };
+
+このアプリケーションはリクエストパスが`/favicon.ico`となっている場合に`favicon.ico`を表示し、ルート(/)については"Hello World"、その他のパスには404を返します。Perlの標準ファイルハンドルである`$fh`はPSGIのボディにそのまま設定することができますし、ステータスコードについても妥当な数字をいれることができます。
View
38 ja/03_using_plackup.md
@@ -0,0 +1,38 @@
+## Day 3: plackupを使う
+
+Day 2の記事ではplackupコマンドを利用してHello World PSGIアプリケーションを起動しました。
+
+plackup はPSGIアプリケーションを起動するためのコマンドラインランチャーで、Rackのrackupにインスパイアされました。.psgiファイルに保存されたPSGIアプリケーションであれば、Plackハンドラーに対応したWebサーババックエンドの上で動かすことができます。使い方はシンプルで、.psgiファイルのパスをコマンドに渡すだけです。
+
+ > plackup hello.psgi
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+カレントディレクトリの`app.psgi`という名前のファイルを起動する場合、ファイル名も省略可能です。
+
+デフォルトで起動するバックエンドは以下の方法で選ばれます。
+
+* 環境変数`PLACK_SERVER`が定義されている場合、その値
+* 環境特有の環境変数、たとえば `GATEWAY_INTERFACE``FCGI_ROLE` などが定義されている場合、CGIやFCGIバックエンドが自動で選ばれます
+* ロードされた`.psgi`ファイルがAnyEvent, CoroやPOEなどのモジュールをロードしている場合、それに対応したバックエンドが自動で選ばれます
+* その他の場合、"Standalone" バックエンドが選択され、HTTP::Server::PSGIモジュールによって起動します
+
+コマンドラインスイッチ`-s``--server`でバックエンドを指定することもできます。
+
+ > plackup -s Starman hello.psgi
+
+plackupコマンドはデフォルトで3つのミドルウェアを有効にします。Lint, AccessLog と StackTrace で、開発の際にログやスタックトレースを表示してくれて便利ですが、これを無効にするには、`-E`または`--environment`スイッチで`development`以外の値をセットします:
+
+ > plackup -E production -s Starman hello.psgi
+
+Plack environment に`development`を利用したいが、デフォルトのミドルウェアは無効にしたい場合、`--no-default-middleware` オプションも用意されています。
+
+その他のコマンドラインオプションをサーババックエンドに渡すこともでき、サーバのリッスンするポートは以下のように設定できます:
+
+ > plackup -s Starlet --host 127.0.0.1 --port 8080 hello.psgi
+ Plack::Handler::Starlet: Accepting connections at http://127.0.0.1:8080/
+
+FCGIバックエンドでUNIXドメインソケットを指定するには:
+
+ > plackup -s FCGI --listen /tmp/fcgi.sock app.psgi
+
+その他のオプションについては、コマンドラインから`perldoc plackup`を実行して参照してください。明日もplackupについて解説をつづけます。
View
41 ja/04_reloading_applications.md
@@ -0,0 +1,41 @@
+## Day 4: アプリケーションのリロード
+
+昨日はplackupの基本とコマンドラインオプションについて解説しました。今日もつづけましょう!
+
+### 必要に応じてアプリケーションをリロードする
+
+開発中のコードは`.psgi``.pm`に書かれたPerlのコードを編集します。plackupによって起動されたサーバは永続プロセスのため、最初に一度だけコンパイルされたPSGIコードが何度も実行されます。コードの変更を反映するにはサーバプロセスを再起動する必要があり、面倒です。
+
+作業ディレクトリ以下のファイルを監視し、変更があったらアプリケーションをリロードするオプションが用意されています。`-r`または`--reload`です。
+
+ plackup -r hello.psgi
+
+デフォルトではカレントディレクトリ以下のファイルをモニターしますが、他のパスを指定するには`-R`(大文字)で指定します。
+
+ plackup -R lib,/path/to/scripts hello.psgi
+
+複数のパスを指定するにはカンマ(,)で区切ります。
+
+デフォルトではタイマーを利用してディレクトリの中身をスキャンしますが、LinuxではLinux::Inotify2, Mac OS Xでは Mac::FSEventsがインストールされている場合、ファイルシステムのイベント通知を利用するため、より効率的です。
+
+### -r とサーバ自動選択
+
+Day 3でplackupのサーバ自動選択について紹介しました。アプリケーションがAnyEvent, CoroやPOEを利用している場合、それに対応したサーバが自動で選択される機能です。この機能は`-r``-R`オプションが有効の場合、正常に機能しません。アプリケーションのロードが起動時には行われなくなるためです。リロード機能を使う場合、`-s`で明示的にバックエンドサーバを指定してください。
+
+### リロードがうまく動かない場合: Shotgun
+
+永続環境のperlプロセスでモジュールやアプリケーションを読み直す場合、問題がおこることがあります。モジュールのパッケージ変数を更新したり、初期化する場合です。
+
+PlackにあるShotgunローダーは、Rackの[shotgun](http://github.com/rtomayko/shotgun)にインスパイアされたハンドラで、リクエストごとに子プロセスをforkして、そこでアプリケーションを読み直します。
+
+Shotgunローダーの利用は簡単です。
+
+ > plackup -L Shotgun myapp.psgi
+
+アプリケーションのコンパイルがランタイムまで遅延され、新しいリクエストが来た際、新しい子プロセスをforkし、PSGIのレスポンスをパイプ上で返します。開発中には変更することのないモジュールはプリロードしておき、レスポンスのボトルネックにならないようにすることも可能です。
+
+たとえば、アプリケーションがMooseとDBIx::Classを使っているなら、
+
+ > plackup -MMoose -MDBIx::Class -L Shotgun myapp.psgi
+
+とすればリクエストごとに読み直すコードが減少するため、スピードアップが期待できます。
View
28 ja/05_run_a_static_web_server_with_plack.md
@@ -0,0 +1,28 @@
+## Day 5: Plackで静的サーバを起動する
+
+Plackディストリビューションにはすぐに使えるPSGIアプリケーションがPlack::Appネームスペースの下に用意されています。いくつかはとても便利で、一例がここで紹介するPlack::App::FileとPlack::App::Directoryです。
+
+Plack::App::Fileは`/foo/bar.html`といったリクエストパスを、`/path/to/htdocs/foo/bar.html`といったローカルのファイルにマップし、ファイルを開いてファイルハンドルをPSGIのレスポンスとして返します。lighttpd, nginx やApacheといった既成のWebサーバと同様です。
+
+Plack::App::DirectoryはPlack::App::Fileのラッパーで、Apacheのmod_autoindexのようなディレクトリインデックスを表示します。
+
+これらのアプリケーションの利用はとても簡単です。以下のような`.psgi`ファイルを記述します。
+
+ use Plack::App::File;
+ my $app = Plack::App::File->new(root => "$ENV{HOME}/public_html");
+
+これをplackupで起動します。
+
+ > plackup file.psgi
+
+これで`~/public_html`以下のファイルはURL http://localhost:5000/somefile.html でアクセスできるようになります。
+
+Plack::App::Directory についても同様ですが、plackupのコマンドラインから直接起動する例を紹介します。
+
+ > plackup -MPlack::App::Directory \
+ -e 'Plack::App::Directory->new(root => "$ENV{HOME}/Sites");
+ HTTP::Server::PSGI: Accepting connections at http://0:5000/
+
+plackupコマンドは、perlコマンド同様、`-I`(インクルードパス), `-M`(ロードするモジュール)や`-e`(実行するコード)を指定できるため、ワンライナーでPSGIアプリを書くことができます。
+
+他にもPlack::Appにはいくつかアプリケーションが用意されていますが、それはまた別の日に。
View
30 ja/06_convert_cgi_apps_to_psgi.md
@@ -0,0 +1,30 @@
+## Day 6: CGIアプリケーションをPSGIに変換
+
+Perlでウェブアプリケーションを書く方法として長い間もっとも人気があったのがCGI, FastCGIとmod_perlでした。CGI.pmはPerlに付属するコアモジュールで、この3つの環境で同時に動くコードを記述することが(少しの変更で)できます。これによって、多くのWebアプリケーションやフレームワークはCGI.pmを使って環境の差異を吸収してきました。
+
+[CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI) を使うと、既存のCGI.pmベースのアプリケーションをPSGIに簡単に変換できます。以下のようなCGIアプリケーションがあるとします:
+
+ use CGI;
+
+ my $q = CGI->new;
+ print $q->header('text/plain'),
+ "Hello ", $q->param('name');
+
+とてもシンプルなCGIスクリプトですが、これをPSGIに変換するには以下のようにします:
+
+ use CGI::PSGI;
+
+ my $app = sub {
+ my $env = shift;
+ my $q = CGI::PSGI->new($env);
+ return [
+ $q->psgi_header('text/plain'),
+ [ "Hello ", $q->param('name') ],
+ ];
+ };
+
+`CGI::PSGI->new($env)` はPSGIの環境変数ハッシュを受け取り、CGI.pmのサブクラスであるCGI::PSGIのインスタンスをつくります。`param`, `query_string`といったメソッドは今までどおり動作しますが、CGIの環境変数ではなく、PSGI環境変数から値を取得します。
+
+`psgi_header` はCGIの`header`メソッドのように動作するユーティリティで、ステータスコードとHTTPヘッダの配列リファレンスをリストで返します。
+
+明日は既存のCGI.pmを利用したフレームワークをPSGIに変換します。
View
24 ja/07_use_web_application_framework_in_psgi.md
@@ -0,0 +1,24 @@
+## Day 7: WebアプリケーションフレームワークをPSGIで利用する
+
+PlackとPSGIプロジェクトを2009年9月にはじめて以来、Catalyst, Jifty やCGI::Applicationといった人気のあるフレームワークのデベロッパーから多くのフィードバックをもらいました。
+
+[CGI::Application](http://cgi-app.org/) はもっとも「伝統的」なCGIベースのWebアプリケーションフレームワークで、昨日も紹介したようにCGI.pmを利用して様々な環境の差異を吸収しています。
+
+CGI::Applicationの現在のメンテナであるMark Stosbergと、CGI::ApplicationにおけるPSGIサポートについて検討してきました。いくつかのアプローチを検討し、その中にはPSGIサポートを直接CGI::Applicationに記述するものも含まれましたが、昨日も紹介したCGI::PSGIをラッパーとして開発し、[CGI::Application::PSGI](http://search.cpan.org/perldoc?CGI::Application::PSGI)を既存のCGI::Applicationを変更することなくPSGI互換モードで起動させるように実装しました。
+
+CGI::Application::PSGIをCPANからインストールして、`.psgi`ファイルを以下のように記述します。
+
+ use CGI::Application::PSGI;
+ use WebApp;
+
+ my $app = sub {
+ my $env = shift;
+ my $app = WebApp->new({ QUERY => CGI::PSGI->new($env) });
+ CGI::Application::PSGI->run($app);
+ };
+
+そして[plackup](http://advent.plackperl.org/2009/12/day-3-using-plackup.html)を使ってスタンドアロンや各種バックエンドのサーバ上で起動することができます。
+
+同様に、多くのWebフレームワークではPSGIサポートをするためのプラグイン、エンジンやアダプターを提供し、PSGIモードで起動するための機能が用意されています。たとえば[Catalyst](http://www.catalystframework.org/)ではCatalyst::EngineというレイヤーでWebサーバエンジンの抽象化をおこなっていて、[Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) でCatalystをPSGI上で起動することができます。(**注**: 2011年にCatalyst 5.8 がリリースされ、PSGIサポートはCatalyst本体に組み込まれており、エンジンを別途インストールする必要はありません)
+
+重要なのは、"PSGIサポート"しているフレームワークを利用する場合、利用者のアプリケーションをPSGI用に書き換える必要はないということです。多くの場合、1行のコードの変更も必要ありません。かつ、PSGIを利用することでplackup, Plack::Testやミドルウェアなど多くのエコシステムを利用することができます。これらについては、のちほど紹介していきます。
View
123 ja/08_adapting_web_frameworks_to_psgi.md
@@ -0,0 +1,123 @@
+## Day 8: WebフレームワークをPSGIに対応させる
+
+Webアプリケーションフレームワーク作者にとって、PSGIの最大のメリットは、一度PSGIに対応すれば、FastCGI、CGIといったWebサーバ固有の環境の差異といった問題に対応する必要がなくなるということです。
+
+オープンソースあるいはプロプライエタリの大規模なWebアプリケーションを開発している場合、自家製のフレームワークを作っているという場合も多いでしょう。
+
+今日のエントリではこうしたフレームワークをどのようにPSGIインタフェースに対応させるかを紹介します。
+
+### CGI.pm ベースのフレームワーク
+
+Day 7ではCGI::ApplicationベースのアプリケーションをCGI::Application::PSGI経由で、PSGIで起動させる方法を紹介しました。CGI::Applicationはその名前からわかるようにCGI.pmを利用していますので、ここをCGI::PSGIにすり替えてしまうのがもっとも手っ取り早い方法です。
+
+ package CGI::Application::PSGI;
+ use strict;
+ use CGI::PSGI;
+
+ sub run {
+ my($class, $app) = @_;
+
+ # HACK: deprecate HTTP header generation
+ # -- CGI::Application should support some flag to turn this off cleanly
+ my $body = do {
+ no warnings 'redefine';
+ local *CGI::Application::_send_headers = sub { '' };
+ local $ENV{CGI_APP_RETURN_ONLY} = 1;
+ $app->run;
+ };
+
+ my $q = $app->query;
+ my $type = $app->header_type;
+
+ my @headers = $q->psgi_header($app->header_props);
+ return [ @headers, [ $body ] ];
+ }
+
+メインとなる実装はたったこれだけです。CGI::Applicationの`run`メソッドは通常、HTTPヘッダとボディを含む全体の出力を文字列で返します。ご覧のとおり、このモジュールはちょっと行儀の悪いハックでHTTPヘッダ生成をオーバーライドして、CGI::PSGIモジュールの`psgi_header`メソッドを使ってPSGIのレスポンスを返しています。
+
+[Mason](http://search.cpan.org/perldoc?HTML::Mason) や [Maypole](http://search.cpan.org/perldoc?Maypole) 用のPSGIアダプターも実装してみましたが、おおむねコードは同様です。
+
+* `$env`からCGI::PSGIインスタンスを作り、それをCGI.pmインスタンスの代わりにセットする
+* 必要ならHTTPヘッダ出力を抑制
+* アプリのメインディスパッチャーを実行
+* 送信するHTTPヘッダを抽出、`psgi_header` を使ってステータスとヘッダを生成
+* レスポンスボディを抽出
+
+### アダプターベースのフレームワーク
+
+フレームワークがすでにアダプターベースのアプローチでWebサーバ環境の差異を吸収している場合、PSGIサポートを追加するのはさらに簡単になります。CGI用のコードを少し変更するだけですみます。以下のコードは[Squatting](http://search.cpan.org/perldoc?Squatting) をPSGI対応させるためのコードです。SquattingはSquatting::On::* ネームスペースでmod_perl, FastCGIやその他のフレームワーク(Catalyst, HTTP::Engine)などへのアダプターを記述します。[Squatting::On::PSGI](http://search.cpan.org/perldoc?Squatting::On::PSGI) でPSGI対応のコードを書くのはとても簡単でした。
+
+ package Squatting::On::PSGI;
+ use strict;
+ use CGI::Cookie;
+ use Plack::Request;
+ use Squatting::H;
+
+ my %p;
+ $p{init_cc} = sub {
+ my ($c, $env) = @_;
+ my $cc = $c->clone;
+ $cc->env = $env;
+ $cc->cookies = $p{c}->($env->{HTTP_COOKIE} || '');
+ $cc->input = $p{i}->($env);
+ $cc->headers = { 'Content-Type' => 'text/html' };
+ $cc->v = { };
+ $cc->status = 200;
+ $cc;
+ };
+
+ # \%input = i($env) # Extract CGI parameters from an env object
+ $p{i} = sub {
+ my $r = Plack::Request->new($_[0]);
+ my $p = $r->params;
+ +{%$p};
+ };
+
+ # \%cookies = $p{c}->($cookie_header) # Parse Cookie header(s).
+ $p{c} = sub {
+ +{ map { ref($_) ? $_->value : $_ } CGI::Cookie->parse($_[0]) };
+ };
+
+ sub psgi {
+ my ($app, $env) = @_;
+
+ $env->{PATH_INFO} ||= "/";
+ $env->{REQUEST_PATH} ||= do {
+ my $script_name = $env->{SCRIPT_NAME};
+ $script_name =~ s{/$}{};
+ $script_name . $env->{PATH_INFO};
+ };
+ $env->{REQUEST_URI} ||= do {
+ ($env->{QUERY_STRING})
+ ? "$env->{REQUEST_PATH}?$env->{QUERY_STRING}"
+ : $env->{REQUEST_PATH};
+ };
+
+ my $res;
+ eval {
+ no strict 'refs';
+ my ($c, $args) = &{ $app . "::D" }($env->{REQUEST_PATH});
+ my $cc = $p{init_cc}->($c, $env);
+ my $content = $app->service($cc, @$args);
+
+ $res = [
+ $cc->status,
+ [ %{ $cc->{headers} } ],
+ [ $content ],
+ ];
+ };
+
+ if ($@) {
+ $res = [ 500, [ 'Content-Type' => 'text/plain' ], [ "<pre>$@</pre>" ] ];
+ }
+
+ return $res;
+ }
+
+多少のコード量がありますが、ほとんどは [Squatting::On::CGI](http://cpansearch.perl.org/src/BEPPU/Squatting-0.70/lib/Squatting/On/CGI.pm) と共通で、CGI.pmを利用している箇所をPlack::Requestに置き換えただけの単純なコードです。
+
+昨日紹介した[Catalyst::Engine::PSGI](http://search.cpan.org/perldoc?Catalyst::Engine::PSGI) もほとんどがCGI用と共通です。
+
+### mod_perl 中心のフレームワーク
+
+いくつかのフレームワークは mod_perl のAPIを多用して実装されていることがあり、こうした場合はCGI.pmを置き換えるといったアプローチは利用できません。Apache::RequestのAPIをfake/mock objectなどでモックする必要があるでしょう。WebGUIデベロッパーであるPatric Donelanが mod_perl ライクなAPIからPSGIへポートした際の事例を[ブログ記事](http://blog.patspam.com/2009/plack-roundup-at-sf-pm)で紹介しています。実際にリンクされている[モッククラス](http://github.com/pdonelan/webgui/blob/plebgui/lib/WebGUI/Session/Plack.pm) を見てみるのもよいでしょう。
View
26 ja/09_running_cgi_scripts_on_plack.md
@@ -0,0 +1,26 @@
+## Day 9: CGIスクリプトをPlackで走らせる
+
+既存のCGIベースのアプリケーションをPSGIに変換する方法を幾つか紹介してきました。今日のエントリでは、すべてのCGIスクリプトを、多くの場合なにも変更せずに、PSGIアプリケーションとして実行する究極の方法を紹介します。
+
+[CGI::PSGI](http://search.cpan.org/perldoc?CGI::PSGI)はCGI.pmのサブクラスとして実装されていて、CGI.pmからのマイグレーションは、多くの場合数行の変更だけで可能ですが、これは元のコードがある程度エントリポイントが整理されているなどの前提が必要です。レガシーなCGIスクリプトで、いろんな箇所で環境変数を直接参照したり、STDOUTに出力がされていて変更が難しい場合はどうでしょうか。
+
+[CGI::Emulate::PSGI](http://search.cpan.org/perldoc?CGI::Emulate::PSGI) はCGIベースのPerlプログラムをPSGI環境で実行するモジュールです。CGI::Emulate::PSGIでは環境変数やSTDIN/STODOUTをCGI向けにエミュレートしてから実行するため、上で書いたようなレガシーなCGIスクリプトでSTDOUTにいろいろな箇所で出力をしていても問題ありません。
+
+ use CGI::Emulate::PSGI;
+ CGI::Emulate::PSGI->handler(sub {
+ do "/path/to/foo.cgi";
+ CGI::initialize_globals() if &CGI::initialize_globals;
+ });
+
+このコードで既存のCGIスクリプトをPSGIとして実行できます。CGI.pm を使っている場合、CGI.pmは多くのグローバル変数にキャッシュをつくるため、`initialize_globals`をリクエストごとに手動で実行する必要があります。
+
+San FranciscoからLondon Perl Workshopに向かうフライトの途中で、これよりもさらにスマートな方法を思いついてハックしていました。`do`でスクリプトを都度実行するのではなく、CGIスクリプトをサブルーチンにコンパイルしてしまうものです。このモジュールは[CGI::Compile](http://search.cpan.org/perldoc?CGI::Comple) として公開されていて、CGI::Emulate::PSGIと組み合わせて使うと最適です。
+
+ my $sub = CGI::Compile->compile("/path/to/script.cgi");
+ my $app = CGI::Emulate::PSGI->handler($sub);
+
+[Plack::App::CGIBin](http://search.cpan.org/perldoc?Plack::App::CGIBin) がPlackに付属していて、このアプリケーションは`/pat/to/cgi-bin`といったディレクトリにあるCGIスクリプトをそのままPSGIアプリケーションとして起動することができます。
+
+ > plackup -MPlack::App::CGIBin -e 'Plack::App::CGIBin->new(root => "/path/to/cgi-bin"))'
+
+こうして`/path/to/cgi-bin`にあるCGIスクリプトをマウントします。cgi-binディレクトリにある`foo.pl`は http://localhost:5000/foo.pl でアクセスできます。最初の実行時にコンパイルされるため、mod_perlのApache::Registryと似たような感じで動作します。
View
68 ja/10_using_plack_middleware.md
@@ -0,0 +1,68 @@
+## Day 10: Plackミドルウェアの利用
+
+### ミドルウェア
+
+ミドルウェアはPSGIにおけるコンセプト(いつものように、PythonのWSGIやRubyのRackからのパクリです)で、サーバとアプリケーション両側の動作をするコンポーネントです。
+
+![WSGI middleware onion](images/pylons_as_onion.png)
+
+(画像は Pylons project)
+
+この画像はミドルウェアのコンセプトをうまく解説しています。玉ねぎの真ん中にPSGIアプリケーションがあり、それをミドルウェアがラップし、リクエストが来るごとに(外側から内側に)前処理をおこない、レスポンスが出力されたら(内側から外側に)後処理を行います。
+
+HTTP認証、エラーの補足、JSONPなど数多くの機能をミドルウェアとして実装することによって、PSGIアプリケーションやフレームワークに動的に機能追加していくことが可能になります。
+
+### Plack::Middleware
+
+[Plack::Middleware](http://search.cpan.org/perldoc?Plack::Middleware) はミドルウェアを記述するためのベースクラスで、シンプルにかつ再利用可能な形でミドルウェアを書くことができます。
+
+Plack::Middlewareで書かれたミドルウェアの利用は簡単で、元のアプリケーションを`wrap`メソッドでラップするだけです。
+
+ my $app = sub { [ 200, ... ] };
+
+ use Plack::Middleware::StackTrace;
+ $app = Plack::Middleware::StackTrace->wrap($app);
+
+この例は元のアプリケーションをStackTraceミドルウェア(実際にはplackupのデフォルトで有効)の`wrap`メソッドでラップします。ラップされたアプリケーションが例外を投げた場合、ミドルウェアがエラーを捕捉して、Devel::StackTrace::AsHTMLを利用して美しいHTMLページを表示します。
+
+ミドルウェアの中にはパラメータをとるものもあります。その場合、`$app`の後ろにハッシュでパラメータを渡すことができます。:
+
+ my $app = sub { ... };
+
+ use Plack::Middleware::MethodOverride;
+ $app = Plack::Middleware::MethodOverride->wrap($app, header => 'X-Method');
+
+多くのミドルウェアをラップするのは、とくにそのミドルウェアを実装したモジュールを先にuseする必要もあるため、退屈になりがちです。この対策として、DSL風の記述法が用意されています。
+
+ use Plack::Builder;
+ my $app = sub { ... };
+
+ builder {
+ enable "StackTrace";
+ enable "MethodOverride", header => 'X-Method';
+ enable "Deflater";
+ $app;
+ };
+
+Plack::Builderの利用方法については明日解説します。
+
+### Middleware and Frameworks
+
+ミドルウェアの美しい点は、どんなPSGIアプリケーションにも適用できるところです。このコード例からは当たり前かもしれませんが、実際にはラップされたアプリケーションはどんなものでも構いません。既存のWebアプリケーションをPSGIモードで起動し、それにPlackミドルウェアを追加することだってできます。例えば、CGI::Applicationで、
+
+ use CGI::Application::PSGI;
+ use WebApp;
+
+ my $app = sub {
+ my $env = shift;
+ my $app = WebApp->new({ QUERY => CGI::PSGI->new($env) });
+ CGI::Application::PSGI->run($app);
+ };
+
+ use Plack::Builder;
+ builder {
+ enable "Auth::Basic", authenticator => sub { $_[1] eq 'foobar' };
+ $app;
+ };
+
+このようにすると、CGI::ApplicationベースのアプリケーションにBasic認証をつけることができます。[PSGIをサポートしているフレームワーク](http://plackperl.org/#frameworks)であればなんでもこのようなことが可能です。
View
43 ja/11_using_plack_builder.md
@@ -0,0 +1,43 @@
+## Day 11: Plack::Builderを使う
+
+昨日のエントリではPlackミドルウェアを.psgiで利用する方法を紹介しました。ミドルウェアを`use`して、そのあと`$app``wrap`メソッドでラップしていくのは退屈ですし、直感的ではありません。そこで、それをより簡単にするDSL (Domain Specific Language) 風シンタックスを用意しています。それが、Plack::Builderです。
+
+Plack::Builderのりようはとても簡単です。`builder``enable`キーワードを使います。
+
+ my $app = sub {
+ return [ 200, [], [ "Hello World" ] ];
+ };
+
+ use Plack::Builder;
+ builder {
+ enable "JSONP";
+ enable "Auth::Basic", authenticator => sub { ... };
+ enable "Deflater";
+ $app;
+ };
+
+このコードは元のアプリケーション`$app`に対して、Deflater, Auth::Basic と JSONP ミドルウェアを内側から外側に向けてラップしていきます。つまり、以下のコードと同様です。
+
+ $app = Plack::Middleware::Deflater->wrap($app);
+ $app = Plack::Middleware::Auth::Basic->wrap($app, authenticator => sub { });
+ $app = Plack::Middleware::JSONP->wrap($app);
+
+ただし、各モジュールを先に`use`する必要がないので、よりDRYになっています。
+
+### 外側から内側へ、上から下へ
+
+ラップされるミドルウェアの順番が逆であることにきづいたでしょうか?builder/enableのDSLでは、ラップされる`$app`に近い行が、*内側*で、最初の行が*外側*にくるようにラップされます。昨日紹介した玉ねぎの図と比較するとよりわかりやすくなります。アプリケーションに近い行ほど、レイヤーの内側になるということです。
+
+`enable`を使うばあいPlack::Middleware::をミドルウェアの名前から省略できます。Plack::Middleware以外の名前空間を使う場合、たとえば MyFramework::PSGI::MW::Foo であれば、
+
+ enable "+MyFramework::PSGI::MW::Foo";
+
+とすることができます。重要なのはプラス(+)でモジュール名がFully Qualified であることを指定できます。
+
+### 裏でおこっていること
+
+もしPlack::Builderの実装に興味があれば、コードを見て何をしているか追ってみてください。`builder`はコードブロックを受け取り、それを実行した結果のコードリファレンスを元のアプリケーション(`$app`)として受け取り、そしてenableされたミドルウェアを逆順にラップしていきます。つまり、`builder`ブロックの最後に`$app`またはPSGIアプリケーションを配置することが重要で、また`builder`ブロックは.psgiファイルの最後になければなりません。
+
+### Thanks, Rack
+
+Plack::BuilderはRubyのRack::Builderにインスパイアされています。Rack::Builderでは`use`キーワードを使っていますが、Perlではこれは使えないため、`enable`で代用しています:) Rackには`map`キーワードでアプリケーションをパスにマップする機能がありますが、Plackでこれをどうするかは明日解説します。
View
86 ja/12_maps_multiple_apps_with_mount_and_urlmap.md
@@ -0,0 +1,86 @@
+## Day 12: 複数のアプリケーションをmountとURLMapでマウントする
+
+### Hello World! but anyone else?
+
+本書では、シンプルなアプリケーションの例として "Hello World" を使っていました。
+
+ my $app = sub {
+ return [ 200, [], [ "Hello World" ] ];
+ };
+
+より複雑な例として、Webアプリケーションフレームワークを使って書かれた複数のアプリケーションを、1つのサーバ内でmod_aliasなどでマップしているような例を考えてみましょう。
+
+### Plack::App::URLMap
+
+Plack::App::URLMap は複数のPSGIアプリケーションを*合成*して1つのPSGIアプリケーションのように振る舞います。リクエストパスやヴァーチャルホストのようにホスト名ベースでアプリケーションをディスパッチすることができます。
+
+ my $app1 = sub {
+ return [ 200, [], [ "Hello John" ] ];
+ };
+
+ my $app2 = sub {
+ return [ 200, [], [ "Hello Bob" ] ];
+ };
+
+このように2つのアプリがあり、1つはJohnもう1つはBobにHelloを返します。この2つのPSGIアプリを1つのサーバで動作させたい場合、どうすればよいでしょう。Plack::App::URLMapを利用すると以下のように出来ます。
+
+ use Plack::App::URLMap;
+ my $app = Plack::App::URLMap->new;
+ $app->mount("/john" => $app1);
+ $app->mount("/bob" => $app2);
+
+たったこれだけです。リクエストパスに応じて、`/john`には`$app1`つまり"Hello John", `/bob`には`$app2`つまり"Hello Bob"へディスパッチします。またマップされいていないパス、たとえばルートの "/" などは404が返ります。
+
+`PATH_INFO``SCRIPT_NAME`といったPSGI環境変数は自動的に調整され、Apacheのmod_aliasやCGIスクリプトを起動したときのように、そのまま動きます。アプリケーションやフレームワークは、`PATH_INFO`を使ってリクエストを処理し、`SCRIPT_NAME`をベースパスとしてURLを生成する必要があります。
+
+### mount DSL
+
+Plack::App::URLMapの`mount`はとても便利なので、Plack::BuilderのDSLにも追加してあります。Rack::Builderでは`map`を使っていますが、これもPerlでは使えないので、`mount`として使います。
+
+ use Plack::Builder;
+ builder {
+ mount "/john" => $app1;
+ mount "/bob" => builder {
+ enable "Auth::Basic", authenticator => ...;
+ $app2;
+ };
+ };
+
+'/john' へのリクエストはURLMapのときと同様、`$app1`にディスパッチされます。この例では"/bob"に対して`builder`をネストさせ、"Hello Bob"を表示するアプリケーションにBasic認証を追加しています。この例は以下のコードと同様です。
+
+ $app = Plack::App::URLMap->new;
+ $app->mount("/john", $app1);
+
+ $app2 = Plack::Middleware::Auth::Basic->wrap($app2, authenticator => ...);
+ $app->mount("/bob", $app2);
+
+が、DSLを利用した方がより短いコードで、簡潔になっています。
+
+### マルチテナントフレームワーク
+
+もちろん、このURLMapやmount APIをつかって複数のフレームワークのアプリケーションを1つのサーバにマウントすることができます。3つのアプリケーションがあって、"Foo"がCatalyst, "Bar"がCGI::Application, "Baz"がSquattingで書かれているとしましょう。
+
+ # Catalyst
+ use Foo;
+ my $app1 = Foo->psgi_app;
+
+ # CGI::Application
+ use Bar;
+ use CGI::Application::PSGI;
+ my $app2 = sub {
+ my $app = Bar->new({ QUERY => CGI::PSGI->new(shift) });
+ CGI::Application::PSGI->run($app);
+ };
+
+ # Squatting
+ use Baz 'On::PSGI';
+ Baz->init;
+ my $app3 = sub { Baz->psgi(shift) };
+
+ builder {
+ mount "/foo" => $app1;
+ mount "/bar" => $app2;
+ mount "/baz" => $app3;
+ };
+
+こうすると、別々のフレームワークで書かれた3つのアプリケーションが、plackupなどを利用して同一サーバ上で異なるパスにマップされて起動します。
View
88 ja/13_use_plack_test_to_test_your_application.md
@@ -0,0 +1,88 @@
+## Day 13: Plack::Test でアプリケーションをテストする
+
+### Testing
+
+Webアプリケーションのテストにはいろいろな方法があり、ライブのサーバを使ったり、モックリクエストを使う方法などがあります。こうしたテスト手法を提供しているフレームワークもありますが、どのようにテストを記述するかはフレームワークごとに異なっていることが多いです。
+
+Plack::TestはどんなPSGI対応のWebアプリケーションフレームワークでも、共通のインターフェースを使って、それぞれモックとライブのサーバを使ったテスト手法を導入できます。
+
+### Plack::Testを利用
+
+Plack::Testのりようはとても簡単で、Perlのテストプロトコル標準である[TAP](http://testanything.org/wiki/) や[Test::More](http://search.cpan.org/perloc?Test::More)と互換性があります。
+
+ use Plack::Test;
+ use Test::More;
+ use HTTP::Request;
+
+ my $app = sub {
+ return [ 200, [ 'Content-Type', 'text/plain' ], [ "Hello" ] ];
+ };
+
+ test_psgi $app, sub {
+ my $cb = shift;
+
+ my $req = HTTP::Request->new(GET => 'http://localhost/');
+ my $res = $cb->($req);
+
+ is $res->code, 200;
+ is $res->content, "Hello";
+ };
+
+ done_testing;
+
+PSGIアプリを作成またはロード([Plack::Util](http://search.cpan.org/perldoc?Plack::Util)の `load_psgi` 関数をつかって`.psgi`ファイルからアプリケーションをロードできます)し、`test_psgi`関数でアプリケーションをテストします。2個目の引数はコールバックで、テスト用クライアントコードを記述します。
+
+名前付き引数をつかって、以下のようにも書けます:
+
+ test_psgi app => $app, client => sub { ... }
+
+クライアントコードはコールバック `$cb` を受け取り、これに対して HTTP::Request オブジェクトを渡すと HTTP::Response オブジェクトを返します。1つのクライアントコード内で複数のリクエストを投げて、リクエストやレスポンスのテストを記述できます。
+
+このファイルを`.t`で保存し、`prove`などでテストを実行します。
+
+### HTTP::Request::Common
+
+これは必須ではありませんが、[HTTP::Request::Common](http://search.cpan.org/perldoc?HTTP::Request::Common) を利用してHTTPリクエストを作成することをおすすめします。コードがより簡潔になります。
+
+ use HTTP::Request::Common;
+
+ test_psgi $app, sub {
+ my $cb = shift;
+ my $res = $cb->(GET "/");
+ # ...
+ };
+
+スキームやホスト名は省略可能で、http://localhost/ (ライブ・テストの場合ポート番号は自動補完されます) になります。
+
+### ライブ/モックモード
+
+デフォルトでは`test_psgi`のコールバックはモックHTTPリクエストモードで実行され、受け取ったHTTP::RequestオブジェクトをPSGI環境変数ハッシュに変換し、PSGIアプリケーションを実行し、レスポンスをHTTP::Responseに変換します。
+
+これをライブHTTPモードに変更して実行するには、a) パッケージ変数`$Plack::Test::Impl` または b) 環境変数 `PLACK_TEST_IMPL``Server` に設定します。
+
+ use Plack::Test;
+ $Plack::Test::Impl = "Server";
+
+ test_psgi ... # the same code
+
+環境変数を使えば、`.t`コードを変更する必要がありません。
+
+ env PLACK_TEST_IMPL=Server prove -l t/test.t
+
+Serverモードでは、PSGIアプリケーションをスタンドアロンサーバで記述し、LWP::UserAgent を利用してHTTPリクエストを送信します。テスト内のクライアントコードを変更する必要はありませんし、ホスト名やポート番号はテスト環境によって自動で設定されます。
+
+### フレームワークをPlack::Testでテスト
+
+繰り返しになりますが、PSGIとPlackの素晴らしいところは、PSGIをターゲットにして書かれたアプリケーションフレームワークであればなんでも利用が可能であるということです。Plack::Testも同様に、PSGIに対応したWebアプリケーションフレームワークをテストすることができます。
+
+ use Plack::Test;
+ use MyCatalystApp;
+
+ my $app = MyCatalystApp->psgi_app;
+
+ test_psgi $app, sub {
+ my $cb = shift;
+ # ...
+ };
+ done_testing;
+
View
36 ja/14_use_plack_request.md
@@ -0,0 +1,36 @@
+## Day 14: Plack::Requestを利用する
+
+Plack自身はWebフレームワークではありません。むしろ、PSGIサーバとミドルウェアの実装にplackup, Plack::Testなどのユーティリティが入ったツールキットのようなものです。
+
+Plackプロジェクトは[HTTP::Engine](http://search.cpan.org/perldoc?HTTP::Engine)プロジェクトから派生した側面もあり、リクエスト・レスポンススタイルのAPIを使ってウェブアプリケーションを開発する需要はあるようです。Plack::Requestは、PSGI環境変数やレスポンス配列に対して、簡単なオブジェクト指向APIを提供します。新しいミドルウェアを記述する際のライブラリとしても利用できますし、PlackをベースにしたWebフレームワークを記述する差異のリクエスト/レスポンスのベースクラスとしても使えます。
+
+### Plack::Request と Response を使う
+
+Plack::Request はPSGI環境変数へのラッパーであり、コードは以下のようになります。
+
+ use Plack::Request;
+
+ my $app = sub {
+ my $req = Plack::Request->new(shift);
+
+ my $name = $req->param('name');
+ my $res = $req->new_response(200);
+ $res->content_type('text/html');
+ $res->content("<html><body>Hello World</body></html>");
+
+ return $res->finalize;
+ };
+
+HTTP::Engineからマイグレートする場合、変更する箇所は`shift`で取得したPSGI環境変数をPlack::Requestに渡し、最後に`finalize`を読んでPSGIレスポンスを取得することだけです。
+
+その他、`path_info`, `uri`, `param` などはHTTP::Engine::RequestやResponseとほぼ同等に動作します。
+
+### Plack::Request と Plack
+
+Plack::Request はPlackディストリビューションに同梱されCPANから入手可能です。Plack::Requestをフレームワークで利用した場合、Plack標準のサーバ以外でも、PSGIに対応したサーバ実装であれば、どのサーバでも動作させることができます。
+
+### Plack::Request を使うか否か
+
+Plack::Requestを利用したコードを`.psgi`に直接記述するのは、簡単なプロトタイピングやテストには便利ですが、ある程度の規模アプリケーション開発にはおすすめしません。1000行のコードをCGIスクリプトに直接書くようなもので、多くの場合はモジュールに分割していくのが正しい方法です。PSGIでも同様で、アプリケーションをクラスにまとめ、リクエストクラスとしてPlack::Requestをサブクラスするなどして、`.psgi`ファイルにはPlack::BuilderのDSLでミドルウェアを設定するようなコードとエントリポイントだけが含まれるようになるはずです。
+
+Plack::Request を利用して既存のフレームワークをPSGIインタフェースに対応させるためのライブラリとして使うのもよいでしょう。
View
77 ja/15_authenticate_your_app_with_middleware.md
@@ -0,0 +1,77 @@
+## Day 15: ミドルウェアでアプリケーションの認証
+
+Plackのミドルウェアは数多くリリースされていて、Plackに含まれているものや、CPANに単独でリリースされているものもあります。このAdvent Calendarをアップデートしている最中にも、多くのデベロッパーがミドルウェアを開発してCPANにアップロードしていました。
+
+今日から、PSGI対応のアプリケーションにすぐ適用可能な、いくつかのおすすめミドルウェアを紹介します。
+
+### Basic認証
+
+Plackミドルウェアはアプリケーションをラップするため、真価を発揮するのはHTTPレイヤでの前処理、後処理です。今日紹介するのはBasic認証を行うミドルウェアです。
+
+アプリケーションへのBasic認証の追加はいくつかの方法があります。フレームワークが対応していれば、提供されている機能で可能でしょう。例えばCatalystではCatalyst::Authentication::Credential::HTTPで対応がされています。多くのCatalyst拡張と同様、認証方法やユーザのストレージなど、様々な設定が可能になっています。
+
+また、認証をウェブサーバレイヤーで行うこともできます。たとえば、Apacheとmod_perlでアプリケーションを動かしている場合、Apacheデフォルトのmod_authモジュールで認証を追加するのはとても簡単ですが、「ユーザをどのように認証するか」の設定は、カスタムのApacheモジュールを書くなどしない限り、限界があります。
+
+Plackミドルウェアでは、Webアプリケーションフレームワークがこうした機能を共有し、多くの場合シンプルなPerlコールバックで拡張することが可能です。Plack::Middleware::Auth::BasicはBasic認証に対してこうしたインターフェースを提供します。
+
+### Plack::Middleware::Auth::Basic
+
+その他のミドルウェアと同様、Auth::Basicミドルウェアの利用はとても簡単です。
+
+ use Plack::Builder;
+
+ my $app = sub { ... };
+
+ builder {
+ enable "Auth::Basic", authenticator => sub {
+ my($username, $password) = @_;
+ return $username eq 'admin' && $password eq 'foobar';
+ };
+ $app;
+ };
+
+
+このコードでアプリケーション`$app`にBaisic認証機能が提供されます。ユーザ名*admin*がパスワード*foobar*でサインインすることができます。認証に成功したユーザはPSGI環境変数`REMOTE_USER`にセットされ、アプリケーションから利用したりAccessLogミドルウェアからログに追加されます。
+
+コールバックベースの設定になるため、Kerberosのような認証システムと連携するのはAuthen::Simpleモジュールをつかうと簡単にできます。
+
+ use Plack::Builder;
+ use Authen::Simple;
+ use Authen::Simple::Kerberos;
+
+ my $auth = Authen::Simple->new(
+ Authen::Simple::Kerberos->new(realm => ...),
+ );
+
+ builder {
+ enable "Auth::Basic", authenticator => sub {
+ $auth->authenticate(@_):
+ };
+ $app;
+ };
+
+同様に [Authen::Simpleバックエンド](http://search.cpan.org/search?query=authen+simple&mode=all) を使ってLDAPなどと連携することも可能です。
+
+### URLMap
+
+URLMap は複数のアプリケーションを1つのアプリケーションに合成することができます。Authミドルウェアと組み合わせると、同一のアプリを認証モードと非認証モードで走らせることもできます。
+
+ use Plack::Builder;
+ my $app = sub {
+ my $env = shift;
+ if ($env->{REMOTE_USER}) {
+ # Authenticated
+ } else {
+ # Unauthenticated
+ }
+ };
+
+ builder {
+ mount "/private" => builder {
+ enable "Auth::Basic", authenticator => ...;
+ $app;
+ };
+ mount "/public" => $app;
+ };
+
+このようにして同一の`$app`を/publicと/privateにマップし、/privateではBasic認証を必須とします。アプリケーションでは`$env->{REMOTE_USER}`をチェックすることで認証ずみアクセスかどうか判別します。
View
66 ja/16_adding_jsonp_support_to_your_app.md
@@ -0,0 +1,66 @@
+## Day 16: アプリケーションにJSONPサポートを追加する
+
+今日はとてもシンプルですが便利な例として、HTTPのベーシック機能だけではないミドルウェアを紹介します。
+
+### JSONP
+
+[JSONP](http://ajaxian.com/archives/jsonp-json-with-padding) (JSON-Padding) はJSONをJavaScriptのコールバック関数にラップするテクノロジーの名前です。JSONベースのコンテンツをサードパーティサイトから`script`タグでクロスドメイン読み込みさせるために利用されています。
+
+### Middleware::JSONP
+
+JSONでエンコードされたデータを`application/json`コンテンツ・タイプで返すアプリケーションがあったとします。簡単なインラインPSGIアプリケーションでは以下のようになります。
+
+ use JSON;
+ my $app = sub {
+ my $env = shift;
+ if ($env->{PATH_INFO} eq '/whatever.json') {
+ my $body = JSON::encode_json({
+ hello => 'world',
+ });
+ return [ 200, ['Content-Type', 'application/json'], [ $body ] ];
+ }
+ return [ 404, ['Content-Type', 'text/html'], ['Not Found']];
+ };
+
+これにJSONPサポートを追加するには、Middleware::JSONPを利用します:
+
+ use Plack::Builder;
+ builder {
+ enable "JSONP";
+ $app;
+ };
+
+たった1行だけです!このミドルウェアは、レスポンスのcontent-typeが`application/json`であるかチェックし、かつ`callback`パラメータがURLにあるかどうかチェックします。"/whatever.json"といったリクエストはそのままJSONとして返されますが、"/whatever.json?callback=myCallback"のようなリクエストには、
+
+ myCallback({"hello":"world"});
+
+というデータが Content-Type `text/javascript` で返され、 Content-Length は自動で調整されます(すでに設定されていた場合)。
+
+### フレームワーク
+
+JSONに加えてJSONPをサポートするのは、多くのフレームワークでは簡単なことですが、Middleware::JSONP はPSGI/Plackのレイヤで共通動作させるものを簡単につくれるよい例でしょう。
+
+もちろん、JSONPミドルウェアはJSONを出力するフレームワークであればどんなものでも適用することができます。Catalystであれば、
+
+ package MyApp::View::JSON;
+ use base qw( Catalyst::View::JSON );
+
+ package MyApp::Controller::Foo;
+ sub hello : Local {
+ my($self, $c) = @_;
+ $c->stash->{message} = 'Hello World!';
+ $c->forward('MyApp::View::JSON');
+ }
+
+これに、Plack::BuilderでJSONPサポートを追加します。
+
+ use MyApp;
+ my $app = MyApp->psgi_app;
+
+ use Plack::Builder;
+ builder {
+ enable "JSONP";
+ $app;
+ };
+
+JSONを出力する[Catalyst::View::JSON](http://search.cpan.org/perldoc?Catalyst::View::JSON) は私が書いたもので、JSONPコールバックはネイティブでサポートされていますが、やり方は1つではありません!
View
42 ja/17_serving_static_files_from_your_application.md
@@ -0,0 +1,42 @@
+## Day 17: 静的ファイルを配信する
+
+Day 5 ではplackupでカレントディレクトリからファイルを配信する方法を紹介しました。ミドルウェアの利用方法や、URLMapをつかったアプリケーションの合成方法を学んだので、Webアプリケーション開発に必須の機能を追加するのもとても簡単です。静的ファイルの配信です。
+
+### あるパスから静的ファイルを配信する
+
+ほとんどのフレームワークが静的ファイルを配信する機能を備えています。PSGIに対応したフレームワークであれば、この機能をつける必要はもうありません。Staticミドルウェアを利用します。
+
+ use Plack::Builder;
+
+ my $app = sub { ... };
+
+ builder {
+ enable "Static", path => qr!^/static!, root => './htdocs';
+ $app;
+ }
+
+/staticではじまるリクエストにマッチすると、そのパスを"htdocs"にマップします。つまり、"/static/images/foo.jpg" は "./htdocs/static/images/foo.jpg" のファイルをレスポンスとして返します。
+
+多くの場合、ディレクトリ名を変更したり、ローカルのパス名とオーバーラップしている場合があります。たとえば、/static/index.css へのリクエストを "./static-files/index.css" にマッピングするといった具合です。以下のようにします。
+
+ builder {
+ enable "Static", path => sub { s!^/static/!! }, root => './static-files';
+ $app;
+ }
+
+重要なのは、pathに正規表現 (`qr`) ではなく、コールバックを利用し、`sub { s/// }`で文字列を置換しています。コールバックはリクエストパスに対して実行され、その値は `$_` に保存されています。この例では、リクエストパスが "/static/" で始まるかテスト、その場合パスから削除し、残りのパスを "./static-files/" 以下に追加しています。
+
+結果として、"/static/foo.jpg" は "./static-files/foo.jpg" となります。このパターンマッチに失敗したリクエストはそのまま元の `$app`にパススルーされます。
+
+### URLMap と App::File でDYI
+
+Perlですから、やり方は一つではありません。Day 12で紹介したmountやURLMapの使い方を覚えていれば、App::Fileと`mount`を使う方法はより直感的にかけます。前の例は、以下のように書けます。
+
+ use Plack::Builder;
+
+ builder {
+ mount "/static" => Plack::App::File->new(root => "./static-files");
+ mount "/" => $app;
+ };
+
+これをどう見るかは個人の主観でしょうが、個人的にはこちらのほうが簡潔だと思います。Staticミドルウェアのコールバックでは、リクエストパスのマッチングや置換がより柔軟に行えるため、こちらを使う方がよい場合もあるでしょう。どちらでも好きな方法を使ってください。
View
49 ja/18_load_middleware_conditionally.md
@@ -0,0 +1,49 @@
+## Day 18: ミドルウェアを条件ロードする
+
+いくつかのミドルウェアを紹介しました。便利なので全体に有効にできるものもあれば、ある条件下でのみ有効にしたいものもあるでしょう。どうやってそれを実現するかを解説します。
+
+### ミドルウェアを条件分岐でロードする
+
+Conditional ミドルウェアはメタミドルウェアで、1つのミドルウェアを受け取り、それをランタイムの条件によって適用させるか決定するミドルウェアを返します。例をとってみましょう。
+
+* JSONP ミドルウェアをパスが /public で始まるときだけ有効にしたい
+* Basic認証をローカルIPからのリクエストについては無効にしたい
+
+WSGIやRackでこうした問題をどのように対処するかを調査していましたが、きれいな方法は見つかりませんでした。各ミドルウェアで有効にする条件を設定するのは、あまりいい方法だとは思えませんでした。
+
+### Middleware::Conditional
+
+Conditional ミドルウェアはこうした問題を柔軟に解決します。
+
+ use Plack::Builder;
+
+ builder {
+ enable_if { $_[0]->{REMOTE_ADDR} !~ /^192\.168\.0\./ }
+ "Auth::Basic", authenticator => ...;
+ $app;
+ };
+
+Plack::Builder に新しいキーワード `enable_if` が追加されています。ブロックを受け取り、リクエスト時に評価され(`$_[0]`がPSGI環境変数ハッシュ) ブロックがtrueを返した場合、ミドルウェアでラップされたアプリケーションを、そうでない場合はなにもせずにパススルーします。
+
+この例ではリクエストがローカルネットワークから来ているかチェックし、そうでない場合にBasic認証ミドルウェアを適用しています。
+
+Conditional は普通のミドルウェアとして実装sれているので、内部的には以下のコードと同等です:
+
+ use Plack::Middleware::Conditional;
+ use Plack::Middleware::Auth::Basic;
+
+ my $app = sub { ... };
+
+ $app = Plack::Middleware::Conditional->wrap($app,
+ builder => sub {
+ Plack::Middleware::Auth::Basic->wrap(
+ $_[0], authenticator => ...,
+ );
+ },
+ condition => sub {
+ my $env = shift;
+ $env->{REMOTE_ADDR} !~ /^192\.168\.0\./;
+ },
+ );
+
+ですがこれを毎回書くのは退屈ですので、DSL版をおすすめします :)
View
54 ja/19_cascade_multiple_applications.md
@@ -0,0 +1,54 @@
+## Day 19: 複数のアプリケーションをカスケードする
+
+Conditionalミドルウェア(Day 18)とURLMapアプリケーション(Day 12)には共通点があります。これら自体がPSGIアプリケーションですが、既存のPSGIアプリケーションやミドルウェアを受け取ってそれらにディスパッチするものです。これがPSGIのアプリケーションやミドルウェアの美しい点で、今日紹介するのもその一例です。
+
+### 複数のアプリケーションをカスケードする
+
+複数のアプリケーションを順番に実行し、成功が返ってくるまでカスケードするのは便利なことがあります。デザインパターンではChain of responsibilityと呼ばれ、mod_perlハンドラなどのWebアプリケーションでも応用されています。
+
+### Cascade Application
+
+Plack::App::Cascade は複数のPSGIアプリケーションを合成し、順番に実行して404以外のレスポンスが返ってくるまでトライします。
+
+ use Plack::App::Cascade;
+ use Plack::App::File;
+ use Plack::App::URLMap;
+
+ my @paths = qw(
+ /home/www/static
+ /virtualhost/example.com/htdocs/static
+ /users/miyagawa/public_html/images
+ );
+
+ my $app = Plack::App::Cascade->new;
+ for my $path (@paths) {
+ my $file = Plack::App::File->new(root => $path);
+ $app->add($file);
+ }
+
+ my $map = Plack::App::URLMap->new;
+ $map->mount("/static" => $app);
+ $map->to_app;
+
+このアプリケーションを URLMap を使って /static にマップしています。すべてのリクエストは`@paths`に設定された3つのディレクトリをApp::Fileで順番にトライし、ファイルが見つかったらそれをレスポンスとして返します。スタティックファイルを複数のディレクトリからカスケードして返すのに便利です。
+
+### アプリケーションをカスケード
+
+ use CatalystApp;
+ my $app1 = CatalystApp->psgi_app;
+
+ use CGI::Application::PSGI;
+ use CGIApp;
+ my $app2 = sub {
+ my $app = CGIApp->new({
+ QUERY => CGI::PSGI->new($_[0]),
+ });
+ CGI::Application::PSGI->run($app);
+ };
+
+ use Plack::App::Cascade;
+ Plack::App::Cascade->new(apps => [ $app1, $app2 ])->to_app;
+
+この例では2つのアプリケーション、1つはCatalyst もう1つはCGI::Applicationを用意し、順番に実行します。/what/ever.cat をCatalystアプリケーション、/what/ever.cgiapp をCGI::Application側で処理する、といった際にこのようにカスケードさせることができます。
+
+とはいえ、クレイジーなアイデアのように聞こえるかもしれません。実際にはURLMapで違うパスにmountするほうが現実的でしょうが、こういうこともできるということで :)
View
39 ja/20_access_your_local_app_from_the_internet.md
@@ -0,0 +1,39 @@
+## Day 20: ローカルアプリケーションにインターネットからアクセスする
+
+(**注意**: reverseHTTP サービスは2012年現在停止しています)
+
+最近では、ノートPC上でアプリケーションを開発し、ローカルのIPアドレスを使ってテストをするのが簡単です。こうして開発してローカルで動いているアプリケーションに対して、リモートで仕事をしている同僚や、webhookなどのテストをするために、インターネットからアクセスしたいことがあります。
+
+### Reverse HTTP
+
+この問題を解決するにはいくつかのソリューションがありますが、一つ面白いやりかたが[ReverseHTTP](http://www.reversehttp.net/)を使った方法です。ReverseHTTPはクライアント・サーバ・ゲートウェイ間のシンプルなプロトコルで、HTTP/1.1の拡張を用いています。便利なことに、reversehttp.netでデモゲートウェイが動作しているため、自分でサーバを立てたりすることなく、デモに利用することができます。
+
+これが実際どのように動作するのか興味が有る人は、[仕様書](http://www.reversehttp.net/specs.html)に目を通してみるとよいでしょう。*Reverse* HTTP という名前の通り、動作させるアプリケーション・サーバがロングポールのHTTPクライアントになり、ゲートウェイ・サーバがインターネット経由でアクセスされたリクエストをレスポンスとして返します。
+
+### Plack::Server::ReverseHTTP
+
+[Plack::Server::ReverseHTTP](http://search.cpan.org/~miyagawa/Plack-Server-ReverseHTTP-0.01/) はPlackのバックエンドサーバ実装で、ReverseHTTPプロトコル上でPSGIアプリケーションを実行し、外部インターネットから、ローカルで動作しているPSGIアプリケーションへのアクセスを可能にします。
+
+ReverseHTTPを利用するには、必要なモジュールをCPANからインストールし、以下のコマンドを実行します。
+
+ > plackup -s ReverseHTTP -o yourhostname --token password \
+ -e 'sub { [200, ["Content-Type","text/plain"], ["Hello"]] }'
+ Public Application URL: http://yourhostname.www.reversehttp.net/
+
+`-o``--host`のエイリアスで、利用するサブドメイン(ラベル)を指定します。`--token`は登録したラベルを使うためのパスワードとして利用します。指定しないこともできますが、この場合、登録したラベルを後から誰でも利用可能になります。
+
+コンソールに出力されたアドレス(URL)をブラウザで開くと、Helloが表示されます。
+
+### フレームワークからの利用
+
+もちろんPSGIサーバのバックエンドですから、どんなフレームワークでも利用することができます。Catalystアプリに対して実行するには、
+
+ > catalyst.pl MyApp
+ > cd MyApp
+ > plackup -o yourhost --token password myapp.psgi
+
+たったこれだけです。 デフォルトのCatalystアプリケーションが http://yourhost.reversehttp.net/ というURLで、インターネット経由でどこからでもアクセス可能です。
+
+### 注意
+
+ReverseHTTP.netのゲートウェイサービスは実験的なものであり、SLAのような保証はありません。プロダクション環境などでの利用は避けたほうが良いでしょう。ちょっとしたアプリを友達に見せるときなどに、SSHやVPNトンネリングなどを必要とせず利用できるのは便利ですね。
View
43 ja/21_lint_your_application_and_middleware.md
@@ -0,0 +1,43 @@
+## Day 21: アプリケーションとミドルウェアのLintチェック
+
+既存のWebフレームワークをPSGIに対応させたり(Day 8)、新しくアプリケーションをPSGIインタフェースで開発する話をしてきましたが、エラー処理についてはまだ解説していませんでした。
+
+### エラー処理
+
+plackupではデフォルトで素敵なスタックトレース(Day 3)が有効になっています。ユーザのアプリケーションが例外を投げた場合、これを捕捉してエラーページを表示します。もし、ミドルウェアやアプリケーションフレームワークのアダプターそのものにバグやエラーがあった場合はどうでしょう?
+
+以下のコードを走らせてみます:
+
+ > plackup -e 'sub { return [ 0, {"Content-Type","text/html"}, "Hello" ] }'
+
+繰り返しですが、生のPSGIインタフェースでアプリケーションを書くことは本来ありませんが、ミドルウェアやフレームワークのアダプターにバグがあった場合のシミュレーションには十分です。
+
+このアプリケーションにブラウザからアクセスすると、サーバは以下のようなエラーとおもにクラッシュします。
+
+ Not an ARRAY reference at lib/Plack/Util.pm line 145.
+
+これは、レスポンスのフォーマットがPSGIインターフェース的に不正であるためです。ステータスコードが不正ですし、ヘッダが配列でなくハッシュリファレンスになっており、またボディも配列でなくプレーンな文字列になっています。
+
+### Lint ミドルウェア
+
+こうしたエアーを各サーバでチェックすることは可能ですが、あまり綺麗なほうほうではありません。コードの重複がおきますし、実際にプロダクション環境でこうしたチェックをすることはパフォーマンスの観点からもよくありません。こうしたアプリケーション、サーバやミドルウェアの妥当性はテストや開発時に検証し、プロダクションでは無効にするのがよいでしょう。
+
+Middleware::Lint はリクエストやレスポンスが妥当なPSGIインタフェースかをチェックします。PSGIアプリケーションをLintミドルウェアを有効にして実行します。
+
+ > plackup -e 'enable "Lint"; sub { return [ 0, { "Content-Type"=>"text/html" }, ["Hello"] ] }'
+
+(**注意**: 執筆時はLintがplackupデフォルトではありませんでしたが、現在はdevelopmentモードでは有効になるため、別途指定する必要はありません)
+
+こうすると、アプリケーションにアクセスすると以下のようなエラーとスタックトレースが表示されます。
+
+ status code needs to be an integer greater than or equal to 100 at ...
+
+Lintミドルウェアがレスポンスが正しくPSGI仕様に沿っているかチェックするためです。
+
+フレームワークのアダプタやミドルウェアを開発する際は、必ずLintミドルウェアを有効にすることを忘れないでください。
+
+### 新しくPSGIサーバを書く
+
+Lintミドルウェアはリクエスト、レスポンス両方のバリデートを実装していますので、新しくPSGIサーバを開発する際にもチェックが利用できます。ただし、サーバの開発者でさらにPSGI仕様を正しく実装しているかテストしたいには、Plack::Test::Suiteを利用するとよいでしょう。
+
+実際にPlack::Test::Suiteを利用しているコードがPlackの`t/Plack-Handler`ディレクトリ内に含まれています。ここにはPSGIサーババックエンドをテストするためのテストスイートが用意されていて、既存のPlack::Handlerはすべてこのテストをパスするように書かれています。
View
77 ja/22_discover_more_middleware.md
@@ -0,0 +1,77 @@
+## Day 22: さらにミドルウェアの紹介
+
+この連載も終了に近づいて来ましたが、すべてのミドルウェアを紹介するには紙面が足りないようです。今日はまだ紹介していないいくつかの素晴らしいミドルウェアを簡単に紹介しましょう。
+
+### ErrorDocument
+
+アプリケーションが500エラーを出した際や、認証が失敗した際のForbiddenページを出力する際、レスポンスコードに応じて、カスタムのエラーページを表示したいことがあります。ErrorDocumentは、Apacheの同名ディレクティブと同様、この処理を実装しています。
+
+ builder {
+ enable "ErrorDocument", 500 => "/path/to/error.html";
+ $app;
+ };
+
+任意のエラーコードをスタティックファイルのパスにマップします。開発時にはStackTraceミドルウェア、プロダクションではErrorDocumentできれいなエラーページを表示するとよいでしょう。
+
+このミドルウェアはPlackディストリビューションに付属しています。
+
+### Session
+
+Rackでは`rack.session`をRackの環境変数で標準定義しており、Hashオブジェクトのインタフェースを提供しています。PSGIではこれを標準には取り入れていませんが、アイデアと実装についてはかなりインスパイアされています。
+
+ builder {
+ enable "Session", store => "File";
+ $qpp;
+ };
+
+デフォルトではセッションデータはオンメモリのハッシュに保存されますので、preforkやマルチプロセス型のサーバではうまく動作しません。CHIなどのエンジンが付属していて、またその他のストレージエンジンに対するインタフェースを記述することで、Authミドルウェアなどと同様、拡張を簡単に行うことができます。
+
+セッションデータは`psgix.session`というPSGI環境変数にハッシュリファレンスとして格納されています。アプリケーションやフレームワークはこのハッシュに直接アクセスしてもよいですし、Plack::Sessionモジュールを使ってラッパーを定義することも可能です。例えば、Tatsumakiフレームワークでは以下のように利用できます。
+
+ # Tatsumaki app
+ sub get {
+ my $self = shift;
+ my $uid = $self->request->session->get('uid');
+ $self->request->session->set(last_access => time);
+ ...
+ }
+
+Sessionミドルウェアの利点として、PSGIアプリケーション間でのセッション共有が可能になるということです。フレームワークのアダプターによっては、ユーザアプリケーションからPSGI環境変数へのアクセスが許可されていない場合がありますが、こうした問題は徐々に解消されていくはずです。
+
+SessionミドルウェアはStevan Littleによって開発され、[github](http://github.com/stevan/plack-middleware-session) とCPANから入手できます。
+
+### Debug
+
+こちらも[Rack-bug](http://github.com/brynary/rack-bug)と[django debug toolbar](http://github.com/robhudson/django-debug-toolbar)からのインスパイアで、このミドルウェアを有効にすると、デバッグ用の「パネル」が表示され、リクエストに関するデータやアナリティクスが表示されます。
+
+標準のパネルにはTimer(リクエスト時間)、Memory(メモリー使用量)、Request(リクエストヘッダ情報)、Response(レスポンスヘッダ)などが含まれています。
+
+ builder {
+ enable "Debug";
+ $app;
+ };
+
+利用はたったこれだけで、利用するパネルを制限したり、標準以外のものを追加するには、`panels`パラメータを指定します。
+
+DBIのクエリプロファイラや、Catalystのログなどの拡張パネルはCPANとgithubから入手可能です。
+
+### Proxy
+
+HTTPリクエストをインターネットまたはローカルネットワークで動いている別のアプリケーションにプロキシしたいことがあります。たとえば、JSONPをサポートしていないJSON APIをプロキシしたい場合など、Cross Origin Policy上アクセスできないため、プロキシを立てる必要があります。また、ローカルで動く別のアプリケーションに対してフロントエンド的に動作させるリバースプロキシ的な利用法もあるでしょう。
+
+Plack::App::Proxyはこれらを可能にします。
+
+ use Plack::App::Proxy;
+ use Plack::Builder;
+
+ my $app = Plack::App::Proxy->new(host => '192.168.0.2:8080')->to_app;
+
+ builder {
+ mount "/app" => $app;
+ };
+
+Plack::App::ProxyはLee Aylwardによって[github](http://github.com/leedo/Plack-App-Proxy)で開発されています。
+
+### さらに
+
+さらに多くのミドルウェアがPlackディストリビューションに付属し、またCPANから検索することができます。すべてのミドルウェアがすぐに使えるというわけではないかもしれませんが、PSGIをサポートするフレームワークで共有できるというすばらしいメリットがあります。
View
111 ja/23_write_your_own_middleware.md
@@ -0,0 +1,111 @@
+## Day 23: ミドルウェアを書く
+
+ミドルウェアの紹介の最後として、自分で書いてみることにしましょう。
+
+### ミドルウェアを書く
+
+PSGIミドルウェアは、通常のPSGIアプリケーションと同様に動作しますが、実際のPSGIアプリケーションをラップするため、サーバからみるとアプリケーションのように見え、ラップされたアプリケーションからはサーバのように振る舞います。
+
+User-Agentを偽装するためのシンプルなミドルウェアは以下のようになります。
+
+ # Wrapped application
+ my $app = sub {
+ my $env = shift;
+ my $who = $env->{HTTP_USER_AGENT} =~ /Mobile Safari/ ? 'iPhone' : 'non-iPhone';
+ return [ 200, ['Content-Type','text/html'], ["Hello $who"] ];
+ };
+
+ # Middleware to wrap $app
+ my $mw = sub {
+ my $env = shift;
+ $env->{HTTP_USER_AGENT} .= " (Mobile Safari)";
+ $app->($env);
+ };
+
+アプリケーションはリクエストがiPhoneブラウザ (*Mobile Safari*) からきた場合のみ、"Hello iPhone" を表示します。このミドルウェアは Mobile Safari 文字列をすべてのリクエストに追加します。このアプリケーションを実行して、任意のブラウザで表示すると、"Hello iPhone" が表示され、アクセスログには以下のように表示されるでしょう。
+
+ 127.0.0.1 - - [23/Dec/2009 12:34:31] "GET / HTTP/1.1" 200 12 "-" "Mozilla/5.0
+ (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like
+ Gecko) Version/4.0.4 Safari/531.21.10 (Mobile Safari)"
+
+" (Mobile Safari)" がUser-Agent文字列に追加されています。
+
+### 再利用可能なMiddlewareにする
+
+`.psgi`にインラインで記述する方法は、一度きりの利用をするには大変便利ですが、多くの場合、一般化して他のアプリケーションでも再利用できるようにしたいでしょう。Plack::Middlewareを利用すると、これが可能になります。
+
+ package Plack::Middleware::FakeUserAgent;
+ use strict;
+ use parent qw(Plack::Middleware);
+ use Plack::Util::Accessors qw(agent);
+