Catalyst::Request#pathの値に、LocationMatchでマッチした文字列がくっつく(3)

Catalyst::Request#pathの値に、LocationMatchでマッチした文字列がくっつく - ヒルズで働く@robarioの技ログ
Catalyst::Request#pathの値に、LocationMatchでマッチした文字列がくっつく(2) - ヒルズで働く@robarioの技ログ
というわけで、Catalystにパッチを当ててみる試み。

Root.pmのdefaultハンドラを以下のようにして、

sub default : Private {
    my ( $self, $c ) = @_;

    my $content = sprintf
      <<EOF, $c->req->path, ( join ', ', @{ $c->req->arguments } ), $c->req->base;
path = %s
arguments = %s
base = %s
EOF
    $c->res->content_type('text/plain');
    $c->res->body($content);
}

Locationディレクティブの値が異なる2種類のhttpd.confを用意して

PerlModule MyApp
<LocationMatch "/">
  SetHandler modperl
  PerlResponseHandler MyApp
</LocationMatch>
PerlModule MyApp
<LocationMatch "^/.*$">
  SetHandler modperl
  PerlResponseHandler MyApp
</LocationMatch>

http://localhost:3000/abc/def/ghiにアクセスする実験をしました。

パッチを当てていない状態

Locationディレクティブの設定が"/"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/
Locationディレクティブの設定が"^/.*$"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/%5E/.*$/

baseの値が変になりました。「変」と言っても、Catalyst的には合っているのかも。

パッチを当てた状態

Apache2::RequestUtil#locationの代わりにApache2::RequestRec#path_infoを使うようにしてみます。
% diff -Nau Apache.pm.orig Apache.pm

--- Apache.pm.orig      2006-10-28 12:39:47.079233600 +0900
+++ Apache.pm   2006-10-28 12:39:54.570004800 +0900
@@ -92,7 +92,7 @@
     my $base_path = q{};

     # Are we running in a non-root Location block?
-    my $location = $self->apache->location;
+    my $location = $self->apache->path_info;
     if ( $location && $location ne '/' ) {
         $base_path = $location;
     }
Locationディレクティブの設定が"/"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/abc/def/ghi/
Locationディレクティブの設定が"^/.*$"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/abc/def/ghi/

どちらもbaseが一致するようになりました。


何かがおかしい。。。

うーん。Catalyst的にはこれらのbaseは一致しちゃったらダメな気がする。Locationでの設定値がbaseに反映されるようにしたいんじゃないかな。ってことでパッチを変更。
% diff -Nau Apache.pm.orig Apache.pm

--- Apache.pm.orig      2006-10-28 12:39:47.079233600 +0900
+++ Apache.pm   2006-10-28 12:52:07.864430400 +0900
@@ -94,7 +94,7 @@
     # Are we running in a non-root Location block?
     my $location = $self->apache->location;
     if ( $location && $location ne '/' ) {
-        $base_path = $location;
+        $base_path = $self->apache->path_info;
     }

     # Are we an Apache::Registry script? Why anyone would ever want to run
Locationディレクティブの設定が"/"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/
Locationディレクティブの設定が"^/.*$"の場合
path = abc/def/ghi
arguments = abc, def, ghi
base = http://localhost:3000/abc/def/ghi/

うーん。これでいいんじゃね?と思ったんだけど、baseにabc/def/ghiが含まれているのにpathがabc/def/ghiなのはおかしい。
ん〜何か分かってきたぞ。
Locationに設定された部分は、Catalystが関知しない領域として扱いたいらしい。なので、

<LocationMatch "/abc">

とすると

path = def/ghi
arguments = ghi
base = http://localhost:3000/abc/

となる。Locationディレクティブの"/abc"を"^/[^/]+"に変えたときに同じ挙動になるためには、
% diff -Nau Apache.pm.orig Apache.pm

--- Apache.pm.orig      2006-10-28 12:39:47.079233600 +0900
+++ Apache.pm   2006-10-28 18:53:32.058046400 +0900
@@ -94,7 +94,8 @@
     # Are we running in a non-root Location block?
     my $location = $self->apache->location;
     if ( $location && $location ne '/' ) {
-        $base_path = $location;
+        $self->apache->path_info =~ m/$location/msx;
+        $base_path = $&;
     }

     # Are we an Apache::Registry script? Why anyone would ever want to run

とすれば良さげ。
Catalystの中の人にパッチ投げて感想聞いてみよう。