http://qs321.pair.com?node_id=752293

cormanaz has asked for the wisdom of the Perl Monks concerning the following question:

Bros, I have a problem here that's got me flummoxed. CGI seems not to be returning a parameter that the log says is being passed. Here's the code:
use CGI; my $q = new CGI; my $function = $q->param('f'); my $id = $q->param('id'); my $table = $q->param('table'); my $coder = $q->param('coder'); if ($function eq 'load') { loaddoc($id,$table,$coder,$data); } if ($function eq 'mark') { my $h = $q->param('h'); my $t = $q->param('t'); my $junk; ($junk,my $headsent,my $headword) = split(/[sw]/,$h); ($junk,my $tailsent,my $tailword) = split(/[sw]/,$t); warn "h: $h t: $t hs: $headsent hw: $headword ts: $tailsent tw: $ +tailword"; . . . }

I am running this on Apache and it has been intermittently returning null for the h parameter, which is why I put the warn in there. So here is what the warn statement writes into the server log:

[Sat Mar 21 13:15:36 2009] [error] [client 127.0.0.1] h: t: s43w29 h +s: hw: ts: 43 tw: 29 at C:/xampplite/cgi-bin/unitize.pl line 31., r +eferer: http://localhost/cgi-bin/unitize.pl?f=mark&id=659&coder=1&tab +le=test&h=s39w9&t=s39w25
So as you can see the h=s39w9 parameter is getting passed to the script but mod CGI is not picking it up somehow. The other odd thing is that sometimes it works fine. What could explain this?!?

TIA.......Steve

UPDATE: I got the param list from CGI with $q->param and listed them in the warn, and they are all there, including h.

Replies are listed 'Best First'.
Re: CGI Not Returning Parameter that's there
by linuxer (Curate) on Mar 21, 2009 at 21:10 UTC

    How can you judge from the quoted log entry that parameter h is set? I only can see, that it was set in the referer, but I couldn't see it for the logged request?

    Are you using strict and warnings? If not, please do it. If yes, I wonder, that there's no warning?

    The following topics are not related to your problem, I think, but maybe give room for "optimization":

    If you want to check alternative values of $function, use the if/elsif/else construct. It saves some time (maybe ;o). Otherwise each if will be checked (what for? If $function eq 'load', it cannot be $function eq 'mark').

    if ( $function eq 'load' ) { # this } elsif ( $function eq 'mark' ) { # that } elsif ( $function eq 'foobar' ) { # something completely different } else { # any other stuff or something unexpected? }

    Your code:

    my $junk; ($junk,my $headsent,my $headword) = split(/[sw]/,$h);

    could be rewritten like this:

    # no $junk anymore and no doubled 'my' ! my ( $headsent, $headword ) = ( split /[sw]/, $h )[1,2];

    Can you reproduce that issue in a little code example which can be tested by the monks to identify the issue?

    Updates:

    • Is there a difference between the times when it works and when not (other url, special action, whatever?)?

      A more important reason for deciding between if ...; if ...; ... and if ... elsif ... is to indicate intent. A string of if statements indicates that any combination of them may be true. An if/elsif chain indicates that only one may be true.

      Efficiency differences in this case are most likely trivial, but the difference in information conveyed between the writer and reader of the code is highly significant!


      True laziness is hard work
      Well obviously it's not getting set, that's the problem. Yet it is getting passed from the client as indicated by the log, the variable is showing up in the parameter list, and the value is getting set most of the times I try the script.

        Sorry, the shown log entry doesn't say anything about the parameter list for the request which produced that log entry.

        It shows your warning message (which indicates that parameter h wasn't set) with an empty string, a whitespace (or a possible undef in $h) at the position where $h should be interpolated... it's hard to guess, what caused that empty space between h: and t:.

        The log doesn't say anything about the actual parameter list for the logged request.

        What we see is the referrer's URL. That's the URL you were coming from (probably the URL you called before this logged one). And that URL contained parameter h in its query string (parameter list).

        If I'm so badly wrong on this, please enlighten me and explain that log format to me.

Re: CGI Not Returning Parameter that's there
by olus (Curate) on Mar 22, 2009 at 01:46 UTC

    You must have noticed that the log line says &t=s39w25 and the value you are printing is t: s43w29. It seems you are not dealing with the same request. Try to log the QUERY_STRING and check again if the params you are getting from CGI are the ones being passed.

      OK, I did this. Same result. The query string is returned as f=mark&id=586&coder=1&table=test&h=s2w0&t=s2w15It is for a different attempt so the numbers aren't the same, but as you can see the parameters are there.
Re: CGI Not Returning Parameter that's there
by ruzam (Curate) on Mar 22, 2009 at 04:24 UTC

    You might want to try:

    my $h = $q->url_param('h');

    If you're mixing URL parameters with GET/POST forms the results may not be where you expect. I make it a habit of checking url_param() if param() is undefined.

Re: CGI Not Returning Parameter that's there
by Anonymous Monk on Mar 22, 2009 at 06:29 UTC
    You should use Dump/self_url/Dumper for debugging
    D:\>perl -MCGI -le"print CGI->new->Dump" a=b%00c d=e a= a=Q <ul> <li><strong>a</strong></li> <ul> <li>b c</li> <li></li> <li>Q</li> </ul> <li><strong>d</strong></li> <ul> <li>e</li> </ul> </ul> D:\>perl -MCGI -le"print CGI->new->self_url" "a=b%00c&d=e&a=&a=Q" http://localhost?a=b%00c;a=;a=Q;d=e D:\>perl -MCGI -MData::Dumper -le"print Data::Dumper->new([ CGI->new ] +)->Useqq(1)->Indent(1)->Dump" a=b%00c d=e a= a=Q $VAR1 = bless( { ".parameters" => [ "a", "d" ], "use_tempfile" => 1, ".charset" => "ISO-8859-1", ".fieldnames" => {}, "param" => { "a" => [ "b\0c", "", "Q" ], "d" => [ "e" ] }, "escape" => 1 }, 'CGI' ); D:\> D:\> D:\>
Re: CGI Not Returning Parameter that's there
by hangon (Deacon) on Mar 22, 2009 at 18:33 UTC

    Take a look at the HTML source in your browser. If there is more than one instance of the h parameter, cgi will return a list, not a scalar.

    If this is the case, and one of the h values is not set, your list will contain an undef value. Also, you would be assigning a list to $h, a scalar, and only getting one value from the list. As there is no guarantee on the order that values for multiple instances of the same parameter will be returned from the browser, you could never be sure which value you are assigning to $h.