[Catalyst] Still weird behavior in sessions and cookies (Hey Nothingmuch:!)

Bill Moseley moseley at hank.org
Sun Dec 2 20:03:22 GMT 2007


I'm hoping I've got something configured wrong, but session and cookie
handling still seem to have a problems.

This has been an ongoing problem.  I'm all up-to-date with Catalyst
and Plugins.  What I see, once in a while is a state where the browser
returns a cookie.  The returned session id is invalid, so a new
session id is created.  But, when the new Set-Cookie headers is added
it's yet a 2nd session id.

In that case I think the session is getting cleared before the cookie
is created, so when it is created a new session id is generated.

Anyway, that's not much help without some examples.

My code was overriding calculate_session_cookie_expires() to implement
"Remember Me".  So I removed that and now trying to use the 
Session::DynamicExpiry plugin.

So I have some overrides to print out the stages.  So I see:

--- in dispatch --
--- in default -- with sid = 35028fd915cc76898ca6ab47b82d8d990193818c
--- in finailze_headers --
--- in calculate_session_cookie_expires
--- in update_session_cookie

Which seems like a good order.  But sometimes, and I'm not sure, but I
think this happens when a session expires, I see:

--- in dispatch --
--- in calculate_session_cookie_expires
--- in update_session_cookie
--- in default -- with sid = 35028fd915cc76898ca6ab47b82d8d990193818c
--- in finailze_headers --

Which makes it kind of hard to effect the cookies in an action
(default) *after* the cookie has been created.  If you wait for a
while and then reload then this 


Now, specifically, with the Session::DynamicExpiry plugin I'm not
having much luck.  I want a session cookie unless they click "remember
me".

I'll attach a simple application, but I'm seeing a ttl set to zero but
still a date 5 minutes into the future.

  finalize_headers => {
        now => "Sun Dec  2 20:00:00 2007",
        response_cookie => [
              "foo_cookie=4c280674aa273f6b6f624b812938f8dc42208506",
              "path=/",
              "expires=Sun, 02-Dec-2007 20:05:00 GMT",
            ],
        session => {
              __created => 1196625501,
              __time_to_live => 0,
              __updated => 1196625534,
              hello => "howdy",
            },
      },
}

See attached for app to play with.







-- 
Bill Moseley
moseley at hank.org

-------------- next part --------------
package Foo;
use strict;
use warnings;
use Catalyst::Runtime;
use Catalyst (
    'Cache',                    # Configurable cache system
    'Cache::Store::FastMmap',   # Since FastMmap doesn't conform to Cache standards

    'Session',                  # Session Management
    'Session::Store::Cache',    # Use the cache to store sessions
    'Session::State::Cookie',   # And use cookies for state.

    'Session::DynamicExpiry'    # To alter the cookie session time per-session.

);

my $cookie_name = 'foo_cookie';

__PACKAGE__->config(
    name => 'Foo',
    session => {
        cookie_name     => $cookie_name,
        cookie_expires  => 300,   # Use session cookies by default
        expires         => 120, # How long to keep sessions/cooke
    },
    cache => {
        backends => {
            default => {
                class       => 'Cache::FastMmap',
                expire_time => 300,
                share_file  => '/tmp/Foo_share_file',
            },
        },
    },

);

__PACKAGE__->setup;


sub default : Private {
    my ( $self, $c ) = @_;


    $c->session->{hello} = 'howdy'; # Force cookie

    warn "--- in default -- with sid = " . $c->sessionid . "\n";


    my $param = $c->req->parameters->{date} || 0;
    if ( $param eq 'y'  ) {
        $c->res->body( 'cookie should have date' );
        $c->session_time_to_live( 300 );
    }
    elsif ( $param eq 'n' ) {
        delete $c->session->{remember_me};
        $c->res->body( 'remember me deleted -- session cookie' );
        $c->session_time_to_live( 0 );
    }
    else {
        $c->res->body( 'should be no change' );
    }
}

sub update_session_cookie {
    my $c = shift;
    warn "--- in update_session_cookie\n";
    return $c->NEXT::update_session_cookie( @_ );
}

sub calculate_session_cookie_expires {
    my $c = shift;
    warn "--- in calculate_session_cookie_expires\n";
    return $c->NEXT::calculate_session_cookie_expires( @_ );
}

sub dispatch {
    my $c = shift;
    warn "--- in dispatch --\n";
    $c->NEXT::dispatch;
}

sub xdispatch {
    my $c = shift;

    warn "--- in dispatch --\n";

    my $session_expires = defined $c->session_expires ? $c->session_expires :  'not set';
    my $calculate = 'skipped'; # $c->calculate_session_cookie_expires || 'not set';

    for ( $session_expires, $calculate ) {
        next unless $_ && /\d+/;
        $_ = scalar gmtime $_;
    }

    my $cookie = $c->req->cookie( $cookie_name ) ? $c->req->cookie( $cookie_name )->value : 'no cookie provided';

    $c->stash->{stuff}{path} = $c->req->path;

    $c->stash->{stuff}{dispatch} = {
        parameters => $c->req->parameters,
        request_cookie => $cookie,
        sessionid => $c->sessionid || 'none',
        now => scalar gmtime,
        session_expires => $session_expires,
        remember_me => $c->session->{remember_me} || '0',
        calculate => $calculate,
    };

    $c->NEXT::dispatch;

}

sub finalize_headers {
    my $c = shift;

    warn "--- in finailze_headers --\n";

    $c->NEXT::finalize_headers( @_ );

    my $cookie = $c->res->header( 'set-cookie' );
    $cookie = [ split /;\s*/, $cookie ] if $cookie;

    $c->stash->{stuff}{finalize_headers} =  {
        response_cookie => $cookie,
        session => $c->session,
        now => scalar gmtime,
    };

    $c->log->_dump( $c->stash->{stuff} );
}

1;


More information about the Catalyst mailing list