Before Hook hit multiple times.
Hi, I put a simple test in my before hook: hook 'before' => sub { debug "Before Hook"; }; and a couple of quick routes: #Home Page get '/' => sub { template 'index'; }; #About Us page get '/about-us' => sub { template 'about-us'; }; (I am also using Auth::Extensible) Whenever I hit the home page, I get 3 debug messages in a row in the log. Whenever I hit the about-up page, I get 2 debug messages in a row in the log. I thought that any kind of page hook would only be called once. Does anybody know why the before hook would ever be called more than once? Rick
Hello, First of all, how are you doing your hits? If you use a browser, like Firefox, chances are that it will request favicon.ico at each requests, hence you'll see at least 2 hits. Also, it's possible that a HEAD request is done before the real GET request, depends on the browser. For testing purposes, I strongly sugesst using curl to send exactly one request: $ curl -i http://0:3000/some_route Cheers, 2013/1/2 Rick Bragg <rbragg@gmnet.net>
Hi,
I put a simple test in my before hook:
hook 'before' => sub { debug "Before Hook"; };
and a couple of quick routes:
#Home Page get '/' => sub { template 'index'; };
#About Us page get '/about-us' => sub { template 'about-us'; };
(I am also using Auth::Extensible)
Whenever I hit the home page, I get 3 debug messages in a row in the log. Whenever I hit the about-up page, I get 2 debug messages in a row in the log.
I thought that any kind of page hook would only be called once. Does anybody know why the before hook would ever be called more than once?
Rick
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Hi, Is it OK to top-post in this list? anyway, I hit the site using chrome. I think that's really weird to call the before hook a bunch of times depending on the browser. Does that mean it will call the before hook for every resource on every page? That's useless. I would expect that all hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page? Rick
Hello,
First of all, how are you doing your hits? If you use a browser, like Firefox, chances are that it will request favicon.ico at each requests, hence you'll see at least 2 hits.
Also, it's possible that a HEAD request is done before the real GET request, depends on the browser.
For testing purposes, I strongly sugesst using curl to send exactly one request:
$ curl -i http://0:3000/some_route
Cheers,
2013/1/2 Rick Bragg <rbragg@gmnet.net>
Hi,
I put a simple test in my before hook:
hook 'before' => sub { debug "Before Hook"; };
and a couple of quick routes:
#Home Page get '/' => sub { template 'index'; };
#About Us page get '/about-us' => sub { template 'about-us'; };
(I am also using Auth::Extensible)
Whenever I hit the home page, I get 3 debug messages in a row in the log. Whenever I hit the about-up page, I get 2 debug messages in a row in the log.
I thought that any kind of page hook would only be called once. Does anybody know why the before hook would ever be called more than once?
Rick
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests. The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook. David
On Jan 2, 2013, at 2:27 PM, David Golden <xdg@xdg.me> wrote:
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
While the above explanation makes sense, and understanding it can lead to designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect. Dancer being the new, easy way of developing apps, should perhaps have two kinds of hooks -- one that behaves the current way, and another that fires the way Rick, myself, and I suspect many other Dancer users expect it to behave, that is, once per human user request. -- Puneet Kishor
On 2013-01-02, at 5:35 PM, Puneet Kishor wrote:
On Jan 2, 2013, at 2:27 PM, David Golden <xdg@xdg.me> wrote:
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
While the above explanation makes sense, and understanding it can lead to designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
Dancer being the new, easy way of developing apps, should perhaps have two kinds of hooks -- one that behaves the current way, and another that fires the way Rick, myself, and I suspect many other Dancer users expect it to behave, that is, once per human user request.
If the before hook is firing on each request for static content (like favicon.ico), why even bother serving it up via the app? You can handle that via https://metacpan.org/module/Plack::Middleware::Static or in your web server config. In most cases you don't even want the app to know about static files. Olaf -- Olaf Alders olaf@wundersolutions.com http://www.wundersolutions.com http://twitter.com/wundercounter 866 503 2204 (Toll free - North America) 416 944 8306 (direct)
On 2013-01-02, at 5:35 PM, Puneet Kishor wrote:
On Jan 2, 2013, at 2:27 PM, David Golden <xdg@xdg.me> wrote:
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
While the above explanation makes sense, and understanding it can lead to designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
Dancer being the new, easy way of developing apps, should perhaps have two kinds of hooks -- one that behaves the current way, and another that fires the way Rick, myself, and I suspect many other Dancer users expect it to behave, that is, once per human user request.
If the before hook is firing on each request for static content (like favicon.ico), why even bother serving it up via the app? You can handle that via https://metacpan.org/module/Plack::Middleware::Static or in your web server config. In most cases you don't even want the app to know about static files.
Olaf -- Olaf Alders olaf@wundersolutions.com
http://www.wundersolutions.com http://twitter.com/wundercounter
866 503 2204 (Toll free - North America) 416 944 8306 (direct)
I'm using plack and I have apache set up to serve the "public" directory directly... so... I still don't get why the multiple calls to the before hook... Rick
On Wed, Jan 2, 2013 at 4:20 PM, Rick Bragg <rbragg@gmnet.net> wrote:
On 2013-01-02, at 5:35 PM, Puneet Kishor wrote:
On Jan 2, 2013, at 2:27 PM, David Golden <xdg@xdg.me> wrote:
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I
really have to
program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
While the above explanation makes sense, and understanding it can lead to designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
Dancer being the new, easy way of developing apps, should perhaps have two kinds of hooks -- one that behaves the current way, and another that fires the way Rick, myself, and I suspect many other Dancer users expect it to behave, that is, once per human user request.
If the before hook is firing on each request for static content (like favicon.ico), why even bother serving it up via the app? You can handle that via https://metacpan.org/module/Plack::Middleware::Static or in your web server config. In most cases you don't even want the app to know about static files.
Olaf -- Olaf Alders olaf@wundersolutions.com
http://www.wundersolutions.com http://twitter.com/wundercounter
866 503 2204 (Toll free - North America) 416 944 8306 (direct)
I'm using plack and I have apache set up to serve the "public" directory directly... so... I still don't get why the multiple calls to the before hook...
Rick
Are you doing any ajax calls? Or perhaps requests that redirect, for example, are you hitting http://yoursite/ which then redirects to http://www.yoursite/? Can you print the full URL that's being hit in the call so you can see if it's the exact same URL or something different? As others have mentioned, by default browsers look for that favicon.ico file in your web root, so it doesn't matter if you're serving /public/ through apache, since the request isn't looking for /public/favicon.ico, it's looking for /favicon.ico. I haven't seen any behavior indicating that multiple calls to any hooks happen unless multiple requests are happening, so I think you should keep looking for the cause of the multiple requests, not the same request hitting the hook multiple times. Of course, there could be some bug that I haven't run into, but based on your messages so far, I really think you're dealing with multiple requests coming in "around" the same time. Can you check your request (access) log before and after you hit the page?
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
While the above explanation makes sense, and understanding it can lead to
designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
I don't think I would agree here. Let me elaborate on my point of view: Dancer is a DSL to write a web application. Its purpose is to provide a clean and intuitive syntax for describing how to handle a request and which response to produce. This is based of course on the HTTP protocol, and Dancer relies entirely on that. That means that everything in Dancer's point of view is related to an incoming _request_. In the HTTP meaning. If Chrome hits favicon.ico whenever you hit the app, you'll send 2 requests every time you hit the browser's reload button. You are sending 2 requests, period. Dancer sees 2 requests, and acts accordingly. Implementing a workaround to simulate the concept of "human requests" versus real "HTTP requests" sounds crazy to me and error-prone. What makes Dancer so appealing is its thin layer over the HTTP stack, this kind of change or enhancement is dangerous, I think. I'm sorry if I'm not following you on this one, I hope you see my point of view :) Cheers
From: Alexis Sukrieh <sukria@sukria.net> To: brian@massassi.com; Perl Dancer users mailing list <dancer-users@dancer.pm> Sent: Thursday, 3 January 2013, 11:46 Subject: Re: [dancer-users] Before Hook hit multiple times.
Dancer is a DSL to write a web application. Its purpose is to provide a clean and intuitive syntax for describing how to handle a request and which response to produce. This is based of course on the HTTP protocol, and Dancer relies entirely on that.
That means that everything in Dancer's point of view is related to an incoming _request_. In the HTTP meaning. If Chrome hits favicon.ico whenever you hit the app, you'll send 2 requests every time you hit the browser's reload button. You are sending 2 requests, period.
Dancer sees 2 requests, and acts accordingly.
Implementing a workaround to simulate the concept of "human requests" versus real "HTTP requests" sounds crazy to me and error-prone.
What makes Dancer so appealing is its thin layer over the HTTP stack, this kind of change or enhancement is dangerous, I think.
I agree with this. The app doesn't know that it's a browser making an extra request to favicon.ico instead of a human doing so. In being a veteran of the "robot versus human" wars, I can tell you that trying to make the distinction is a nightmare and wastes time trying to fight a losing war when, instead, you can be building value. If you really think something is wrong, dump the request object in the before hook so you can see exactly what is happening in each request. That will clear this up pretty fast, I suspect. On the other hand, if you can demonstrate a foolproof method of determining which requests are of human origin and which are not, I suspect the Dancer team would be happy to incorporate this right after you pick up your Turing Award :) Cheers, Ovid -- Twitter - http://twitter.com/OvidPerl/ Buy my book - http://bit.ly/beginning_perl Buy my other book - http://www.oreilly.com/catalog/perlhks/ Live and work overseas - http://www.overseas-exile.com/
On Thu, Jan 3, 2013 at 9:43 AM, Ovid <curtis_ovid_poe@yahoo.com> wrote:
On the other hand, if you can demonstrate a foolproof method of determining which requests are of human origin and which are not, I suspect the Dancer team would be happy to incorporate this right after you pick up your Turing Award :)
I think we may have a sort of XY problem. The underlying question seems to be this: "how do I run common code for some but not all requests?" Dancer doesn't (to my knowledge) have a way to have per-route hooks, or hooks for routes matching some criteria. before qr{^/private} => sub { ... }; (This is the sort of thing that I think Catalyst does with 'begin' actions in controllers.) David -- David Golden <xdg@xdg.me> Take back your inbox! → http://www.bunchmail.com/ Twitter/IRC: @xdg
And then, I raise the Dancer 2 flag: 2013/1/3 David Golden <xdg@xdg.me>
Dancer doesn't (to my knowledge) have a way to have per-route hooks, or hooks for routes matching some criteria.
before qr{^/private} => sub { ... };
(This is the sort of thing that I think Catalyst does with 'begin' actions in controllers.)
If you mean Dancer 1, you're right, if you mean Dancer 2, you're wrong. In Dancer 2, everything is scoped to the "app" it's defined, so doing that is preatty easy with D2: package SomeApp; hook 'before' => sub { }; # some routes In this case, only the routes defined in SomeApp will have the filters defined. Only them. For more details about that feature, I suggest reading that article: http://advent.perldancer.org/2012/7 Wouldn't that be a perfect opportunity to try a switch to Dancer 2? PS: you could actually do it in Dancer 1 with a test in the before filter like so: hook before => sub { return pass if request->path !~ //; ... };
On Thu, Jan 3, 2013 at 10:05 AM, Alexis Sukrieh <sukria@sukria.net> wrote:
In Dancer 2, everything is scoped to the "app" it's defined, so doing that is preatty easy with D2:
Good to hear.
Wouldn't that be a perfect opportunity to try a switch to Dancer 2?
I'm not planning on switching until the various session-related issues I opened are resolved. As I said in issue 126, config handling is opaque and seems to rely too much on hardcoded values. These sorts of things are code smells and I think it's premature to encourage people to switch until those rough edges are sorted out. David -- David Golden <xdg@xdg.me> Take back your inbox! → http://www.bunchmail.com/ Twitter/IRC: @xdg
2013/1/3 David Golden <xdg@xdg.me>
Wouldn't that be a perfect opportunity to try a switch to Dancer 2?
I'm not planning on switching until the various session-related issues I opened are resolved. As I said in issue 126, config handling is opaque and seems to rely too much on hardcoded values.
Hmm, I'm surprised something that does not exist in Dancer 1 is a blocker
for a D2 transition. Or maybe I miss something.
These sorts of things are code smells and I think it's premature to encourage people to switch until those rough edges are sorted out.
I don't get it. Do you have something that works (or is supported) in Dancer 1 regarding session that is not in Dancer 2? If so, please enlight that, and I'd be very happy to fix it. That doesn't mean the issue you're mentioning is interesting, and I'll take a look at what I can do (actually sessions are fare more better in D2 than in D1 if you look closely at the implementation). Cheers,
2013/1/3 Alexis Sukrieh <sukria@sukria.net>
That doesn't mean the issue you're mentioning is interesting, and I'll take a look at what I can do (actually sessions are fare more better in D2 than in D1 if you look closely at the implementation).
Typo: that doesn't mean the issue isn't interesting !
Le jeudi 3 janvier 2013 à 16:05, Alexis Sukrieh a écrit :
And then, I raise the Dancer 2 flag:
2013/1/3 David Golden <xdg@xdg.me (mailto:xdg@xdg.me)>
Dancer doesn't (to my knowledge) have a way to have per-route hooks, or hooks for routes matching some criteria.
before qr{^/private} => sub { ... };
(This is the sort of thing that I think Catalyst does with 'begin' actions in controllers.)
If you mean Dancer 1, you're right, if you mean Dancer 2, you're wrong.
In Dancer 2, everything is scoped to the "app" it's defined, so doing that is preatty easy with D2:
package SomeApp;
hook 'before' => sub { };
# some routes
In this case, only the routes defined in SomeApp will have the filters defined. Only them. For more details about that feature, I suggest reading that article: http://advent.perldancer.org/2012/7
Hi, After reading some emails of people about this scoping, I think we have a hidden issue here: Scoping hooks in a package is great and is a must have feature. However, as some people have pointed out it makes it very difficult to quickly add a hook on all routes if they are in multiple packages. We should accept that developers have the right to separate features by packages, and not oblige them to group routes and hooks per package. Celogeek mentioned that this can be worked around by using roles but not everybody ate fluent with them. So, I propose that one could specify the scope of a hook. By default a hook would be package-scoped. But we should make it possible to scope it to the whole application ( if that's possible), and also be able to scope it to a selection of routes, as David Golden mentioned. Maybe it's not the right solution, but at least you'll agree that there is an issue in the current state ( I think English speaking people say "red herring" :)
Wouldn't that be a perfect opportunity to try a switch to Dancer 2?
PS: you could actually do it in Dancer 1 with a test in the before filter like so:
hook before => sub { return pass if request->path !~ //; ... };
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
On Thu, Jan 3, 2013 at 12:58 PM, Damien Krotkine <dkrotkine@gmail.com> wrote:
By default a hook would be package-scoped. But we should make it possible to scope it to the whole application ( if that's possible), and also be able to scope it to a selection of routes, as David Golden mentioned.
I wouldn't say that *all* hooks need to have scope of that sort. But a "before route" hook scoped to a route would seem to make sense. If you think about how, say, OX, does it. handlers dispatch to methods, and then you can use the normal Moose-ish before/after/around modifiers on those methods, which has some nice elegance. Since Dancer uses coderefs to dispatch, it would be useful to have a way to act before/after/around the dispatches. Some of the auth plugins do that by just wrapping the ref. E.g. get "/private/foo" => needs login => sub { ... }; The "problem" there is that you have to remember the auth modifier for every dispatch, plus if you want to have multiple modifiers, then you can get into this sort of chaining: get "/private/foo" => needs login => using another_thing => remember one_more => sub { ... }; That gets brittle and repetitive fast. I think the package scoped hooks can work. But it might also make sense to just have route modifiers. In the most general sense: around qr{^/private} => sub { my $coderef = shift; # ... do stuff before route ... my $result = $coderef->(); # ... do stuff after route ... return $result }; The question is whether that is/can-be dynamic or whether at the time the "around" is called, it goes and applies itself to every currently defined route that matches. It's probably hard to do "around" dynamically, but it might be possible to do "before" dynamically. (I.e. walk array of before route hooks, fire ones that match in order, then fire the handler.) In any case, these are the tricky design decisions to be made. David -- David Golden <xdg@xdg.me> Take back your inbox! → http://www.bunchmail.com/ Twitter/IRC: @xdg
Hello, 2013/1/3 Damien Krotkine <dkrotkine@gmail.com>
We should accept that developers have the right to separate features by packages, and not oblige them to group routes and hooks per package.
Indeed, and I'd go even a step further:
Celogeek mentioned that this can be worked around by using roles but not everybody ate fluent with them.
So, I propose that one could specify the scope of a hook.
By default a hook would be package-scoped. But we should make it possible to scope it to the whole application ( if that's possible), and also be able to scope it to a selection of routes, as David Golden mentioned.
Maybe it's not the right solution, but at least you'll agree that there is an issue in the current state ( I think English speaking people say "red herring" :)
You're absolutely right Damien, thanks to users like Celogeek who spend some time migrating a real application for 1 to 2, we've realized that the scoping we have in 2 is great, but is not _always_ what the user wants. I also think the "package scoping by default" is a good idea but it's clear now that we need a way to disable that in some places. I don't think it should be an exception for hooks, or even a kind of hooks. I think the user should be able to say : these apps (packages) share the same registry, or in other words, these are supposed to be merged into one app. For instance: package App; use Dancer; use App::Foo; use App::Bar; In this example, everything in Foo and Bar are in a jail, they don't share hooks or engines. We need a way to tell Dancer to load multiple apps as one, I'm not sure exactly how the DSL should be extended to allow that, but here is the idea I have in mind: package App; use Dancer; consume 'App::Foo', 'App::Bar'; That new "consume" keyword would be responsible for loading everything that is defined in the packages _into_ the current package. That would be, I think, the most generic and proper way to share settings, hooks and everything between "apps".
On Fri, 4 Jan 2013 10:28:43 +0100 Alexis Sukrieh <sukria@sukria.net> wrote:
I think the user should be able to say : these apps (packages) share the same registry, or in other words, these are supposed to be merged into one app.
For instance:
package App; use Dancer; use App::Foo; use App::Bar;
In this example, everything in Foo and Bar are in a jail, they don't share hooks or engines. We need a way to tell Dancer to load multiple apps as one, I'm not sure exactly how the DSL should be extended to allow that, but here is the idea I have in mind:
package App; use Dancer; consume 'App::Foo', 'App::Bar';
That new "consume" keyword would be responsible for loading everything that is defined in the packages _into_ the current package. That would be, I think, the most generic and proper way to share settings, hooks and everything between "apps".
Hmm, I like that; the sounds like it could be a good solution to the problem. I definitely think it should be possible to load routes etc from different packages but have them share a scope for config / hooks etc. At $work, we have a very large Dancer app, with routes defined in various packages (grouped logically); however, we have before hooks which should run for all routes, and session engine / serializer etc settings which apply to all; we'd need to be able to do the same with D2 one way or another. Part of me wonders if the auto scope-per-package stuff should be configurable, so you could request D1-style "all in one" behaviour if desired, but I'm not sure. -- David Precious ("bigpresh") <davidp@preshweb.co.uk> http://www.preshweb.co.uk/ www.preshweb.co.uk/twitter www.preshweb.co.uk/linkedin www.preshweb.co.uk/facebook www.preshweb.co.uk/cpan www.preshweb.co.uk/github
Sorry, top posting... An other way is to think about it bottom up instead of top down Instead of the parent app including the children packages, we could do : package App::Foo; use Dancer scope => qw(App); It's a bit like in relational database where you say who your parent is, not who your children are. It Also avoids to change the parent package every time you add a child. Also it makes it possible to use dancer with more than one scope. Not why it would useful though :) We should probably look at breadboard and catalyst, see how they do it. David, I think you have experience with catalyst? And that brings up the fact that we should use a serious tool to handle dancer 'use' options. Can we try an enhanced sub::exporter or similar? Le vendredi 4 janvier 2013 à 13:57, David Precious a écrit :
On Fri, 4 Jan 2013 10:28:43 +0100 Alexis Sukrieh <sukria@sukria.net> wrote:
I think the user should be able to say : these apps (packages) share the same registry, or in other words, these are supposed to be merged into one app.
For instance:
package App; use Dancer; use App::Foo; use App::Bar;
In this example, everything in Foo and Bar are in a jail, they don't share hooks or engines. We need a way to tell Dancer to load multiple apps as one, I'm not sure exactly how the DSL should be extended to allow that, but here is the idea I have in mind:
package App; use Dancer; consume 'App::Foo', 'App::Bar';
That new "consume" keyword would be responsible for loading everything that is defined in the packages _into_ the current package. That would be, I think, the most generic and proper way to share settings, hooks and everything between "apps".
Hmm, I like that; the sounds like it could be a good solution to the problem.
I definitely think it should be possible to load routes etc from different packages but have them share a scope for config / hooks etc.
At $work, we have a very large Dancer app, with routes defined in various packages (grouped logically); however, we have before hooks which should run for all routes, and session engine / serializer etc settings which apply to all; we'd need to be able to do the same with D2 one way or another.
Part of me wonders if the auto scope-per-package stuff should be configurable, so you could request D1-style "all in one" behaviour if desired, but I'm not sure.
-- David Precious ("bigpresh") <davidp@preshweb.co.uk> http://www.preshweb.co.uk/ www.preshweb.co.uk/twitter www.preshweb.co.uk/linkedin www.preshweb.co.uk/facebook www.preshweb.co.uk/cpan www.preshweb.co.uk/github
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Though doing it this way requires the user to maintain a manifest or some sort of class loading system, does it not? Cheers, Rik On 4 Jan 2013 13:21, "Damien Krotkine" <dkrotkine@gmail.com> wrote:
Sorry, top posting...
An other way is to think about it bottom up instead of top down
Instead of the parent app including the children packages, we could do :
package App::Foo; use Dancer scope => qw(App);
It's a bit like in relational database where you say who your parent is, not who your children are.
It Also avoids to change the parent package every time you add a child.
Also it makes it possible to use dancer with more than one scope. Not why it would useful though :)
We should probably look at breadboard and catalyst, see how they do it. David, I think you have experience with catalyst?
And that brings up the fact that we should use a serious tool to handle dancer 'use' options. Can we try an enhanced sub::exporter or similar?
Le vendredi 4 janvier 2013 à 13:57, David Precious a écrit :
On Fri, 4 Jan 2013 10:28:43 +0100 Alexis Sukrieh <sukria@sukria.net> wrote:
I think the user should be able to say : these apps (packages) share the same registry, or in other words, these are supposed to be merged into one app.
For instance:
package App; use Dancer; use App::Foo; use App::Bar;
In this example, everything in Foo and Bar are in a jail, they don't share hooks or engines. We need a way to tell Dancer to load multiple apps as one, I'm not sure exactly how the DSL should be extended to allow that, but here is the idea I have in mind:
package App; use Dancer; consume 'App::Foo', 'App::Bar';
That new "consume" keyword would be responsible for loading everything that is defined in the packages _into_ the current package. That would be, I think, the most generic and proper way to share settings, hooks and everything between "apps".
Hmm, I like that; the sounds like it could be a good solution to the problem.
I definitely think it should be possible to load routes etc from different packages but have them share a scope for config / hooks etc.
At $work, we have a very large Dancer app, with routes defined in various packages (grouped logically); however, we have before hooks which should run for all routes, and session engine / serializer etc settings which apply to all; we'd need to be able to do the same with D2 one way or another.
Part of me wonders if the auto scope-per-package stuff should be configurable, so you could request D1-style "all in one" behaviour if desired, but I'm not sure.
-- David Precious ("bigpresh") <davidp@preshweb.co.uk> http://www.preshweb.co.uk/ www.preshweb.co.uk/twitter www.preshweb.co.uk/linkedin www.preshweb.co.uk/facebook www.preshweb.co.uk/cpan www.preshweb.co.uk/github
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
On 4 Jan 2013 13:21, "Damien Krotkine" <dkrotkine@gmail.com> wrote:
And that brings up the fact that we should use a serious tool to handle dancer 'use' options. Can we try an enhanced sub::exporter or similar?
I doubt this is an exporter issue actually, but rather an
object-encapsulation problem, so I'm not sure opening a new work area about Sub::Exporter is what we want. On top of introducing another core-dep, we're going to diverge, I fear. I may be wrong, but that's my feeling. The exporting of symbols done by the DSL role works pretty well, not sure we want to spend energy on changing something that works. The main deal here is to be able to tell Dancer to compose a set of packages into one Dancer::Core::App object, for the caller. Or if we do it like you say, from a sub-app to a parent app. And after thinking about it, I don't think both ways are exclusive. Once we have that, we should be in a very good position for implementing the option David is speaking about: scope: single # the D1 way Or scope: per_app # the current D2 way Of course, there may be better names but you get the idea. I think we have something there, combining all the comments in this thread.
Le vendredi 4 janvier 2013 à 14:57, Alexis Sukrieh a écrit :
On 4 Jan 2013 13:21, "Damien Krotkine" <dkrotkine@gmail.com (mailto:dkrotkine@gmail.com)> wrote:
And that brings up the fact that we should use a serious tool to handle dancer 'use' options. Can we try an enhanced sub::exporter or similar?
I doubt this is an exporter issue actually, but rather an object-encapsulation problem, so I'm not sure opening a new work area about Sub::Exporter is what we want. On top of introducing another core-dep, we're going to diverge, I fear. I may be wrong, but that's my feeling.
Sorry I answered the other message before seeing this one. Yes I agree it's a different topic. I was just thinking out loud. What mean is that if we need to handle : use Dancer; use Dancer qw(:moose); use Dancer qw( :syntax :test); Use Dancer dsl => 'My::DSL', scope => 'Parent', ':moose' then maybe we can rely on existing mechanism. Maybe not a new dependency, but at least get inspired and maybe steal the syntax of existing stuff
The exporting of symbols done by the DSL role works pretty well, not sure we want to spend energy on changing something that works.
Yes definitely, see my other email
The main deal here is to be able to tell Dancer to compose a set of packages into one Dancer::Core::App object, for the caller. Or if we do it like you say, from a sub-app to a parent app. And after thinking about it, I don't think both ways are exclusive.
That's true actually, we could do both. Now the hard thing is to find the right syntax :)
Once we have that, we should be in a very good position for implementing the option David is speaking about:
scope: single # the D1 way
Or
scope: per_app # the current D2 way
maybe per_package ?
Of course, there may be better names but you get the idea. I think we have something there, combining all the comments in this thread.
Fully agree. Productive thread :)
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Le vendredi 4 janvier 2013 à 14:26, Rik Brown a écrit :
Though doing it this way requires the user to maintain a manifest or some sort of class loading system, does it not?
I need to check the code, but if I'm correct, the app object is stores as a package variable ( well, subroutine ). Maybe we can keep an app object per package, but it can be the same object shared across multiple package. So you would say : package Child; use My::Parent; use Dancer scope => 'My::Parent'; That would Do exactly as usual ( install the app object in Child, but instead of creating a new app object, get it from My::Parent. Or have *Child::dsl = \&My::Parent::dsl. Also, use Dancer scope => 'My::Parent'; could use My::Parent behind the scene. Alexis, what do you say ?
Cheers, Rik On 4 Jan 2013 13:21, "Damien Krotkine" <dkrotkine@gmail.com (mailto:dkrotkine@gmail.com)> wrote:
Sorry, top posting...
An other way is to think about it bottom up instead of top down
Instead of the parent app including the children packages, we could do :
package App::Foo; use Dancer scope => qw(App);
It's a bit like in relational database where you say who your parent is, not who your children are.
It Also avoids to change the parent package every time you add a child.
Also it makes it possible to use dancer with more than one scope. Not why it would useful though :)
We should probably look at breadboard and catalyst, see how they do it. David, I think you have experience with catalyst?
And that brings up the fact that we should use a serious tool to handle dancer 'use' options. Can we try an enhanced sub::exporter or similar?
Le vendredi 4 janvier 2013 à 13:57, David Precious a écrit :
On Fri, 4 Jan 2013 10:28:43 +0100 Alexis Sukrieh <sukria@sukria.net (mailto:sukria@sukria.net)> wrote:
I think the user should be able to say : these apps (packages) share the same registry, or in other words, these are supposed to be merged into one app.
For instance:
package App; use Dancer; use App::Foo; use App::Bar;
In this example, everything in Foo and Bar are in a jail, they don't share hooks or engines. We need a way to tell Dancer to load multiple apps as one, I'm not sure exactly how the DSL should be extended to allow that, but here is the idea I have in mind:
package App; use Dancer; consume 'App::Foo', 'App::Bar';
That new "consume" keyword would be responsible for loading everything that is defined in the packages _into_ the current package. That would be, I think, the most generic and proper way to share settings, hooks and everything between "apps".
Hmm, I like that; the sounds like it could be a good solution to the problem.
I definitely think it should be possible to load routes etc from different packages but have them share a scope for config / hooks etc.
At $work, we have a very large Dancer app, with routes defined in various packages (grouped logically); however, we have before hooks which should run for all routes, and session engine / serializer etc settings which apply to all; we'd need to be able to do the same with D2 one way or another.
Part of me wonders if the auto scope-per-package stuff should be configurable, so you could request D1-style "all in one" behaviour if desired, but I'm not sure.
-- David Precious ("bigpresh") <davidp@preshweb.co.uk (mailto:davidp@preshweb.co.uk)> http://www.preshweb.co.uk/ www.preshweb.co.uk/twitter (http://www.preshweb.co.uk/twitter) www.preshweb.co.uk/linkedin (http://www.preshweb.co.uk/linkedin) www.preshweb.co.uk/facebook (http://www.preshweb.co.uk/facebook) www.preshweb.co.uk/cpan (http://www.preshweb.co.uk/cpan) www.preshweb.co.uk/github (http://www.preshweb.co.uk/github)
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm (mailto:dancer-users@dancer.pm) http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm (mailto:dancer-users@dancer.pm) http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
_______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
On Jan 3, 2013, at 2:46 AM, Alexis Sukrieh <sukria@sukria.net> wrote:
While the above explanation makes sense, and understanding it can lead to
designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
I don't think I would agree here. Let me elaborate on my point of view:
Dancer is a DSL to write a web application. Its purpose is to provide a clean and intuitive syntax for describing how to handle a request and which response to produce. This is based of course on the HTTP protocol, and Dancer relies entirely on that.
That means that everything in Dancer's point of view is related to an incoming _request_. In the HTTP meaning. If Chrome hits favicon.ico whenever you hit the app, you'll send 2 requests every time you hit the browser's reload button. You are sending 2 requests, period.
Dancer sees 2 requests, and acts accordingly.
Implementing a workaround to simulate the concept of "human requests" versus real "HTTP requests" sounds crazy to me and error-prone.
What makes Dancer so appealing is its thin layer over the HTTP stack, this kind of change or enhancement is dangerous, I think.
I'm sorry if I'm not following you on this one, I hope you see my point of view :)
I see your point completely, and as I acknowledged in my first email, I saw the point as made by David. Yet, I respectfully disagree with the above explanation. All manner of rational explanations can be put forward, but my point is, as much as possible, programming tools should allow human beings to think the way humans think, not force humans to think some other way. HTTP was invented with documents in mind. Statelessness was a feature, and it allowed the web to rapidly scale. However, the web has gone way beyond its original intent, and most everyone is making apps that mimic some level of "app" functionality, that is, trying their best to remember state. Dancer could have several different philosophies -- one, as you describe above, is to enable users to do things the right way. The other, as I describe, is to enable users to do the right thing even if it is the "wrong" way. A user on a web app, as opposed to a user or a program on a command line app or a program, querying a web server is typically doing something -- clicking on a DOM object or choosing something in a form or hovering the mouse over something -- and something is happening in return. Whether that something happens on the client or server, once or many times, none of that matters from the user's point of view. Dancer is involved *if* the server is involved. So, from the POV of the app developer, she has to make the app respond rationally and reasonably in response to the user. Making that easy would be very nice to the extent that Dancer can make it easy. As I said in my earlier post, a way would be to perhaps have two kinds of before hooks. One, that behaves the way it behaves currently, perhaps the right way, that is, firing before *every* request no matter who makes that. Two, that behaves *once* and only once in response to the app from the user's perspective. If the second way doesn't exist then users will try to code that. All I am saying is that that coding could be standardized and made available out of the box. Nevertheless, Dancer is great, and I am happy to understand the difference elaborated above. Now that I am aware of it, I will find a way to code around it. But, I appreciate the opportunity to express my POV above. Many thanks, -- Puneet Kishor
On Jan 2, 2013, at 2:27 PM, David Golden <xdg@xdg.me> wrote:
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
While the above explanation makes sense, and understanding it can lead to designing applications better, my gut feeling is with Rick. If I create a 'before' hook, I want it normally to fire once everything the human user makes a request even though under the scene the browser is making multiple requests. In other words, the current behavior seems to be against the DWIM nature that I would expect.
Dancer being the new, easy way of developing apps, should perhaps have two kinds of hooks -- one that behaves the current way, and another that fires the way Rick, myself, and I suspect many other Dancer users expect it to behave, that is, once per human user request.
-- Puneet Kishor _______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Thanks again! I like the way Dancer is REALLY thin. As long as things like this are well documented and more cookbook examples start to emerge (and plugins) I think Dancer is on the right path. rick
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
David _______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Thanks, I know well the stateless nature of HTTP :) It does make sense that Dancer has an in for every resource request... I'm trying to put some logic in one place to test custom fine-grain user/groups/roles/permissions management stuff on every page get or form post. I guess this runs on EVERY resource request so I need to think about that. It makes sense, but it just seemed a little weird and maybe needs some extra programming workaround. Thanks! Rick
On Wed, Jan 2, 2013 at 5:16 PM, Rick Bragg <rbragg@gmnet.net> wrote:
hooks and routes are called once in the application flow. Do I really have to program around this taking into consideration the number of times the before hook is called on each page?
HTTP is stateless. The client can make as many requests as it likes and your Dancer app will see them as separate requests.
The 'before' hook fires for every request. If you want to limit a hook to particular routes, you have to write that logic yourself in the hook subroutine or else wrap the route handlers instead of using a before hook.
David _______________________________________________ dancer-users mailing list dancer-users@dancer.pm http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
Makes total sense. Thanks again!
participants (11)
-
Alexis Sukrieh -
Brian E. Lozier -
Damien Krotkine -
David Golden -
David Precious -
Mr. Puneet Kishor -
Olaf Alders -
Ovid -
Puneet Kishor -
Rick Bragg -
Rik Brown