@kyanny's blog

私は天才ではありません。ただ、人より長く一つの事と付き合っていただけです - アインシュタイン

CGI::Application::Plugin::Redirectのredirect()メソッドを改造してみた

おまえのログ/CGI::Application::Dispatch勉強中その2をうけたblog.nomadscafe.jp/PATH_INFOと相対パス(リンク)でのredirect_dispatch()に対して、「CGI::Appliction::Plugin::Dispatchというモジュールが出たからそれを利用できないだろうか」というエントリを起こそうとおもっていた。おもっていたらかぜぶろさんが先にDispatchモジュールに言及されていたのだが、せっかくなのでかぜぶろさんが先のエントリで実装したredirect_dispatch()メソッドとCGI::Application::Plugin::Redirectモジュールのredirect()メソッドのいいとこどりをしてあわせ技一本を狙ってみた。

以下のディレクトリ構成で、http://hogehoge/app.cgiにアクセスすると、自動的にhttp://hogehoge/app.cgi/index/indexというURIにリダイレクトされる。一応ソースコードの詰め合わせはここにおいておく。


~/app.cgi -- インスタンス・スクリプト
~/lib -- MyApp.pm -- CGI::Applicationを継承したベースクラス
|- Index.pm -- app.cgi/index/index用のクラス
|- Redirect.pm -- CGI::Application::Plugin::Redirectに独自のメソッドを付け足したもの
~/tmpl -- index.tmpl -- テンプレートファイル

以下がコード。長いので、redirect_dispatch()とは無関係なapp.cgiとMyApp.pm、テンプレートのindex.tmplは掲載しない。また、Redirect.pmから大元のredirect()メソッドも消しておいた。
Index.pm


package MyApp::Index;
use strict;
use warnings;
use base qw(MyApp);

sub setup
{
my $self = shift;
$self->start_mode('index');
$self->run_modes(
index => 'do_index',
);
}

sub do_index
{
my $self = shift;
$self->redirect_dispatch('index/index');

my $tmpl = $self->load_tmpl('index.html');
return $tmpl->output;
}

1;

Redirect.pm

package MyApp::Redirect;

use strict;
use vars qw($VERSION @EXPORT);

$VERSION = 0.10;

require Exporter;

@EXPORT = qw(
redirect
redirect_dispatch
);

sub import { goto &Exporter::import }

# redirect_dispatch(): accept module/mode location parameter and redirect URI like this: http://path/to/script/module/mode
sub redirect_dispatch {
my $self = shift;
# $location must be these format: module/mode or /module/mode
my $location = shift;
eval {
$self->run_modes( dummy_redirect => sub { } );
$self->prerun_mode('dummy_redirect');
};
unless($self->query->path_info =~ m{^/.+/.+$})
{
my $script_name = $self->query->script_name;
my $uri = ($location =~ m{^/}) ? $script_name . $location
: $script_name . "/" . $location;
$self->header_add( -location => $uri );
$self->header_type('redirect');
}

return;
}

1;
__END__

長ったらしいわりにやってることはたいしたことがない(速度とか効率とか想定外)のだが、もうちょっと上手に作ってあげて、redirect()メソッドだけで外部URIへのリダイレクトなのかパス整形のためのリダイレクトなのかまで判断できるようになれば、割と使いでのあるモジュールになってくれるのではないだろうか?

ということでこのアイデアをCGI::Application::Plugin::Redirectの作者氏に提案してみたらどうだろうかと考えているのだが、redirect_dispatch()の発案者であるかぜぶろさん、いかがでしょう?