[cgiapp] run mode issues when posting data

2008-11-25 Thread Michael De Soto
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

2008-11-25 Thread Michael Peters

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

2008-11-25 Thread Cees Hek
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

2008-11-25 Thread Michael De Soto
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/ ##
####