Why does CGI::Session new and load fail ( couldn't thaw() )?-Collection of common programming errors

I tried using the CGI::Session Library but for some reason my code won’t keep a persistant session … this is using Perl Moose for OOP, and is using Moose builders to instantiate the _cgi and _sss (session) parameters of a My::Session object…

UPDATED CODE

My::Role::PersistantData

package My::Role::PersistsData;

use Moose::Role;
use namespace::autoclean;
  has '_cgi' => (
           is        => 'rw', 
           isa       => 'Maybe[CGI]', 
           builder   => '_build_cgi'
  );

  has '_sss' => (
           is        => 'rw', 
           isa       => 'Maybe[CGI::Session]',
           builder   => '_build_sss'
  );

My::Session

    package My::Session;

    use Moose;
    use namespace::autoclean;
    with 'My::Role::PersistsData';  

    use CGI;
    use CGI::Session ('-ip_match');
    use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;

    sub start{
      my($self) = @_;
      my $cgi = $self->cgi();
      $self->log("Session Started!");        
    }


    sub cgi{
      my($self) = @_;
      $self->_cgi = $self->_build_cgi() unless $self->_cgi;
      return ($self->_cgi); 
    }


    sub _build_cgi{
      my($self) = @_; 
      my $cgi = CGI->new();

      if(!$cgi){
        #print "mising cgi";          
      }

      return ( $cgi );
    }


    sub _build_sss{
          my($self) = @_;
          my $cgi = $self->cgi(); 

          my $sid = $cgi->cookie("CGISESSID") || $cgi->param('CGISESSID') || undef;

          $self->log("Session ID Initial is: ".($sid?$sid:"undef"));

          my $sss =  CGI::Session->new(undef, $cgi, {Directory=>'tmp'})  or die CGI::Session->errstr;



          my $cookie = $cgi->cookie(CGISESSID => $sss->id() );


          $self->log("Resulting Session ID is: ".$sid." cookie is: ".$cookie);    

          print $cgi->header( -cookie=>$cookie );

          return ( $sss );
    }

main.pl

use Data::Dumper; 
$Data::Dumper::Sortkeys = 1;

use CGI;
use CGI::Carp qw(fatalsToBrowser);
use My::Session;

$| = 1;
$, = " ";
$\ = "\n 
"; my $sss = My::Session->new(); $sss->start(); print Dumper($sss);

It’s pretty weird because the first time I run this I get an actual CGISESSION ID and I am able to carry it over on a page refresh…

however if I load the page again, suddenly the $sss (session) comes back as undefined, when it should return a new Session object:

 $sss = new CGI::Session("driver:File", $sid, {Directory=>'/tmp'})

for some reason $sss is coming back as undefined, which means it didnt initiate a new Session. A few tweaks to my code revealed this error:

new(): failed: load(): couldn't thaw() data using CGI::Session::Serialize::default:thaw(): couldn't thaw. syntax error at (eval 253) line 2, near "/>" 

I also snooped around in CGI::Session.pm and found where this error was being thrown at, I guess it’s not able to parse _DATA or even read it…because of some strange characters… “/>”

CGI::Session.pm

....
    $self->{_DATA} = $self->{_OBJECTS}->{serializer}->thaw($raw_data);
    unless ( defined $self->{_DATA} ) {
        #die $raw_data . "\n";
        return $self->set_error( "load(): couldn't thaw() data using $self->{_OBJECTS}->{serializer} :" .
                                $self->{_OBJECTS}->{serializer}->errstr );
    }

Any idea why this isnt working?

  1. For some reason you can’t use Data::Dumper or other HTML tags with CGI::Session

    Answer found here and here

    Removing Dumper and HTML output fixed this problem — kind of —

    updated

    Apparently you have to use escapes

     $cgi->escapeHTML ( Dumper($session) );
    

    and that FINALLY resolves this problem.

    Perl is a pain!

  2. Most likely this is due to a different session cookie being sent (been there, hit that wall with head. HARD).

    Please print the session cookie value being used to store the session initially as well as session cookie value supplied by subsequent request.

    If they are indeed different, you have 2 options:

    • Investigate why different session cookie is sent by the browser in subsequent requests and fix that issue somehow.

      I was never able to find conclusive answer but my app consisted of a frame with internal so I suspect it was due to that.

    • If like me you can’t find the root cause, you can also work around this.

      My workaround: explicitly STORING the original session cookie value as a form variable being passed around 100% of your code pieces.

      Then re-initialize session object with correct cookie value before your server side code requests session data.

      Not very secure, annoying, hard to get right. But works. I wouldn’t recommend it except as a uber-last-resort hack

  3. Perhaps you could try (or at least look at the code to see how it works) for some stateful webapp module. I have used Continuity, very cool stuff.