pluginにおけるcookieの扱い方を考える

blosxomのプラグインを作っていて、cookieの扱いについて思いついたことを。

blosxomには、HTTPレスポンスヘッダを構成するための $blosxom::header というグローバル変数があります。これはハッシュリファレンスであり、最終的にはこれの値がCGIモジュールのheaderサブルーチンに渡され、HTTPヘッダとして整形されることになります。

なので、blosxomプラグインでcookieを追加する場合には、

  1. CGIモジュールのcookieサブルーチンで、CGI::Cookieオブジェクトを作成する。
  2. それを $blosxom::header->{'-cookie'} へ代入する。

という感じでうまく行きそうに思えます。

しかし複数のプラグインでcookieを扱っているものがあった場合、各プラグインがこの方法を採っていると、前に実行されたプラグインが追加したcookieを、後に実行されたプラグインが上書き消去してしまう場合があることに気づきました。

そこでCGIモジュールで複数のcookieを追加するためにはどうすればよいものかとperldoc CGI(日本語訳)を更に読むことになった訳ですが、今後cookieを使ったプラグインを作った時にこの辺りをいちいち参照しなくてもよいよう、以下のようなサブルーチンを作ってみました。

sub add_cookie {
  my $new_cookie = (ref($_[0]) eq 'CGI::Cookie') ? $_[0] : cookie(@_);
  my $old_cookie = $blosxom::header->{'-cookie'};
  if (!$old_cookie) {
    $blosxom::header->{'-cookie'} = $new_cookie;
  } elsif (ref($old_cookie) eq 'CGI::Cookie') {
    $blosxom::header->{'-cookie'} = [$old_cookie, $new_cookie];
  } elsif (ref($old_cookie) eq 'ARRAY') {
    push(@$old_cookie, $new_cookie);
  }
}

引数はCGI::Cookieオブジェクト、またはcookieのパラメタ名と値を並べたリストです。例えば以下のような感じで。詳しくはperldoc CGI(日本語訳)を参照のこと。

use CGI qw(:standard);

# CGI::Cookieオブジェクトを追加

$cookie = cookie( ... );
&add_cookie($cookie);

# リストを使って追加

&add_cookie(
  -name    => 'sessionID',
  -value   => 'xyzzy',
  -expires => '+1h',
  -path    => '/cgi-bin/database',
  -domain  => '.capricorn.org',
  -secure  => 1,
);

で、cookieを扱う各プラグインでこのadd_cookieサブルーチンを持つようにして、これを通してcookieを追加するようにすれば、他のプラグインが追加したcookieを上書きしてしまうこともなくなるだろうと考えたのでした。

* * *

というかこのようなことはきっと既に誰かが考えているに違いない訳で、本家サイトにも登録されているcookiesプラグインは正にそのような用途のためのものなのでしょう。しかしながらこのようなメタなプラグイン(プラグインを動かすためのプラグイン)を導入するのには好き嫌いが分かれそうな気もするので、自前で何とかしつつ、なるべく他に迷惑をかけないようにするための解決法としては、前記のようなサブルーチンを使うのもありではないかと考えたのですが、いかがでしょう。