Converteren van Modperl config naar Plack - verschillende handlers uitvoeren op bestandsextensie

Hiermee probeer ik mijn huidige Apache/Modperl-site naar Starman over te zetten en moet app.psgi met verschillende handlers voor verschillende bestandsextensies worden gebouwd. Iets als in de Apache:


     SetHandler              perl-script
     PerlHandler             MyApp::Mhandler



     SetHandler              perl-script
     PerlHandler             MyApp::Phandler

Nu heb ik:

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

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

maar hoe de bouwer te gebruiken?

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
};

Benodigde "regels":

  • if the request does not have any extension, or the request ends with '/'
    • should be handled with $Mapp
  • if the request ends with some extension, then
    • .m and .mh should be handled by $Mapp
    • .p and .ph should be handled by $Papp
    • all other files with extensions (like .css .js .pdf .jpg ...) should be handled as static.

Natuurlijk, het zal veel gemakkelijker zijn om elk statisch bestand in een of andere boom te plaatsen, maar de huidige app is gegeven en nu wil ik hem alleen maar naar Startman verplaatsen, refactoren - later.

6

1 antwoord

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'
2
toegevoegd
huh! Gaan proberen dit te begrijpen. :)
toegevoegd de auteur kobame, de bron
maar ja! De hoofdtruc is het gebruik van een "sub" in het pad voor de statische en het groeperen van twee apps in één voor beslissing. Trouwens, nog nooit een Tie gebruikt ..;) THANX veel !!! :)
toegevoegd de auteur kobame, de bron