[Dancer-users] Dancer - new suggestion - "route namespace"
Perlover
perlover at perlover.com
Wed Nov 23 11:08:28 CET 2011
Good day!
Does anybody have thoughts about this idea? :)
Best regards, Perlover
2011/11/20 Perlover <perlover at perlover.com>:
> Good day!
>
> I found a buggy behavior of Dancer with multiply application
> configuration and routes.
>
> Please to see example in current Dancer::Deployment -> Running
> multiple apps with Plack::Builder
>
> [...]
> builder {
> mount "/app1" => builder {$app1};
> mount "/app2" => builder {$app2};
> };
>
> Here 'mount' through Plack::App::URLMap->map will call our $app1 &
> $app2 BUT /app1 & /app2 will be removed from $request->path_info!
>
> Our applications will get a new path_info paths. Imagine a following example:
> builder {
> mount "/app1" => builder {$app1};
> mount "/app2" => builder { enable "Auth::Basic",
> authenticator => \&authen_cb; $app2};
> };
>
> Here $app2 is protected by Plack::Middleware::Auth::Basic and it has
> some /admin/* routes (for /app2/admin/... urls)
> But $app has only one root routes for example as '/' (and may be other routes)
>
> Now please to see the source of module Dancer::App, lines 104-106:
>
> ....
> sub find_route_through_apps {
> my ($class, $request) = @_;
> for my $app (Dancer::App->current, Dancer::App->applications) {
> my $route = $app->find_route($request);
> ....
>
>
> Here we see that searching is going until the target route will be
> found in all applications!
> Imagine that we requested the url /app1/admin/... What happens?
> The $app1 will get path_info as /admin/... after Plack::App::URLMap
> and Dancer will start a searching in find_route_through_apps and will
> find a route of $app2!
> And it will call it code without middleware Auth! And protected and
> security data will be given for remote user without protection!
>
> What is result? The /app1/ URLs will sometimes run app2's routes, the
> /app2/ URLs will sometimes run a routes of app1 and so on.
> And in above example we will get a security hole additional...
>
> ---------------------------------------
>
> What i suggest ?
>
> I think Dancer should have:
>
> 1) For get & post now we can pass an options hashref before code like
> this get '/' => {option1 =>..., ...}, sub {} (i see this in code of
> Dancer but i didn't find it in docs) . I think there should be option
> 'route_namespace' for example. If it defined it consists a namespace
> of this route. If not defined it has a namespace defined in
> route_namespace command (point 2 here)
>
> 2) Should be command like 'prefix' but named as 'route_namespace' fro
> setting up namespace of routes of this application. The prefix option
> for real pieces in $request->path_info but this route_namespace for
> virtual because we cannot get a namespace from path_info (only from
> $request->script_name but i want to make this behavior flexible for
> 'route_namespace')
>
> 3) I think the object Dancer::Request should have a method
> (getter/setter) route_namespace. Through this method we can setup a
> namespace of current request for searching of routes. If we set up for
> example $request->route_namespace('app1') before
> Dancer->dance($request) (example in Dancer::Deployment -> Running
> multiple apps with Plack::Builder) for example then the
> find_route_through_apps should search through all applications all
> routes BUT with same namespace only. If route_namespace is not defined
> for current $request a behavior is as now (backward compatible)
>
> So after this patches our example in Dancer::Deployment will look like:
>
> use Dancer ':syntax';
> use Plack::Builder;
>
> setting apphandler => 'PSGI';
>
> my $app1 = sub {
> my $env = shift;
> local $ENV{DANCER_APPDIR} = '/Users/franck/tmp/app1';
>
> load_app "app1"; # In the app1 module we have command:
> route_namespace "app1" before routes
> # May be here we should be
> able to setup too like: load_app "app1", route_namespace => 'app1';
>
> Dancer::App->set_running_app('app1');
> setting appdir => '/Users/franck/tmp/app1';
> Dancer::Config->load;
>
> my $request = Dancer::Request->new( env => $env
> )->route_namespace('app1'); # route_namespace as setter returns an
> instance of Dancer::Request
>
> Dancer->dance($request); # Now the Dancer knows in the
> find_route_through_apps what we want (only routes from "app1"
> namespace)
> };
>
> my $app2 = sub {
> my $env = shift;
> local $ENV{DANCER_APPDIR} = '/Users/franck/tmp/app2';
>
> load_app "app2"; # In the app2 module we have command:
> route_namespace "app2" before routes
>
> Dancer::App->set_running_app('app2');
> setting appdir => '/Users/franck/tmp/app2';
> Dancer::Config->load;
>
> my $request = Dancer::Request->new( env => $env
> )->route_namespace('app2'); # route_namespace as setter returns an
> instance of Dancer::Request;
>
> Dancer->dance($request); # Now the Dancer knows in the
> find_route_through_apps what we want (only routes from "app2"
> namespace)
> };
>
> builder {
> mount "/app1" => builder {$app1};
> mount "/app2" => builder { enable "Auth::Basic",
> authenticator => \&authen_cb; $app2};
> };
>
> Your opinions?
>
> I can make all this patches in Dancer for devel branch at github
> But before i want to listen from you some suggestions and opinions
>
> Thanks!
> Perlover
>
More information about the Dancer-users
mailing list