2012-06-24 2 views
6

저는 현재 Apache/Modperl 사이트를 Starman으로 이전하려고합니다. 다른 파일 확장명에 대해 다른 핸들러로 app.psgi를 빌드해야합니다. 뭔가를해야만 아파치 같이 : 이제Modperl 설정을 Plack으로 변환 - 파일 확장자별로 다른 핸들러를 실행합니다.

<LocationMatch "(\.m|\.mh|\/)$"> 
    SetHandler    perl-script 
    PerlHandler    MyApp::Mhandler 
</LocationMatch> 

<LocationMatch "(\.p|\.ph)$"> 
    SetHandler    perl-script 
    PerlHandler    MyApp::Phandler 
</LocationMatch> 

내가 가진 :

#app for handle .m and .mh 
my $Mapp = Some::PSGI->handler(sub { 
... 
}); 

#app for handling .p and .ph 
my $Papp = SomeOther::PSGI->handler(sub { 
... 
}); 

하지만 어떻게 빌더를 사용하는 방법?

builder { 

    #any extension what is not .m .mh .p .ph - handle as static 
    #but, only when the request have any extension 
    enable "Plack::Middleware::Static", 
     path => __what here__, ??? 
     root => "/my/doc/root"; 

    #and what here to achieve the following "rules". 

    #??? $Papp 
    #default $Mapp 
}; 

필요 "규칙"

  • 는는 확장자가없는 요청 가없는 경우, 또는 요청은 '/'로 끝나는
    • $Mapp
  • 으로 취급한다
  • 요청이 일부 확장자로 끝나는 경우
    • .m.mh$Mapp
    • .p.ph에 의해 처리되어야한다 (.CSS의 .js .PDF .JPG처럼 ...) 정적으로 처리되어야 확장을 $Papp
    • 다른 모든 파일을 처리해야한다. 물론

, 일부 나무에 모든 정적 파일을 넣어 훨씬 쉽게 수 있지만 리팩토링, 현재 응용 프로그램 주어진이며, 지금은 Startman로 이동합니다 - 이상.

답변

2
use strictures; 
use Plack::Request qw(); 
use Plack::Builder qw(builder enable); 
use Tie::REHash do_cache => 1; 

tie my %location_match, 'Tie::REHash'; 
%location_match = (
    qr'(\.m|\.mh|/|/[^.]+)$' => sub {[200,[],['Mhandler']]}, 
    qr'(\.p|\.ph)$'   => sub {[200,[],['Phandler']]}, 
); 

my $app = sub { 
    my ($env) = @_; 
    my $req = Plack::Request->new($env); 
    my $res; 
    if ($location_match{$req->path_info}) { 
     printf "path [%s] dispatches to %s\n", $req->path_info, $location_match{$req->path_info}; 
     $res = $location_match{$req->path_info}; 
    } else { 
     die sprintf "no match for path [%s], check routing configuration\n", $req->path_info; 
    } 
    return $res->($env); 
}; 

builder { 
    enable 'Static', path => sub { 
     my ($path) = @_; 
     if ($location_match{$path}) { 
      print "redispatch\n"; 
      return; 
     } elsif ($path =~ qr'/ [^/]+ [.] [^/]+ $'x) { 
      return 1; 
     } else { 
      die "no match for path [$path], check routing configuration\n"; 
     } 
    }, root => './htdocs/'; 
    $app; 
} 

__END__ 
GET 'http://localhost:5000/foo?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo/?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.m?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.mh?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.p?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.ph?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.css?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.js?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.pdf?bar=baz;quux#fnord' 
GET 'http://localhost:5000/foo.jpg?bar=baz;quux#fnord' 
+0

허! 이것을 이해하려고 노력합니다. :) – kobame

+0

하지만 예! 주된 트릭은 Static의 경로에 "sub"를 사용하고 두 개의 앱을 하나로 묶어 결정합니다. BTW, 결코 아직 어떤 넥타이도 사용하지 않았다.;) THANX a lot !!! :) – kobame