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

Hi, One of the core Jellybean objects uses to pull data from the QUERY_STRING. (We're good monks.) Since Jellybean offers a persistent object platform, we ran into an issue where the values from CGI::param() didn't match the query string passed from the client.

For example, the following code is a snippet showing the behavior. The print statements are for debugging, and I'll describe the commented bits after the code:

sub save { my $self = shift; print STDERR $ENV{QUERY_STRING}, "\n"; # $CGI::PERLEX = 1; my $q = new CGI; my $result; foreach my $sect ($self->{config}->sectionNames()) { foreach my $item ($self->{config}->sectionKeys($sect)) { print STDERR "Found:\t", $q->param("$sect|$item"), "\n"; $self->{config}->put($item, $q->param("$sect|$item"), $sec +t); } } # $q->_reset_globals(); if (!$self->{config}->save()) { return "Error saving config file: $!"; } else { return $self->default(); } }
From my brief perusal of, am I correct in assuming that there is something in its namespace that ought to be reset? Either of the two commented out lines achieve the same results -- namely, that it works properly.

Anyone with more familiarity is invited to comment on this, especially if you can provide insight or a better way to do things.

Replies are listed 'Best First'.
Re: Caching Issue
by btrott (Parson) on May 11, 2000 at 21:54 UTC
    Are you running under mod_perl or PerlEx?

    From a quick glance at the source, it looks like it calls _reset_globals for each new object, if you're running under either of those architectures (mod_perl or PerlEx). Since I believe both of them work similarly--ie. compiling a Perl interpreter into the web server and pre-compiling modules--this would imply that when you're doing "similar" things (only compiling once, or using persistent CGI objects), you'll need to call _reset_globals.

    Ah, here it is: this is why you're getting that behavior. In the init subroutine, there's this code:

    # if we get called more than once, we want to initialize # ourselves from the original query (which may be gone # if it was read from STDIN originally.) if (defined(@QUERY_PARAM) && !defined($initializer)) { foreach (@QUERY_PARAM) { $self->param('-name'=>$_,'-value'=>$QUERY_PARAM{$_}); } return; }
    So this is initializing your object with the original query, rather than the new (and possibly different) one.

    And what does _reset_globals do? It calls initialize_globals, which does this:

    undef @QUERY_PARAM;
    There you go. In persistent situations, then, (mod_perl or PerlEx), needs to clean up @QUERY_PARAM--you'll need to fake this in your persistent application, then.

    Calling initialize_globals would be another option--plus it's not "private" (no "_"). :)

      Does delete_all not take care of that? It does undef %{$self} on the CGI object.
        No, that won't do it. @QUERY_PARAM is apparently a package variable. Once you have CGI compiled and in memory, @QUERY_PARAM is set until explicitly reset or undefined.

        Note in the subroutine, the CGI object $q goes out of scope (and would thus be destroyed) at either of the return statements. btrott has it right -- Jellybean is a persistent environment like PERLEX or mod_perl, but CGI doesn't know that. We have to give it a hand.

Re: Caching Issue
by cei (Monk) on May 11, 2000 at 22:30 UTC

    Several other named parameters are recognized. Here's a contrived example that uses them all:

    print $query->header(-type=>'image/gif', -status=>'402 Payment Required', -expires=>'+3d', -cookie=>$my_cookie, -charset=>'UTF-7', -Cost=>'$0.02');

    Some browsers, such as Internet Explorer, cache the output of CGI scripts. Others, such as Netscape Navigator do not. This leads to annoying and inconsistent behavior when going from one browser to another. You can force the behavior to be consistent by using the -expires parameter. When you specify an absolute or relative expiration interval with this parameter, browsers and proxy servers will cache the script's output until the indicated expiration date. The following forms are all valid for the -expires field:

    +30s 30 seconds from now +10m ten minutes from now +1h one hour from now -1d yesterday (i.e. "ASAP!") now immediately +3M in three months +10y in ten years time Thu, 25-Apr-1999 00:40:33 GMT at the indicated time & date
    When you use -expires, the script also generates a correct time stamp for the generated document to ensure that your clock and the browser's clock agree. This allows you to create documents that are reliably cached for short periods of time.

    CGI::expires() is the static function call used internally that turns relative time intervals into HTTP dates. You can call it directly if you wish.