ブログトップ 記事一覧 ログイン 無料ブログ開設

刺身☆ブーメランのはてなダイアリー

2005/09/16(Fri) 「Perl救命病棟」を読んだ

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()の発案者であるかぜぶろさん、いかがでしょう?

kazeburokazeburo 2005/09/16 19:42
$self->redirect(”http://example.com/example.cgi/module/mode?key=value”);

$self->redirect(
-uri=>”http://example.com/example.cgi”,
-path_info=>”/module/mode”,-query_string=>”key=value”
);
の様に書けるようになって
$self->redirect(
-path_info=>”/module/mode”
);
これだけで動いたら分かりやすいかなぁ。

a666666a666666 2005/09/18 00:16 コメントありがとうございます!
なるほど、-uri => ’http://www.yahoo.com/’ などのときは外部へそのままリダイレクト、 -path_info => ’/module/mode’;のみの形ならばbase uriは補完してやる、なんてすると親切ですね。
あと自分で書いたのを使って気づいたんですが、パスをあわせるためだけに同じモードをもう一度呼ぶのならGETやPOSTで送られたクエリーもあわせておくってやるべきだよなあ、なんてことも考えました。

そのへんもうちょっとよく考えて、それなりにちゃんと動くものができたら、Redirectモジュールの作者にメールしてみようと思います。ありがとうございました!

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/a666666/20050916/1126852039