Subject: | PATCH: Add multiple session configs to CAP::Session |
Attached is a patch that adds a SESSION_NAME parameter to
session_config, and lets you retrieve different session objects by name.
This can be used in conjunction with separate cookie names to maintain
multiple independent session cookies (if that's your thing. :) ).
The diff changes Session.pm considerably but all tests pass
(09_options.t changed slightly because it peeks inside the object;
13_names.t added to test the new stuff.)
I haven't used this for anything yet and I encourage significantly more
real-world testing. The idea for the feature was inspired by this thread:
http://perlmonks.org/?node_id=695764
Mike Friedman
Subject: | capsess.diff |
diff -rN CGI-Application-Plugin-Session-1.03/lib/CGI/Application/Plugin/Session.pm CGI-Application-Plugin-Session-1.03-exp/lib/CGI/Application/Plugin/Session.pm
29c29,32
< if (!$self->{__CAP__SESSION_OBJ}) {
---
> my $name = $self->{__CAP__SESSION_DEFAULT} ||= 'DEFAULT';
> $name = $_[0] if $_[0];
>
> if (!$self->{__CAP__SESSION_OBJ}{$name}) {
31c34
< $self->{__CAP__SESSION_CONFIG} = {} unless $self->{__CAP__SESSION_CONFIG};
---
> $self->{__CAP__SESSION_CONFIG}{$name} = {} unless $self->{__CAP__SESSION_CONFIG}{$name};
35,36c38,39
< my @params = ($self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS}) ?
< @{ $self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS} } :
---
> my @params = ($self->{__CAP__SESSION_CONFIG}{$name}{CGI_SESSION_OPTIONS}) ?
> @{ $self->{__CAP__SESSION_CONFIG}{$name}{CGI_SESSION_OPTIONS} } :
48,49c51,52
< $self->{__CAP__SESSION_OBJ} = CGI::Session->new(@params);
< if (! $self->{__CAP__SESSION_OBJ} ) {
---
> $self->{__CAP__SESSION_OBJ}{$name} = CGI::Session->new(@params);
> if (! $self->{__CAP__SESSION_OBJ}{$name} ) {
55,56c58,59
< if ($self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY} && $self->{__CAP__SESSION_OBJ}->is_new) {
< $self->{__CAP__SESSION_OBJ}->expire($self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY});
---
> if ($self->{__CAP__SESSION_CONFIG}{$name}{DEFAULT_EXPIRY} && $self->{__CAP__SESSION_OBJ}{$name}->is_new) {
> $self->{__CAP__SESSION_OBJ}{$name}->expire($self->{__CAP__SESSION_CONFIG}{$name}{DEFAULT_EXPIRY});
64c67
< if (!defined $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE} || $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE}) {
---
> if (!defined $self->{__CAP__SESSION_CONFIG}{$name}{SEND_COOKIE} || $self->{__CAP__SESSION_CONFIG}{$name}{SEND_COOKIE}) {
66c69,72
< if (!$cid || $cid ne $self->{__CAP__SESSION_OBJ}->id || $self->{__CAP__SESSION_OBJ}->expire()) {
---
> if (!$cid || $cid ne $self->{__CAP__SESSION_OBJ}{$name}->id || $self->{__CAP__SESSION_OBJ}{$name}->expire()) {
> # hack around passing session name directly since this method
> # can be called with %options from the outside
> $self->{__CAP__SESSION_TMP_SNAME} = $name;
67a74
> delete $self->{__CAP__SESSION_TMP_SNAME};
72c79
< return $self->{__CAP__SESSION_OBJ};
---
> return $self->{__CAP__SESSION_OBJ}{$name};
79d85
< die "Calling session_config after the session has already been created" if (defined $self->{__CAP__SESSION_OBJ});
87a94,101
> # check if we already have a default session conf
> my $name = delete( $props->{SESSION_NAME} ) || 'DEFAULT';
> unless( $self->{__CAP__SESSION_DEFAULT} ) {
> $self->{__CAP__SESSION_DEFAULT} = $name;
> }
>
> die "Calling session_config after the session has already been created (session=$name)" if (exists $self->{__CAP__SESSION_OBJ}{$name});
>
91c105
< $self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS} = delete $props->{CGI_SESSION_OPTIONS};
---
> $self->{__CAP__SESSION_CONFIG}{$name}{CGI_SESSION_OPTIONS} = delete $props->{CGI_SESSION_OPTIONS};
97c111
< $self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS} = delete $props->{COOKIE_PARAMS};
---
> $self->{__CAP__SESSION_CONFIG}{$name}{COOKIE_PARAMS} = delete $props->{COOKIE_PARAMS};
102c116
< $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE} = (delete $props->{SEND_COOKIE}) ? 1 : 0;
---
> $self->{__CAP__SESSION_CONFIG}{$name}{SEND_COOKIE} = (delete $props->{SEND_COOKIE}) ? 1 : 0;
107c121
< $self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY} = delete $props->{DEFAULT_EXPIRY};
---
> $self->{__CAP__SESSION_CONFIG}{$name}{DEFAULT_EXPIRY} = delete $props->{DEFAULT_EXPIRY};
120a135,136
> my $name = $self->{__CAP__SESSION_TMP_SNAME} || $self->{__CAP__SESSION_DEFAULT};
>
122,123c138,139
< if ($self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS}) {
< %options = (%{ $self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS} }, %options);
---
> if ($self->{__CAP__SESSION_CONFIG}{$name}{COOKIE_PARAMS}) {
> %options = (%{ $self->{__CAP__SESSION_CONFIG}{$name}{COOKIE_PARAMS} }, %options);
126c142
< if (!$self->{__CAP__SESSION_OBJ}) {
---
> if (!$self->{__CAP__SESSION_OBJ}{$name}) {
176a193,194
> my $name = $self->{__CAP__SESSION_DEFAULT};
>
179c197
< if ( $self->{'__CAP__SESSION_CONFIG'}->{'SEND_COOKIE'} ) {
---
> if ( $self->{__CAP__SESSION_CONFIG}{$name}{SEND_COOKIE} ) {
181,182c199,200
< if ( $self->{'__CAP__SESSION_CONFIG'}->{'COOKIE_PARAMS'} ) {
< %options = ( %{ $self->{'__CAP__SESSION_CONFIG'}->{'COOKIE_PARAMS'} }, %options );
---
> if ( $self->{__CAP__SESSION_CONFIG}{$name}{COOKIE_PARAMS} ) {
> %options = ( %{ $self->{__CAP__SESSION_CONFIG}{$name}{COOKIE_PARAMS} }, %options );
218c236,239
< return defined $self->{__CAP__SESSION_OBJ};
---
>
> my $name = $self->{__CAP__SESSION_DEFAULT};
>
> return defined $self->{__CAP__SESSION_OBJ}{$name};
224c245,247
<
---
>
> my $name = $self->{__CAP__SESSION_DEFAULT};
>
229c252
< $self->{__CAP__SESSION_OBJ} = undef;
---
> $self->{__CAP__SESSION_OBJ}{$name} = undef;
293a317,324
> (WARNING: EXPERIMENTAL). Pass this method a session configuration name to retrieve a named configuration
> that you set up with the C<SESSION_NAME> parameter in C<session_config> (see below.)
>
> my $foo_session = $self->session( 'foo' );
> my $thing = $self->session( 'bar' )->param( 'thing' );
>
>
>
346a378,384
> =item SESSION_NAME
>
> (WARNING: EXPERIMENTAL). This lets you associate a name with a particular session configuration,
> and can be used in conjunction with the C<-name> parameter in C<COOKIE_PARAMS> to maintain
> multiple simultaneous session cookies. You can call C<session_config> multiple times
> with a different C<SESSION_NAME> parameter each time to set up multiple configurations.
>
diff -rN CGI-Application-Plugin-Session-1.03/t/09_options.t CGI-Application-Plugin-Session-1.03-exp/t/09_options.t
1c1
< use Test::More tests => 9;
---
> use Test::More tests => 13;
23,26c23,41
< ok($t1_obj->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS}, 'CGI_SESSION_OPTIONS defined');
< ok($t1_obj->{__CAP__SESSION_CONFIG}->{SEND_COOKIE}, 'SEND_COOKIE defined');
< ok($t1_obj->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY}, 'DEFAULT_EXPIRY defined');
< ok($t1_obj->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS}, 'COOKIE_PARAMS defined');
---
> ok($t1_obj->{__CAP__SESSION_CONFIG}{DEFAULT}{CGI_SESSION_OPTIONS}, 'CGI_SESSION_OPTIONS defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{DEFAULT}{SEND_COOKIE}, 'SEND_COOKIE defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{DEFAULT}{DEFAULT_EXPIRY}, 'DEFAULT_EXPIRY defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{DEFAULT}{COOKIE_PARAMS}, 'COOKIE_PARAMS defined');
>
>
> $t1_obj->session_config(
> SESSION_NAME => 'foobar',
> CGI_SESSION_OPTIONS => [ "driver:File", $t1_obj->query, {Directory=>'t/'} ],
> SEND_COOKIE => 1,
> DEFAULT_EXPIRY => '+1y',
> COOKIE_PARAMS => { -domain => 'example.com' }
> );
>
> ok($t1_obj->{__CAP__SESSION_CONFIG}{foobar}{CGI_SESSION_OPTIONS}, 'Named CGI_SESSION_OPTIONS defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{foobar}{SEND_COOKIE}, 'Named SEND_COOKIE defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{foobar}{DEFAULT_EXPIRY}, 'Named DEFAULT_EXPIRY defined');
> ok($t1_obj->{__CAP__SESSION_CONFIG}{foobar}{COOKIE_PARAMS}, 'Named COOKIE_PARAMS defined');
>
diff -rN CGI-Application-Plugin-Session-1.03/t/13_names.t CGI-Application-Plugin-Session-1.03-exp/t/13_names.t
0a1,41
> use Test::More tests => 5;
> use File::Spec;
> BEGIN { use_ok('CGI::Application::Plugin::Session') };
>
> use lib './t';
> use strict;
>
> use TestAppNames;
> use CGI;
>
> my $t1_obj = TestAppNames->new( QUERY => CGI->new );
>
>
> $t1_obj->session_config(
> SESSION_NAME => 'foobar',
> CGI_SESSION_OPTIONS => [ "driver:File", $t1_obj->query, {Directory=>'t/'} ],
> SEND_COOKIE => 1,
> DEFAULT_EXPIRY => '+1y',
> COOKIE_PARAMS => { -domain => 'example.com', -name => 'FOOBARSESS' }
> );
>
>
> $t1_obj->session_config(
> SESSION_NAME => 'barbaz',
> CGI_SESSION_OPTIONS => [ "driver:File", $t1_obj->query, {Directory=>'t/'} ],
> SEND_COOKIE => 1,
> DEFAULT_EXPIRY => '+1y',
> COOKIE_PARAMS => { -domain => 'baz.example.com', -name => 'BARBAZSESS' }
> );
>
>
>
>
> my $t1_output = $t1_obj->run();
>
>
> like($t1_output, qr/foo session created/, 'foo session created');
> like($t1_output, qr/Set-Cookie: FOOBARSESS=[a-zA-Z0-9]+/, 'foo session cookie set');
>
> like($t1_output, qr/bar session created/, 'bar session created');
> like($t1_output, qr/Set-Cookie: BARBAZSESS=[a-zA-Z0-9]+/, 'bar session cookie set');
diff -rN CGI-Application-Plugin-Session-1.03/t/TestAppNames.pm CGI-Application-Plugin-Session-1.03-exp/t/TestAppNames.pm
0a1,36
> package TestAppNames;
>
> use strict;
>
> use CGI::Application;
> use CGI::Application::Plugin::Session;
> @TestAppNames::ISA = qw(CGI::Application);
>
>
> sub setup {
> my $self = shift;
>
> $self->start_mode('test_mode');
>
> $self->run_modes(test_mode => 'test_mode' );
> }
>
> sub test_mode {
> my $self = shift;
> my $output = '';
>
>
> my $foos = $self->session( 'foobar' );
> my $bars = $self->session( 'barbaz' );
>
> $output .= $foos->is_new ? "foo session created\n" : "session found\n";
> $output .= "id=".$foos->id."\n";
>
> $output .= $bars->is_new ? "bar session created\n" : "session found\n";
> $output .= "id=".$bars->id."\n";
>
> return $output;
> }
>
>
> 1;