http://www.perlmonks.org?node_id=70883


in reply to "Action" variables and form data

CGI.pm can be somewhat tricky when you are trying to get the parameters from both GET and POST methods. The url_param instead of param will get the parameters from the url line. However, I have found that CGI.pm can still be somewhat mischivious when trying to get the values from the param function especially when dealing with both the GET and POST methods. So here is my suggestion. Parse the query string yourself. The client will send an environment variable called QUERY_STRING. So try to get it this way: (Assuming you only have ?action=additem in the query string)
my $query_srting = $ENV{QUERY_SRING}; my ( $query, $action ) = split /=/, $query_string;
This should put "additem" in your $action . Good Luck!

Update: Thanks to tilly and Ovid for your suggestions. Seems that I still have a long way to go to get this perl thing down. Anyway, I agree that rolling on your own can be much harder than really understanding how CGI.pm works and forgeting the little details such as the difference between POST and GET. Thanks to you guys I am going back and revising my CGI code. :)

Ovid wrote:

but the "roll your own" parsing that kha0z suggested is terribly broken.

Please enlighten me. I don't see where the "broken" part is.

Thanks.

Another Update:Thanks again for your help Ovid. :)

kha0z -- www.kha0z.net

Replies are listed 'Best First'.
Re (tilly) 2: "Action" variables and form data
by tilly (Archbishop) on Apr 09, 2001 at 15:39 UTC
    Yet another example of why not to roll your own.

    First of all you assumed that the query string only has one name/value pair. What if it has more? Use a hash? Well what if there are multiple name/value pairs? What if someone for testing turns a post back into a get to collect a URL and then wonders why their code broke?

    Plus did you consider the poor schmuck who will use your code with form data that has been modified in escaping? At least you warned people that you got the first wrong. But you should also be pointing people to URI::Escape so they can decode the data.

    No, it is far better to do as CGI intentionally does and leave get/post transparent within the CGI so that the developer can easily switch, and just use hidden form elements as they were intended rather than trying to mix and match.

      That is a very good point. And one that, as a newbie, I forgot to point out. However, I may be wrong, but it think that it is always important to remember that in perl "there is more than one way to do it". That said maybe it is not the best but it is a possible solution to an imidiate problem. Anyway, we should alays comment on these fixes so that we can review them later and that others can improve on our code as well.

      Thanks for bringing up that point. :)

      Update:I stand corrected. Throught the examples and arguements that have been presented, I think that I understand, that by trying to parse through the quesry string myself all I am doing is tring to rewrite a function that is already in CGI.pm. This didn't make sense to me at first, until I sat and thought about it. I agree that instead of writing a quick fix to the problem. We should be robust enough to look at the module and understand how it works and use it to its full potential instead of trying to rewrite the API ourselves.

      kha0z -- www.kha0z.net

        kha0z wrote:
        I may be wrong, but it think that it is always important to remember that in perl "there is more than one way to do it".

        There is definitely more than one way to do it, but mixing GET and POST is still wrong -- though I realize you're not advocating that here. GET and POST are not the same and shouldn't be used as such. In this post, I wrote:

        As a general rule of thumb, use GET when you get information from a server without changing it. Use POST when you post information to a server and thus change it. That's why we have two methods.

        That's the rule of thumb to remember, but there are technical distinctions as well. See the aforementioned link for a bit more information. Blindly mixing the two usually doesn't cause problems, but like so many issues of its kind, the intermittant problems that can result are very difficult to diagnose.

        Cheers,
        Ovid

        Update: Ugh. I just read kha0z's original post. Amongst other things, /s?he/ advised "Parse the query string yourself yourself." This is bad. Very bad. First, not only does CGI.pm parse the query string for you, thus causing your parsing of the query string to be rewriting code, but the "roll your own" parsing that kha0z suggested is terribly broken.

        Obviously, I can't be that good of a programmer if I failed to note the "context" of the node I was replying to :)

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

(Ovid - why your CGI code is broken) Re(2): "Action" variables and form data
by Ovid (Cardinal) on Apr 10, 2001 at 11:44 UTC

    You ask why your code is broken, so here goes:

    Your suggestion on how to parse the CGI code reveals a subtle flaw that is, unfortunately, all to common in programming: it's not robust.

    Here's the original FORM tag:

    <FORM METHOD=POST ACTION="http://CanadaAllergy.com/~canadaal/cgi-bin/s +hopcart.pl?action=additem">
    Here's your code to parse it:
    my $query_srting = $ENV{QUERY_STRING}; my ( $query, $action ) = split /=/, $query_string;

    That code is going to work perfectly fine and as long as the format string remains the same, you can test it all day long and not notice problems. However, the following query strings will all break:

    <form method="post" action="http://someserver.com/index.cgi?action=add +item&id=12345"> <form method="post" action="http://someserver.com/index.cgi?action=add +item&action=checkout"> <form method="post" action="http://someserver.com/index.cgi?action=pro +cess r%E9sum%E9">

    All of the above are valid query strings (even the second with duplicate parameter names), but will cause your code to fail, or in the case of the last one, to produce output the programmer may not be testing for ($action eq 'process r%E9sum%E9'). The problem is that while your code works now, the first time some programmer in the future tries to do something unexpected with the query string, your code will fail. Part of our job as programmers is to anticipate issues like this and write code that is robust enough to handle these issues.

    Now, if I may apologize for a couple of shameless plugs, you can read more about this at use CGI or die; and Lesson 2 of my online CGI course.

    Hope this helps!

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.