Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Re: mod_perl and multiuser global variables

by maverick (Curate)
on Dec 05, 2005 at 15:31 UTC ( [id://514152] : note . print w/replies, xml ) Need Help??

in reply to mod_perl and multiuser global variables

Try looking at Apache::Session in tandem with Apache::Cookie. The former sets up a hash that can be used to store any user specific data and retrive it in subsequent requests by referencing a unique key. The later helps you manage cookies that can be used to store your unique session key on the browser side.

The problem that you're running into isn't really one of keeping a value shared, it's one of making sure you have the same value for the same browser session. Since HTTP is stateless, you have to have the browser pass back to the server on each request (either via cookie or URL parameter) the unique identifier of the session.

It's Monday AM...let's see if I can whip out a working example.

use Apache::Cookie; use Apache::Session::File; # Inside your mod_perl handler my $cookie = Apache::Cookie->new($r, -name => 'session_id', -expires => '+1D', -domain => '', -path => '/' ); my %session; my $session_id = $cookie->value; # The tie will fail if the session_id isn't valid or is missing. Thus + the need for eval. eval { tie(%session,'Apache::Session::File',$session_id, { Directory => ' +/tmp', LockDirectory => '/tmp' }); }; if ($@) { # bogus session_id. Setting it to undef will cause Apache::Sessio +n to create a new one undef $session_id; tie(%session,'Apache::Session::File',$session_id, { Directory => ' +/tmp', LockDirectory => '/tmp') || die "say something useful"; } if ($session_id != $cookie->value) { # session id has changed or is a new one; update the cookie $cookie->value($session_id); $cookie->bake; } # use %session at will to store user data. $session{'name'} = 'John Doe'; $session{'user_id'} = 123; my $value = $session{'some_data'}; # untie the session after you're done with it untie %session;
Hope this helps

Edit: Typos, add links to cpan


Replies are listed 'Best First'.
Re^2: mod_perl and multiuser global variables
by rsennat (Beadle) on Dec 05, 2005 at 15:44 UTC
    hi wazzuteke, maverick, already im maintaining a session, using CGI::Session. So i will try storing the user info in the session and retrieve it from there.

    but whats the solution in using global variables with mod_perl

    because i have one more problem too. like in the HTML::Template im passing some data. Only in mod_perl, i see that after every reload of the page, the data displayed gets repeatedly displayed. this happens for every reload.

      This is somewhat of a tricky question. Assuming you're running Apache on *nix, each child will be forked off into it's own process. Therefore, if you make a variable global, it will only be global to that child. However, if you make the same variable name global in each child to the same value (via a database, or something similar), then you will have some sort of psudo-global variable. Nonetheless, to have a variable that is global to the Parent and each child is not possible; at least from my knowledge of mod_perl and Apache (someone correct me if I'm wrong here).

      print map{$_.' '}grep{/\w+/}@{[reverse(qw{Perl Code})]} or die while ( 'trying' );
        You can use "global" in memory values, but only as constants. Once you change the value in one place, it only changes there. There's a couple of ways you can make read-write globals. Via a database (as mentioned above), via a second instance of Apache::Session (or CGI::Session) using a constant superLongSecretKeyThatDoesn'tFitTheAutoGenerateFormatKey (ahem) or something like IPC::ShareLite to get true "shared across all children" global variables.

        The Database method might have some performance penalties, but the advantage is that if you every start load balancing web servers, your global variables are still global.

        The Secret Session method, is probably the fastest and easiest to code, since you already have similar parts in your program, but it also has some security implications surrounding your secret session key.

        The IPC::SharedLite method requires installing a new module and learning some new (but realively straight forward) techniques. The amount of "shared" memory on a system is much smaller than "main" memory (at least with Unix) so you can't cram it TOO full, but it will yield the desired effect. For what you're trying to do, I'd be tempted to pick this method.


        Probably that should be right. But then whats the way to override this problem??

        And i just got a thought here, even after using CGI::Session, i will read the user id from the session stored and store it in a variable in that .cgi file. Anyways it becomes a global var. So how do i use it to maintain a persistent data.