cpan

これにインスパイヤされて。

Python と Twisted できみにも書ける Web サーバ
誰でも比較的簡単に Web サーバを書くことを可能にするのが Python と Twisted というフレームワークの組合せです。

Pure Perlで書かれたWeb Serverはそれこそ山ほどあるのですが、実はLWPにもサーバーを簡単に実装するModuleが用意されていて、それがHTTP::Daemonです。

例えば、ブラウザのリクエストをおうむ返しにするサーバーは、以下のとおりとなります。

#!/usr/local/bin/perl -T
use strict;
use warnings;
use HTTP::Daemon;
use HTTP::Date;

my $d = HTTP::Daemon->new(
    LocalAddr => '0.0.0.0',
    LocalPort => shift || 8080
) or die $!;

while ( my ( $c, $peer_addr ) = $d->accept ) {
    while ( my $req = $c->get_request ) {
        my $header = HTTP::Headers->new( 'Content-Type' => 'text/plain' );
        my $res = HTTP::Response->new( 200, 'OK', $header, $req->as_string );
        $c->send_response($res);
        print_log($peer_addr, $req, $res);
    }
    $c->close;
    undef($c);
}

# you don't need this unless you need logging
sub print_log {
    use Socket qw/sockaddr_in inet_ntoa/;    # to deparse $peer_addr
    use bytes ();                            # for length
    my ( $peer_addr, $req, $res ) = @_;
    my ( $port, $iaddr ) = sockaddr_in($peer_addr);
    my $remote_addr = inet_ntoa($iaddr);
    my $remote_user = $req->headers->authorization_basic || '-';
    $remote_user =~ s/:.*//o;
    printf qq(%s %s - [%s] "%s %s %s" %d %d\n), 
        $remote_addr, $remote_user, time2str( time() ),
         $req->method, $req->url, $req->protocol,
         $res->code, bytes::length( $res->content );
}
__END__

一応stdoutにCommon Logを吐くように書きましたが、logすら不要ならprint_log()も不要なので、20行未満でWeb Serverの出来上がりです。

もちろん、HTTP::Daemonという名前に反して、プロセスをdaemon化したりまではしてくれないので、本格的なWeb Serverを書くならCookbookの第17章を参考にしたり、POEを使うなりするべきですが、意外なところにお宝が隠れている例としてHTTP::Daemonを取り上げた次第です。

Enjoy!

Dan the Daemon