PrePAN

Sign in to PrePAN

Plack::App::URLMux PSGI/Plack component for dispatching multiple applications based on URL path and patterns

Good

Synopsis

use strict;
use Plack::App::URLMux;
use Plack::Test;
use HTTP::Request::Common;

sub appN {
    my $app = shift;
    return sub {
        my $env = shift;
        my %params = @{$env->{'plack.urlmux.params.url'}};
        my $name = $params{name} ||= [];
        my $test = $params{test} ||= [];
        my $body = join " | ", 'app='.$app, "name=@$name,test=@$test", "script=$env->{SCRIPT_NAME}", "path=$env->{PATH_INFO}";
        return [ 200, [ 'Content-Type' => 'text/plain' ], [ $body ] ];
    }
};

my $app = Plack::App::URLMux->new;
$app->map("/" => appN('app1'));
$app->map("/:name*" => appN('app2'));
$app->map("/:name+/foo" => appN('app3'));
$app->map("/foobar/:name+" => appN('app4'));
$app->map("http://bar.example.com/:name*" => appN('app5'));
$app->map("/:name*/bar/:test*" => appN('app6'));
$app->map("/foo/:name{2,}" => appN('app7'));
$app->map("/foo/:name{2,3}" => appN('app8'));
$app->map("/foo/:name{1,4}" => appN('app9'));

test_psgi app => $app, client => sub {
    my $cb = shift;
    my $res;
    $res = $cb->(GET "http://localhost/foo/name1/name2");
    lg "res ".$res->content();
};

Description

The module is designed for multiplexing applications by URL path and patterns. This module is based on Plack::App::URLMap, but it optimized to dispatching a lot of URLs without performance regression. Additionally this module provide the ability to assign routing rules using URL patterns with named parameters. The format of parameter consist of ':' followed by parameter name and quantifier which is the same as for regexp expressions.

The idea was in that URL in RFC1738 for HTTP defined as hierarchical resource locator with '/' as delimeter and the package splits url-path on this parts, searches the application by them in mapped search tree and fills the matched named patters. This module defines value of a named parameter as one o more parts of the url-path (hsegment in RFC terms) in array context and returns list of matched parameters in PSGI/Plack environment 'plack.urlmux,params.url' as array of name and value pairs.

The namespace for Plack additional modules can be used for components as Plack::App and for middleware as Plack::Middleware, so I have chosen the Plack::App::URLMux name. I send a email to author of Plack modules about naming the module and did not receive feedback, so I decide to write about the package here.

I don`t like the idea to implement a URL multiplexer as regexp expression URL parser as in (Python dispatcher)[https://docs.djangoproject.com/en/1.11/topics/http/urls/#example] for example, due its performance issues for a lot of URL rules. This module solves the performance problem by simplify the regexp expressions to named patterns and operates more larger constructions - url-path segments.

Any suggestions, comments and criticism are welcome.

Comments

Please sign up to post a review.