ホーム > perl
perlのアーカイブ
Plack::Middleware::Header
- 2009/12/3 木曜日 23:19:23
- perl
Plack::Middleware::Headerをgithubに上げました。
これは、Plack::Middlewareレイヤーでレスポンスヘッダを設定するもので、Apacheでいうところのmod_headersに相当します。
使い方はこんな感じです。
use Plack::Builder; builder { enable 'Header', set => ['X-Plack-One' => '1'], append => ['X-Plack-Two' => '2'], unset => ['X-Plack-Three']; $app; };
自分はPlack::Middleware::Staticと併用してExpiresをつけたりするのに使うために作りました。IEがExpires: -1とかやっておかないとしばらくキャッシュしてIf-Modifled-Sinceなリクエストも投げてくれなくなっちゃうという弊害があったので。
あと、IE関連では、If-Modified-Sinceの値に”;length=***”という余計なものが付いてきてしまい(ここやここを参照)、Middleware::ConditionalGETを有効にしても304を吐けなかったりしていたので、それを取り除くためのMiddlewareも書いてみました。こちらは名前とかがきもいのでgistレベル。
追記(2009-12-13 21:27): cpanにアップしました。あと、If-Modified-SinceのIEバグの件はmiyagawaさんがConditionalGET側で対応してくれました
patternがemptyな場合には前回成功時のpatternが使われるというハマりポイント
- 2009/11/26 木曜日 2:42:23
- perl
print "match1\n" if "baz" =~ m{}; "foo" =~ m{foo}; print "match2\n" if "baz" =~ m{};
の結果は
match1
である。なぜならperldoc perlrerefに書いてある通り、
If 'pattern' is an empty string, the last successfully matched regex is used.
であるから。
patternを動的に生成してたりする時に空になっちゃうケースなんかがあると思うので、その場合はマッチ処理自体を回避するようにしたほうがよいかと思われます。
最初バグかと思いました。
Casual Talks#1でLTしてきました
- 2009/11/21 土曜日 22:35:56
- perl
昨日(11/20)にperl-casualのCasual Talks#1にて拙作のFormValidator::NestedについてLTしてきました。
slideをslideshareにあげておきました。
得られた教訓
1. 実際に話し始めると早口気味になるのでスライド大目ぐらいが自分にはちょうどいいかも
2. プロジェクターにつなぐときはねじをちゃんとしめておく
3. やっぱり笑いを一つぐらいとっといたほうが場は暖かくなる
(PAUSE ID requestの際にcatalyst-pluginを作りたいと書いていたと言ったときに若干嘲笑気味の笑いはありましたがw)
自分以外も発表が初めてだという方も多かったのに、発表が皆さんうまくて非常に面白かったです。またの機会があったら今回の教訓を踏まえまた発表できたら幸いです。
主催されたyusukebeさん、会場の用意や二次会の(実質)幹事をされたnobjasさんお疲れ様でした。
JSocketを使ってPOSTもストリーミングするPlackアプリ
- 2009/10/20 火曜日 3:58:37
- perl
さて、前エントリでJSocketというのを作ったと書いたのですが、これは実はjavascriptで動くtwitter streamクライアントを作るならばmultipart/mixedを使うべきというのを読んで、レスポンスがpollではなくてストリーミングできるというのを知って、リクエストもやりたいよというふうに思ったのがきっかけでした。
まず、XHRでできないかを試してみたのですが、xhr.send(data)を一回読んでしまうと少なくともjavascript側ではリクエストは完了したと思ってしまって、再度xhr.send(data)しても反応はありませんでした。
そこでJSocketの登場です。JSocketを使うとhttpリクエストを断続的に送信することができます。やったですね。
で、Plack::Server::Coroを使って試しに
リアルタイムチャット
を作ってみました。どうぞお試し下さい。レスポンスもJSocketを使っていますのでmultipartに比べてboundary分お得だったりもします。テキストエリアに入力された文字がストリーミングで送信され、また他人のデータもストリーミングで受信できていると思います。ちなみに自分の発言もサーバから持ってきてるので一人でも確認できます。
ちなみにこれを1つのコネクションでやってしまおうというのがWebsocketなんだろうという認識ですね。ただwebsocketはhttpの上に一応のってますがハンドシェイク以外の部分はhttp/1.0やhttp/1.1的には正しくないでしょうし、JSocketでの二重接続であれば正しいhttpとしてふるまえるはずで、現行のapacheやproxy等でも扱える可能性があったりします。
あ、チャットのサンプルコードもgithubにあげてあります。
plackup -s Coro --app chat.psgi
という感じでPlack::Server::Coroをお使いください。
mod_psgi試してみた
- 2009/10/16 金曜日 18:17:20
- perl
mod_psgi をインストールしてみたをみて速くなるなら試してみようということでmod_psgiを試してみますた。
まずはこんな感じの簡単なPSGIアプリで。
my $app = sub { return ['200', [Content-Length => '5'], ['hello']]; };
ab -n 10000 -c 100 mod_psgi Requests per second: 1403.51 [#/sec] (mean) mod_perl Requests per second: 668.33 [#/sec] (mean) Standalone Requests per second: 702.46 [#/sec] (mean) Standalone::Prefork Requests per second: 725.78 [#/sec] (mean)
おおおお。超絶早いですね!
(plackupの際に-E product(development以外ならなんでもおk)をつけないとだいぶ遅くてそれをそのまま載せてたのを修正しました)
で、お次は、Catalyst::Engine::PSGIを使ってCatalystのhello worldなアプリを。
catalyst.pl Hello
で作って、debugモードを切って、Root.pmのindexで
$c->response->content_type('text/plain'); $c->response->body( 'hello' );
こんな感じにしたもの。
ab -n 1000 -c 10 mod_psgi Requests per second: 207.87 [#/sec] (mean) mod_perl Requests per second: 144.94 [#/sec] (mean) cat-standalone Requests per second: 184.95 [#/sec] (mean)
おおおおお。早いですね!!これはこれだけでも乗り換える意味がありそうだ。と思ってたんですが現在実運用中のCatalystアプリでやってみたところ”child pid 32320 exit signal Segmentation fault (11)”とかいって死にました。うーむ。これは再現する最小構成を探ってid:spiritlooseさんにフィードバックしたいところですね。
casual-perlerな人たちは今持ってるCatalystアプリをmod_psgi+Catalyst::Engine::PSGIで動かしてどんどんフィードバックするといいんじゃないかな!
Acme::Coro::Sukeをリリースしました
- 2009/10/12 月曜日 15:44:51
- perl
多分、5人以上の人が思いついたけどあまりのくだらなさに作成を断念したといううわさのAcme::Coro::Sukeを先ほどCPANにリリースしました。(githubにもあげてあります)
これは、Coroのasyncと基本的には同じ動作をするbenzoというブロック定義ができるようになるもので、benzoブロックにCoroがスレッドを切り替えるたびに、「うわぁ…べんぞうさんの中…すごくあったかいナリぃ… 」とコロちゃんが囁やいてくれるモジュールです。
一番簡単な使い方は以下のようになります。
use Coro; use Acme::Coro::Suke; benzo { }; cede;
enjoy Acme::Coro::Suke!
CPANに上げる三つめのモジュールがAcmeモジュールというのはこれはひどい。
Re: PSGI Implのsendfileについて
- 2009/10/7 水曜日 15:29:06
- perl
PSGI Implのsendfileについてですが、自分の今のところのイメージを書いておくです。
on Plack::Server
- $res->[2]がGLOBだったら fileno($res->[2])して sendfile に fd を渡す
- $res->[2]->can(‘fileno’) が生えてたら、$res->[2]->filenoからfdを取って使う
- $res->[2]->can(‘path’) が生えてたら、$res->[2]->pathからファイルパスを取って使う
$env->{psgix.sendfile}を使わない以外は一緒
on app
realfileをserveしたい時は
- GLOBを返す
- ->pathを生やしたIO-Handle-likeなオブジェクトを返す
の二種類の方法があって、後者のほうがあらゆるサーバで最適化される可能性がある。かといって前者だからといってクライアントに届くresponseが変わることはないと期待される。後者において->filenoの実体のファイルと->pathが違うものだった場合の動作は未定義。
on middleware
- Plack::Middleware::XSendfile
responseから->pathが取れる場合にはそれをヘッダのX-Sendfileにセットするようなmiddleware。これのpsgix.sendfileサポートを無くしたやつのイメージ。
X-Sendfileヘッダをセットする場合というのはbackendがlightyの場合とかだと思うけど、それをセットしていいかどうかはPlackは知り得ない。かといってappでセットしていて必要のない時に外にファイルPATHが出ていくものいくない。というわけでappでは->path付きオブジェクトを返すだけにして、このmiddlewareをbackendにあわせて付けたり外したりする。Plack::Server::*のsendfile(2)サポートとかとはまったく関係無い。 - Plack::Middleware::GuessPath
GLOBからファイルPathを推測して->path付きのオブジェクトに変換しちゃうMiddleware。マルチプラットフォーム対応が課題。Plack::Middleware::XSendfileより先に実行する。Plack::Server::*のsendfile(2)サポートとも関係する。
追記(10/7 17:24): 大体ここに書いてある感じで追加されたみたいです。詳しくは本家specのchangesetをご覧ください。Plack::Middleware::XSendfileも追加されたみたいです。miyagawaさん仕事ハヤス、、、。
ファイルPATHを覚えているfhを作成できるIO::File::WithPathをリリース
- 1:49:30
- perl
Plackのsendfileサポート関連を追いかけてて、Plack::Server::Apache2でsendfileサポートされてない理由がfhからファイル名を取るベストな方法がないというわけで、gist: 200797みたいなパッチを書いて#http-engineとかに張り付けたけどそれlinuxでしか動かないよねみたいなことで日本の恥を晒してしまったりしてたわけですが、その中でIO::File::WithPathみたいなのがあればいいよねと話がでていたので作ってみました。
使い方はこんな感じ。
my $fh = IO::File::WithPath->new('/path/to/file'); print $fh->path; # /path/to/fileがとれるよ print $fh->getline; # IO::Handleとしても扱える print <$fh>; # もちろんGLOBとしても
Plackのappでは
return ['200', [], IO::File::WithPath->new('/path/to/file')];
みたいな使い方を想定していますが、Plack::Server側はこのモジュールを使うことが前提というわけではなくて、duck typingで->pathがあるオブジェクトであればそのpathを(使える条件であれば)使うようになる予定だと思います。
あと、純粋なfhからpathを取るマルチプラットフォーム対応なモジュールもできれば欲しいよねというところ。windowsはかなり無理っぽい。
Plack::Requestからのhostのとりかた
- 2009/9/30 水曜日 21:42:21
- perl
Plack::Requestにhost無いなぁ。と思って勢い余ってforkしてコミットまでしてしまったのですが、#perl-casual@freenodeで呟いたところyappoさんから
$req->uri->host
もしくはURIオブジェクトの作成コストが気になるなら($req->uriは遅延作成なので)
$req->env->{HTTP_HOST}
でいいじゃんと言われました。確かにその通りですね。
Wassrのyapcasia2009チャンネルの発言をIRCに投稿するボットをYAPC::Asiaの二日目向けに作った
- 2009/9/10 木曜日 23:47:54
- perl
twitterの#yapcasia2009ハッシュタグがスクリーンに晒されるのが個人的に非常にツボだったので、wassrのyapcasia2009チャンネルに発言するとirc.freenode.orgの#yapc.asia-jaに投稿するボットも作ってみました。
wassrにはstreaming APIはないようなので5秒ごとにpollingしちゃってます。いいんでしょうか。
参考文献(つうかほぼパクリ):
Twitterのハッシュタグ付き発言をIRCに投稿するボットをYAPC::Asia向けに作った
以下コード
#!/usr/bin/perl use strict; use warnings; use AnyEvent::IRC::Client; use Net::Wassr; use Encode (); use Storable; my $channel = '#yapc.asia-ja'; my $interval = 5; my $wassr_channel = 'yapcasia2009'; my $wassr = Net::Wassr->new( user => 'nihen', passwd => '*****', ); my $cv = AnyEvent->condvar; my $pc = AnyEvent::IRC::Client->new; my $send_message = -e 'send_message' ? retrieve('send_message') : {}; $SIG{INT} = $SIG{TERM} = sub { $pc->disconnect('bye'); store $send_message, 'send_message'; exit; }; $pc->reg_cb( connect => sub { my ( $pc, $err ) = @_; if ( defined $err ) { warn $err; return; } }, registered => sub { my ( $self ) = @_; print "registerd!\n"; $pc->enable_ping(60); }, disconnect => sub { print "disconnected: $_[1]!\n"; } ); $pc->send_srv('JOIN', $channel); $pc->send_chan($channel, 'NOTICE', $channel, 'hi'); $pc->connect('irc.freenode.org', 6667, { nick => 'wassr_bot', user => 'wassr_bot', real => 'wassr_bot', }); my $w = AnyEvent->timer(after => $interval, interval => $interval, cb => sub { my $time_line = $wassr->channel_timeline('name_en=' . $wassr_channel); if ( !$time_line || ref $time_line ne 'ARRAY' ) { return; } foreach my $message ( @{$time_line} ) { next if $send_message->{$message->{rid}}; $send_message->{$message->{rid}} = 1; $pc->send_chan($channel, 'NOTICE', $channel, Encode::encode('utf-8', $message->{user}->{login_id} . ': ' . $message->{body})); } }); $cv->wait;
ホーム > perl
- 検索
- フィード
- メタ情報