[cgiapp] run mode issues when posting data
Hi all. I've been a long time user of C::A and I dig it. Until now, the applications I've written have been pretty simple. They basically consisted of a form with data passed via GET. A hidden input with the run mode was all I needed to pass the data off to the right run mode. Too easy. The trouble comes when using POST. And the frustrating thing is that I know there's a simple way to handle this that I'm missing. I've scoured all the docs and I think I'm just missing something. This is why I seek your collective wisdom. Consider this simple use case: my application does basic user management. There's a login form, a run mode to list the users and a run mode to edit/create users. The login aspect works great. cgiapp_prerun checks the server side session and if a session variable denoting the user is logged in is missing (or the session is expired), then it directs the user to the login run mode. When the user submits the login form, we go through the same process, except this time the presence of username and password parameters triggers the login run mode to check to see if they're valid. If they are, then the session variable is set and cgiapp_prerun isn't triggered again until the session expires: sub cgiapp_prerun { my $app = shift; unless ($app-session-param('__logged_in')) { $app-prerun_mode('login'); } } I had a little bit of trouble passing the POST parameters to the login run mode. This was solved by stashing them in the app's param during cgiapp_init. I assume this is how we handle POST parameters. All the docs I read didn't differentiate between GET and POST. I found out the hard way that GET parameters were always available to the app, while POST had to be handled with kid gloves. Any wisdom regarding POST and best practices would be greatly appreciated. I simply do the following: sub cgiapp_init { my $app = shift; $app-param('query', $app-query); [...] } And then in the run modes that require POST variables: sub login { my $app = shift; my $q = $app-param('query'); [...] } As opposed to run modes that require GET variables: sub list_user { my $app = shift; my $q = $app-query; [...] } The above works great for the the authentication aspect of my application. Advice on the above would be great, but it's not the primary reason I write now. Now I have trouble with a run mode called edit_user. This simply displays a form pre-populated with user data if the query string looks like: ?rm=edit_useruser_id=1, and displays a blank from if the query string looks like: ?rm=edit_user. This is simple enough. The trouble comes when I try to submit that form. When submitted, the parameters are passed and stored as they should be in $app-param('query'), but the run mode that is fired is the default run mode as specified in setup(). If I change POST to GET (and make no other change) the app works as it should and edit_user is triggered allowing the form to be posted back to itself. If I change the form back to POST, we trigger the default run mode. So there's where I am. I know there's something simple I'm overlooking. I know that what I'm doing isn't unusual. I hope that I'm not going to have to overload mode_param to do the run mode switching for me. I can't for the life of me see how C::A would be written to natively and nicely handle run modes in GET variables but not in POST variables. Seems to me that I'm just not doing something right. So now I humbly ask you for advice. Show me the error of my ways. Michael De Soto # CGI::Application community mailing list #### ## To unsubscribe, or change your message delivery options, ## ## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp## #### ## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ## ## Wiki: http://cgiapp.erlbaum.net/ ## ####
Re: [cgiapp] run mode issues when posting data
Michael De Soto wrote: I had a little bit of trouble passing the POST parameters to the login run mode. This was solved by stashing them in the app's param during cgiapp_init. I assume this is how we handle POST parameters. All the docs I read didn't differentiate between GET and POST. I found out the hard way that GET parameters were always available to the app, while POST had to be handled with kid gloves. Any wisdom regarding POST and best practices would be greatly appreciated. I simply do the following: For normal name/value pairs there is no difference between GET and POST params when handling them in your application. You can get both from $self-query-param(). Something else is wrong with your application. -- Michael Peters Plus Three, LP # CGI::Application community mailing list #### ## To unsubscribe, or change your message delivery options, ## ## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp## #### ## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ## ## Wiki: http://cgiapp.erlbaum.net/ ## ####
Re: [cgiapp] run mode issues when posting data
On Wed, Nov 26, 2008 at 4:32 AM, Michael De Soto [EMAIL PROTECTED] wrote: The above works great for the the authentication aspect of my application. Advice on the above would be great, but it's not the primary reason I write now. Now I have trouble with a run mode called edit_user. This simply displays a form pre-populated with user data if the query string looks like: ?rm=edit_useruser_id=1, and displays a blank from if the query string looks like: ?rm=edit_user. This is simple enough. The trouble comes when I try to submit that form. When submitted, the parameters are passed and stored as they should be in $app-param('query'), but the run mode that is fired is the default run mode as specified in setup(). If I change POST to GET (and make no other change) the app works as it should and edit_user is triggered allowing the form to be posted back to itself. If I change the form back to POST, we trigger the default run mode. Are you perhaps mixing GET and POST parameters? Did you put an action in your form tag, and also add the rm and user_id as hidden input fields? form method=POST action=my.cgi?rm=edit_useruser_id=1 ... /form The above will not work, since the CGI.pm object will ignore the get parameters in the URL and only look at the parameters in the POST body. form method=POST action=my.cgi?rm=edit_useruser_id=1 input type=hidden name=rm value=edit_user / input type=hidden name=user_id value=1 / ... /form That will work, since all parameters are part of the post body. You can edit the source code of CGI.pm to get it to parse both the GET and POST params if they both exist, but I would not recommend that. If you want to get a bit more advanced, you can use the PATH_INFO to pass these values: form method=POST action=my.cgi/edit_user/1 ... /form That requires some more work in your application, but makes your forms simpler and your URLs cleaner. Ask if you want more details. Cheers, Cees # CGI::Application community mailing list #### ## To unsubscribe, or change your message delivery options, ## ## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp## #### ## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ## ## Wiki: http://cgiapp.erlbaum.net/ ## ####
Re: [cgiapp] run mode issues when posting data
Thanks for the quick reply. On Tue, Nov 25, 2008 at 12:39 PM, Michael Peters [EMAIL PROTECTED] wrote: For normal name/value pairs there is no difference between GET and POST params when handling them in your application. You can get both from $self-query-param(). Something else is wrong with your application. I see now that there is no difference in C::A's handling of GET and POST. I wrote a quick bare bones app to prove it. The app was as follows: two run modes, one with a form and one with straight HTML. The straight HTML page was the default run mode. I used Data::Dumper in cgiapp_postrun to dump the application object and see what was what. I was able to load the form and post to itself without an issue. The app used the correct run mode when the form was submitted. Best of all, the POST params were passed without issue. So I began adding the pieces of my real app into the test app to see what and where it breaks. It seems that CAP::Session is the bad guy. When I dump the application object without CAP::Session, we have param '__QUERY_OBJ' that contains all the query information. This is the expected behavior. When $app-session_config is called from cgiapp_init, then it appears that the POST parameters disappear from '__QUERY_OBJ' and are placed in a application parameter called 'CGI_SESSION_OPTIONS'. I think this is the root of my problem, though I do not understand it. I tracked down the issue to the second argument '$app-query': $app-session_config( CGI_SESSION_OPTIONS = [ 'driver:mysql;serializer:Storable;id:sha256', $app-query, [...] I found that if I replaced that argument with undef, the application reverted back to normal and stored my params in __QUERY_OBJ. Otherwise the params went into 'CGI_SESSION_OPTIONS'. So the problem is that I don't understand what that argument is actually doing. At this point we're probably beyond the scope of this mailing list, but since you all are seasoned application developers, I'll ask anyway: what does that argument do and why does it appear to affect the application object? I went to the CGI::Session docs for guidance. It's not explicit. So I don't know. I'm assuming it pre-loads the query into the session. It's not clear why it (or probably more correctly CAP::Session) would remove the query parameters from the application object. That doesn't make sense to me. Can anyone shed some light on it? Michael De Soto # CGI::Application community mailing list #### ## To unsubscribe, or change your message delivery options, ## ## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp## #### ## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ## ## Wiki: http://cgiapp.erlbaum.net/ ## ####