Perl5 での Plack に当たる Crust をみんなで作った話

この記事は Perl 6 Advent Calendar 2015 の1日目です。

Perl 6 は、2015年のクリスマスにリリースされることになっており、我々としてはそれを待ち受ける必要があると考えました。

Perl6 がリリースされた暁には、いろいろ遊ぼうかなという気持ちをみなさんお持ちだと思います。 Perl6 には夢が詰まっており、様々な機能が含まれている夢の言語です。

そういった、夢の機能については今後、クリスマスまでの間に、語られていきますが、本稿では、現実的な話をします。


今年のクリスマスに Perl6 がリリースされるぞ、という宣言がでたわけですが、そうなってくると、Perl6 をクリスマスから早速遊びたいなと思うわけですよね。

そして、私は web engineer なので、 Perl6 が出たら早速 web application を書きたいと思うわけです。

しかし、そこで気づいてしまう。Perl6 には Plack のようなものが無いと!

Perl6 に Plack のようなものがないし、当時まともな httpd の実装が存在していなかったのです! (実際には存在はしていたのですが、multi thread 対応していないし、なぜか当時の MoarVM は listen の backlog が 1 にハードコードされているためにまったく実用的ではなかったのです。この listen のバックログがハードコードされている問題は現在では修正されています)

これではいけない。と気づくわけです。まともな httpd が必要だ。 とりあえず fork(2) があれば、listen backlog が 1 にハードコードされているというハードな環境下でもなんとかなるだろうと思って、まず NativeCall ( Perl6 から FFI で C 関数をコールする機能) を使って fork を呼ぶようにしてみました。これはなかなかうまく動作したのですが、Mac で動作しないという問題が発見されました。

なぜか。

MoarVM は内部で libuv を利用しており、あらゆるソケット処理に libuv を利用しています。 libuv は fork をサポートしていません。より具体的に言うと mac の kqueue は fork をサポートしてないので、完全に詰みました。

対策として、ソケットライブラリを全部 NativeCall で実装することも考えたのですが(実装もしたのですが)、完全に本質を見失っている感じがしてきたので、この方針は諦めることにしました。


そうこうしているうちに、IO::Socket::Async ベースならわりと動くっぽいのではないかという話になり、IO::Socket::Async ベースで実装する方針に転換しました。

何度か書き直したのですが、まあそこそこ動くようになりました。

そのそこそこ動く実装が HTTP::Server::Tiny です。これは Perl5 の有名な httpd 実装である kazuhooku 氏による Starlet を参考に実装されており、HTTP/1.1 に対応した高速なサーバーです。 (Perl6 でできる範囲としてはかなり高速になるように実装しています。期待したパフォーマンスが出ていなければ、それは、、)

https://github.com/tokuhirom/p6-HTTP-Server-Tiny/


そういうわけで、HTTP::Server::Tiny ができたので、あとは Plack 相当のレイヤーを実装しようということになりました。

そこで、下記12名の Perl Monger が集まり、Plack を Perl6 に移植するプロジェクトに乗り出しました。

  • fayland
  • hiroraba
  • kentaro
  • lestrrat
  • mattn
  • moznion
  • retupmoca
  • softmoth
  • sugyan
  • syohex
  • syoichikaji
  • tokuhirom

https://github.com/tokuhirom/p6-Crust

結果として、2015年12月1日時点でほぼ Plack の機能を実装しております。 例えばイカのように実行すれば、さくっと httpd が立ち上がります。めっちゃ便利。

crustup -e 'sub { 200, [], ["OK"] }'

具体的にはイカのものが完備されています。

  • Crust::App::Directory
  • Crust::App::File
  • Crust::App::URLMap
  • Crust::Builder
  • Crust::Handler::FastCGI
  • Crust::Handler::HTTP::Easy
  • Crust::Handler::HTTP::Server::Tiny
  • Crust::Headers
  • Crust::Middleware::AccessLog
  • Crust::Middleware::Auth::Basic
  • Crust::Middleware::Conditional
  • Crust::Middleware::ContentLength
  • Crust::Middleware::ErrorDocument
  • Crust::Middleware::Lint
  • Crust::Middleware
  • Crust::Middleware::ReverseProxy
  • Crust::Middleware::Runtime
  • Crust::Middleware::StackTrace
  • Crust::Middleware::Static
  • Crust::Middleware::XFramework
  • Crust::MIME
  • Crust
  • Crust::Request
  • Crust::Request::Upload
  • Crust::Response
  • Crust::Runner
  • Crust::Test::MockHTTP
  • Crust::Test
  • HTTP::Message::PSGI

そんなわけで、ウェブアプリケーションをかく準備は整っています。

あとは Perl6 のリリースを待つだけや!!!!

明日は karupanerura さんの 無限リストであそぶ です。

http://qiita.com/advent-calendar/2015/perl6