Subject: | Changing 'name' for session query/cookie key difficult |
It is very difficult to change the cookie/query session name parameter
in CGI::Session. It requires altering a class method which causes issues
in persistent environments.
The current setup requires client code to do the following to change the
'name' value:
my $old = CGI::Session->name;
CGI::Session->name( 'newname' );
my $s = CGI::Session->new("driver:db_file", $query);
$s->name( 'newname' );
CGI::Session->name( $old );
I propose adding a new 4th parameter to following update to the new/load
interface:
my $s = CGI::Session->new("driver:db_file", $query, \%dsn_args, { name
=> 'newname'} );
now: $s->name eq 'newname'.
The following bug contains patches for Session.pm and name.t test.
Thanks,
Subject: | name.t.patch |
--- orig.name.t 2006-12-04 21:38:13.000000000 -0500
+++ name.t 2008-02-19 13:22:09.043436000 -0500
@@ -3,7 +3,9 @@
use strict;
use diagnostics;
-use Test::More tests => 10;
+use Test::More tests => 15;
+use CGI;
+
use_ok('CGI::Session');
my $session = CGI::Session->new('id:static','testname',{Directory=>'t'});
@@ -23,4 +25,38 @@
ok($session->name eq 'spot','instance method w/ param effective?');
-ok(CGI::Session->name eq 'fluffy','instance method did not affect class method');
\ No newline at end of file
+ok(CGI::Session->name eq 'fluffy','instance method did not affect class method');
+
+## test interface for setting it
+my $s2 = CGI::Session->new(
+ 'id:static',
+ 'testname',
+ { Directory => 't' },
+ { name => 'itchy' }
+);
+
+is $s2->name, 'itchy', 'constructor new with name';
+is CGI::Session->name, 'fluffy', 'constructor name not affecting class';
+is $session->name, 'spot', 'constructor on new session not affecting old';
+
+## test from query
+$s2 = CGI::Session->new(
+ 'id:static',
+ CGI->new( 'itchy=2001' ),
+ { Directory => 't' },
+ { name => 'itchy' }
+);
+
+is $s2->id, 2001, 'session from query with new name';
+
+## should die since it won't find value from query
+eval {
+ $s2 = CGI::Session->new(
+ 'id:static',
+ CGI->new( 'CGISESSID=2001' ),
+ { Directory => 't' },
+ { name => 'itchy' }
+ );
+};
+
+ok $@, "session in query with default name";
Subject: | Session.name.patch |
--- Orig.Session.pm 2006-12-04 20:59:15.000000000 -0500
+++ Session.pm 2008-02-19 13:05:51.944992000 -0500
@@ -556,6 +556,8 @@
=head2 new( $dsn, $query||$sid, \%dsn_args )
+=head2 new( $dsn, $query||$sid, \%dsn_args, \%session_params )
+
Constructor. Returns new session object, or undef on failure. Error message is accessible through L<errstr() - class method|CGI::Session::ErrorHandler/errstr>. If called on an already initialized session will re-initialize the session based on already configured object. This is only useful after a call to L<load()|/"load">.
Can accept up to three arguments, $dsn - Data Source Name, $query||$sid - query object OR a string representing session id, and finally, \%dsn_args, arguments used by $dsn components.
@@ -598,6 +600,18 @@
If called with three arguments, first two will be treated as in the previous example, and third argument will be C<\%dsn_args>, which will be passed to C<$dsn> components (namely, driver, serializer and id generators) for initialization purposes. Since all the $dsn components must initialize to some default value, this third argument should not be required for most drivers to operate properly.
+If called with four arguments, the first three match previous examples. The fourth argument will be a hash reference with parameters to be used by the CGI::Session object. (as named in the example as \%session_params )
+
+The following is a list of the current arguments:
+
+=over
+
+=item *
+
+B<name> - Name to use for the cookie/query parameter name. This defaults to CGISESSID. This can be altered or accessed by C<name> accessor.
+
+=back
+
undef is acceptable as a valid placeholder to any of the above arguments, which will force default behavior.
=head2 load()
@@ -608,6 +622,8 @@
=head2 load($dsn, $query, \%dsn_args);
+=head2 load($dsn, $query, \%dsn_args, \%session_params);
+
Accepts the same arguments as new(), and also returns a new session object, or
undef on failure. The difference is, L<new()|/"new"> can create new session if
it detects expired and non-existing sessions, but C<load()> does not.
@@ -637,7 +653,7 @@
sub load {
my $class = shift;
return $class->set_error( "called as instance method") if ref $class;
- return $class->set_error( "Too many arguments") if @_ > 4;
+ return $class->set_error( "Too many arguments") if @_ > 5;
my $self = bless {
_DATA => {
@@ -661,7 +677,7 @@
_QUERY => undef # query object
}, $class;
- my ($dsn,$query_or_sid,$dsn_args,$update_atime);
+ my ($dsn,$query_or_sid,$dsn_args, $params, $update_atime);
# load($query||$sid)
if ( @_ == 1 ) {
$self->_set_query_or_sid($_[0]);
@@ -669,13 +685,26 @@
# Two or more args passed:
# load($dsn, $query||$sid)
elsif ( @_ > 1 ) {
- ($dsn, $query_or_sid, $dsn_args,$update_atime) = @_;
+ ($dsn, $query_or_sid, $dsn_args, $params ) = @_;
+
+ ## make it backwards compatabile
+ $update_atime = $params;
+
+ ## change values if it is really a hash ref
+ if ( ref $params and ref $params eq 'HASH' ) {
+ ## make sure to update atime parameter
+ $update_atime = $params->{'update_atime'};
+
+ ## update session name
+ $self->{_NAME} = $params->{'name'}
+ if defined $params->{'name'};
+ }
# Since $update_atime is not part of the public API
# we ignore any value but the one we use internally: 0.
if (defined $update_atime and $update_atime ne '0') {
return $class->set_error( "Too many arguments");
- }
+ }
if ( defined $dsn ) { # <-- to avoid 'Uninitialized value...' warnings
$self->{_DSN} = $self->parse_dsn($dsn);