I'd really like to be able to do something like this --- >8 --- package MyApp; use MyApp::Secret; prefix 'undef'; before sub { # do something }; package MyApp::Secret; prefix '/secret'; before sub { return unless auth && auth->is_admin; } 1; --- >8 --- Rather than having to have the before sub in the main MyApp do all my auth work (or conditionally load resources or whatever). However at the moment *all* before subs get run no matter what the route is - if I put some warns in the before subs for MyApp and MyApp::Secret I get [78776] core @0.000241> request: GET / from 127.0.0.1 in /Library/Perl/5.10.0/Dancer/Handler.pm l. 51 In the before for MyApp::Secret at lib/MyApp/Secret.pm line 8, <DATA> line 16. In the before for MyApp at lib/MyApp.pm line 9, <DATA> line 16. [78776] core @0.000302> request: GET /secret from 127.0.0.1 in /Library/Perl/5.10.0/Dancer/Handler.pm l. 51 In the before for MyApp::Secret at lib/MyApp/Secret.pm line 8, <DATA> line 16. In the before for MyApp at lib/MyApp.pm line 9, <DATA> line 16. Perhaps a new method called before_prefix (and before_template_prefix) or something to maintain backwards compatibility?
On Mon, 2011-03-28 at 20:51 +0100, Simon Wistow wrote:
I'd really like to be able to do something like this
--- >8 ---
package MyApp;
use MyApp::Secret;
prefix 'undef';
before sub { # do something };
package MyApp::Secret;
prefix '/secret';
before sub { return unless auth && auth->is_admin; }
1;
--- >8 ---
Rather than having to have the before sub in the main MyApp do all my auth work (or conditionally load resources or whatever).
However at the moment *all* before subs get run no matter what the route is
That's by design, but the before filter can always inplement whatever logic it wants, e.g.: before sub { if (request->{path} =~ m{^/secret} && !auth || !auth->is_admin) { redirect '/login'; } }; We could perhaps add the ability to pass options to 'before', e.g.: before { path => m{^/secret} } => sub { ... }; (or reversed, before sub { ....} { path ... }; ) However, we'd be getting close to 'before' just being used as another way to declare route handlers. In fact, you could use a route for this, e.g.: prefix '/secret'; any qr{.*} => sub { redirect '/login' if !auth || !auth->is_admin; pass; # continue on to the next route which matches }; get '/foo' => sub { "Foo!" }; ... that should cause all requests for anything under that prefix to hit that first route, which will either redirect to login, or pass(), causing execution to continue on to the next route which matches the request. Cheers Dave P -- David Precious ("bigpresh") http://www.preshweb.co.uk/ "Programming is like sex. One mistake and you have to support it for the rest of your life". (Michael Sinz)
On Mon, Mar 28, 2011 at 10:38:56PM +0100, David Precious said:
That's by design, but the before filter can always inplement whatever logic it wants, e.g.:
before sub { if (request->{path} =~ m{^/secret} && !auth || !auth->is_admin) { redirect '/login'; } };
That's what I currently do - and it's kind of ugly. I'd much rather that I could separate that code out into the different sub modules.
In fact, you could use a route for this, e.g.:
prefix '/secret'; any qr{.*} => sub { redirect '/login' if !auth || !auth->is_admin; pass; # continue on to the next route which matches };
get '/foo' => sub { "Foo!" };
Hmm, yes - that would work. It still feels a little kludgy though. Also, how performant is that versus having a new type of begin?
On 28/03/11 22:38, David Precious wrote:
On Mon, 2011-03-28 at 20:51 +0100, Simon Wistow wrote:
I'd really like to be able to do something like this
package MyApp;
use MyApp::Secret;
prefix 'undef';
before sub { # do something };
package MyApp::Secret;
prefix '/secret';
before sub { return unless auth&& auth->is_admin; }
I've tried to do something similar to Simon too and been disappointed. I was trying: load_app 'MyApp::Secret', prefix =>'/secret', before => &admin_only; I think the surprising thing is the fact that "before" spans packages. Within a package, I'm happy with multiple occurrences chaining, but it seems wrong for an included module to change global behaviour. -- Richard Huxton Archonet Ltd
On 1-04-2011 at 10:21, Richard Huxton wrote:
I've tried to do something similar to Simon too and been disappointed. I was trying:
load_app 'MyApp::Secret', prefix =>'/secret', before => &admin_only;
I think the surprising thing is the fact that "before" spans packages. Within a package, I'm happy with multiple occurrences chaining, but it seems wrong for an included module to change global behaviour.
You're close. This will work as you need: package MyApp; before sub { ... }; # do something package MyApp::Secret; before sub { ... }; # do something else package main; load_app 'MyApp'; load_app 'MyApp::Secret', prefix => '/secret'; 'before' hooks are scoped to a single Dancer app. Note that splitting your application in packages is not sufficient to have Dancer see them as different 'apps': you have to load them using load_app(). Everything (well, almost) that happens during that load_app() call is scoped to that particular app and not to the global application. Note that while this works correctly for the example you provided, there are some issues that you may be interested in: https://github.com/sukria/Dancer/issues/421 https://github.com/sukria/Dancer/issues/425 https://github.com/sukria/Dancer/issues/429 Cheers, - al.
On 01/04/11 09:38, Alessandro Ranellucci wrote:
On 1-04-2011 at 10:21, Richard Huxton wrote:
'before' hooks are scoped to a single Dancer app. Note that splitting your application in packages is not sufficient to have Dancer see them as different 'apps': you have to load them using load_app(). Everything (well, almost) that happens during that load_app() call is scoped to that particular app and not to the global application.
Aha! That's the missing bit of the puzzle.
Note that while this works correctly for the example you provided, there are some issues that you may be interested in:
https://github.com/sukria/Dancer/issues/421 https://github.com/sukria/Dancer/issues/425 https://github.com/sukria/Dancer/issues/429
Thanks a lot -- Richard Huxton Archonet Ltd
participants (4)
-
Alessandro Ranellucci -
David Precious -
Richard Huxton -
Simon Wistow