Perl プログラミング:
CGI と PSGI
(ビギナー向け)

Naney <>

2013年12月24日

HTTP

まずは HTTP についてのおさらい

  • HyperText Transfar Protocol
  • RFC 2616 (http://www.ietf.org/rfc/rfc2616.txt)
  • クライアントがサーバへ接続しリクエストを送り、サーバがレスポンスを返すというプロトコル。

用語 (RFC 2616)

  • クライアント (client)
  • サーバ (server)
  • リクエスト (request)
  • レスポンス (response)

静的なコンテンツ

リクエスト URI (section 5.1.2) などを元に、サーバがホスト上のファイルを読み込みメッセージボディとして返す。

  • Apache HTTP Server (以下 Apache) なら
    • デフォルトで htdocs ディレクトリ(DocumentRoot)以下にある対応するファイルを返す。
http://www.example.com/example.html →
/usr/local/apache/htdocs/example.html

動的なコンテンツ

リクエスト URI などを元に、サーバがリソースを生成しレスポンスとして返す。

http://www.example.com/trend-information → どうやって生成する?
  • (方式1)サーバ自体がリソースを生成して返す。
    • 毎回 TCP/IP ソケット処理まで HTTP 通信を実装するのは大変。
  • (方式2)Web サーバがリソースを生成するプログラムを使って、そのプログラムが生成したリソースを受け取って返す。
    • ネットワーク処理などは Web サーバに任せられる。

リソースを生成する Perl プログラムとのインタフェース

外部プログラムをプロセスとして実行する方式

  • CGI
  • FastCGI
  • SpeedyCGI

Web サーバに Perl インタプリタを埋め込んで実行する方式

  • mod_perl (Apache)

読み込んだ Perl のサブルーチンを実行する方式

  • PSGI

CGI

CGI

CGI リクエスト

  • リクエスト外部変数
    • UNIX 互換 OS では環境変数として渡される。
    • Perl では %ENV
  • リクエストメッセージボディ
    • 標準入力に渡される。
    • Perl では STDIN
  • スクリプトコマンドライン
    • コマンドライン引数として渡される。
    • Perl では @ARGV

CGI レスポンス

  • 標準出力に返す。
  • message-header と message-body で構成する。

LL 言語以外でももちろん OK

例:

#include <stdio.h>

int main(void) {
  printf("Content-Type: text/html\x0d\x0a");
  printf("\x0d\x0a");
  printf("!<DOCTYPE html>\x0d\x0a");
  printf("<title>Hello World!</title><p>Hello World!</title>");
  return 0;
}
cat > a.c
上記の内容
gcc -Wall -o a.cgi a.c

CGI プログラムとして実行できる場所に置く/設定して a.cgi にアクセス。

Perl CGI プログラムを書く

#!/usr/local/bin/perl -w
use CGI;
$q = CGI->new;
      $q->start_html('hello world'),
      $q->h1('hello world'),
      $q->end_html;
# CGI.pm の Pod より。

Perl CGI プログラムの使いどころ

  • CGI 使用のできるレンタルサーバなどで動的ページを提供したい時。
    • なお CGI 呼び出しされたプログラムから後述の PSGI アプリケーションを実行することもできる。
やり方1
#!/usr/bin/env plackup
以下 .psgi ファイルと同じ。
やり方2
#!/usr/bin/perl
use Plack::Loader;
my $app = Plack::Util::load_psgi("/path/to/app.psgi");
Plack::Loader->auto->run($app);
どちらも Plack::Handler::CGI の Pod より。

PSGI

PSGI

  • Perl Web Server Gateway Interface
  • Web サーバと Web アプリケーションフレームワークとの間の共通インタフェース
  • アプリケーションはコードリファレンス
  • アプリケーションの実行環境はハッシュリファレンスとして渡される。
  • アプリケーションは3要素の配列リファレンスを返す。
my $handler = sub {
  return [
    200,
    ["Content-Type" => "text/plain", "Content-Length" => 11],
    ["Hello World"]
  ];
};
Plack 1.0030 eg/dot-psgi/Hello.psgi より。

Plack

plackup ワンライナー

plackup -e 'sub { [ 200, [ "Content-Type" => "text/plain" ], [ "Hello World" ] ]}'
curl http://localhost:5000/

ワンライナーについては Shibuya Plack PSGI Conference #1 での @bayashi 氏のスライド plackup 2013 Winter Collection が詳しい。

Server

  • Plack (Web サーバアダプタ)
  • HTTP::Server::PSGI
  • Starman
  • Twiggy
  • Starlet

など。

PSGI の使いどころ

  • Web アプリケーションフレームワークを書く時
    • PSGI をサポートしておけば、Web サーバからの様々な呼び出し方法に対応する必要がない (Plack が対応してくれる)
  • 新しく自分で Web アプリケーションを書く時
    • plackup などのユーティリティや、Plack のテストツールを使える。
    • Plack 向けミドルウェアが使える。
  • 新規に作るなら基本 PSGI で。

おしまい

Appendix

by @Naney