I've had some difficulties with the before filter example provided in Dancer::Introduction. If we pass the information via 'session' rather than 'var' and use 'redirect' instead of 'request->path_info' we get code that more-or-less works as expected: before sub { if (!session('user') and request->path_info !~ m{^/login}) { session requested_path => request->path_info; redirect('/login'); } }; post '/login' => sub { # authenticate credentials session user => params->{user}; my $path = session->{requested_path}; session requested_path => undef; redirect $path }; Here is naive code based on the docs that _doesn't_ work: before sub { if (!session('user') && request->path_info !~ m{^/login}) { var requested_path => request->path_info; request->path_info('/login'); } }; post '/login' => sub { # check credentials session user => params->{user}; my $path = vars->{requested_path}; redirect $path # [1] # request->path_info($path) # [2] }; The first difference is that this 'before' filter causes the login page to show the original URL instead of /login. The second difference is that neither of the rerouting alternatives leads to the desired behavior. [1] results in VOID. [2] results '/initial_requested_path' as display content I'd be interested in understanding how to fix the failed implementation. And I'm also willing to patch the docs to show a complete, successful implementation. Cheers, Joel -- Joel Roth
Hi Joel, I am doing my implementation a bit differently, so the following is all guesswork, but I think you will find it useful. See below... Joel Roth wrote:
I've had some difficulties with the before filter example provided in Dancer::Introduction.
If we pass the information via 'session' rather than 'var' and use 'redirect' instead of 'request->path_info' we get code that more-or-less works as expected:
before sub { if (!session('user') and request->path_info !~ m{^/login}) { session requested_path => request->path_info; redirect('/login'); } };
post '/login' => sub { # authenticate credentials session user => params->{user}; my $path = session->{requested_path}; session requested_path => undef; redirect $path };
Here is naive code based on the docs that _doesn't_ work:
before sub { if (!session('user')&& request->path_info !~ m{^/login}) { var requested_path => request->path_info; request->path_info('/login'); } };
post '/login' => sub { # check credentials session user => params->{user}; my $path = vars->{requested_path}; redirect $path # [1] # request->path_info($path) # [2] };
The first difference is that this 'before' filter causes the login page to show the original URL instead of /login.
Which it would. By changing requested path via `request->path_info('/login')` you are changing the path internally. If you want the URI in the browser to change as well, then you have to use `redirect` which is equivalent to doing an http-refresh.
The second difference is that neither of the rerouting alternatives leads to the desired behavior.
[1] results in VOID. [2] results '/initial_requested_path' as display content
I'd be interested in understanding how to fix the failed implementation.
The above also is expected. By the time you come to `post '/login'`, the requested path is already /login. Your working code above is correct. What you are doing is saving the requested path in a session variable. That ensures that the value persists over repeated calls. Then, you are redirecting, which emulates a browser refresh, a brand new call to the server, this time requesting the login page. Once at the login page, you extract the previously requested path from the session var. All that makes sense, and works as expected.
And I'm also willing to patch the docs to show a complete, successful implementation.
I haven't looked at the latest docs. If you think the docs are misleading, definitely file an issue with the suggested complete documentation that works.
Cheers,
Joel
On Sat, Dec 04, 2010 at 07:30:26AM -0600, Puneet Kishor wrote:
Hi Joel,
I am doing my implementation a bit differently, so the following is all guesswork, but I think you will find it useful. See below...
Thanks for taking the time to reply. In these formative times in my development, a few hints mean a lot. :-)
Joel Roth wrote:
I've had some difficulties with the before filter example provided in Dancer::Introduction.
If we pass the information via 'session' rather than 'var' and use 'redirect' instead of 'request->path_info' we get code that more-or-less works as expected:
before sub { if (!session('user') and request->path_info !~ m{^/login}) { session requested_path => request->path_info; redirect('/login'); } };
post '/login' => sub { # authenticate credentials session user => params->{user}; my $path = session->{requested_path}; session requested_path => undef; redirect $path };
Your working code above is correct. What you are doing is saving the requested path in a session variable. That ensures that the value persists over repeated calls. Then, you are redirecting, which emulates a browser refresh, a brand new call to the server, this time requesting the login page. Once at the login page, you extract the previously requested path from the session var. All that makes sense, and works as expected.
Yes, and my site is live, which I appreciate :-) I've finally tracked down my problem code. The code below works on my local machine as stand-alone using HTTP::Simple::PSGI. However it 404s on the server using Plack::Runner and these mod_rewrite rules. RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) dispatch.cgi/$1 before sub { my $path = request->path_info; if (!session('user') and $path !~ m{^/login}) { session requested_path => $path; request->path_info('/login'); # 404s on server using mod_rewrite #redirect '/login' ; # works } }; post '/login' => sub { if( validate(params->{user}, params->{pass}) ){ session user => params->{user}; my $path = session->{requested_path}; session requested_path => undef; session failed_login => undef; redirect $path; } else { session failed_login => 1; # use this to trigger "failed login" message redirect '/login'; } };
And I'm also willing to patch the docs to show a complete, successful implementation.
I haven't looked at the latest docs. If you think the docs are misleading, definitely file an issue with the suggested complete documentation that works.
Will do. I'd like people to see things work the first time out. :-) Best, Joel -- Joel Roth
participants (2)
-
Joel Roth -
Puneet Kishor