Converting Modperl config to Plack - running different handlers by file extension

StackOverflow https://stackoverflow.com/questions/11176786

  •  16-06-2021
  •  | 
  •  

Question

This I'm trying for transfer my current Apache/Modperl site to Starman, and need build app.psgi with different handlers for different file extensions. Somthing as in the Apache:

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

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

Now I have:

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

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

but how to use the builder?

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

Needed "rules":

  • 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.

Sure, will be much easier put every static file into some tree, but the current app is given and now i only want move it into Startman, refactoring - later.

Was it helpful?

Solution

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'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top