--- /dev/null
+package Plack::Session::Store::File;
+use strict;
+use warnings;
+
+use Storable ();
+
+use parent 'Plack::Session::Store';
+
+use Plack::Util::Accessor qw[
+ dir
+ serializer
+ deserializer
+];
+
+sub new {
+ my ($class, %params) = @_;
+
+ $params{'dir'} ||= '/tmp';
+
+ die "Storage directory (" . $params{'dir'} . ") is not writeable"
+ unless -w $params{'dir'};
+
+ $params{'serializer'} ||= sub { Storable::nstore( @_ ) };
+ $params{'deserializer'} ||= sub { Storable::retrieve( @_ ) };
+
+ $class->SUPER::new( %params );
+}
+
+sub fetch {
+ my ($self, $session_id, $key) = @_;
+ $self->_deserialize( $session_id )->{ $key };
+}
+
+sub store {
+ my ($self, $session_id, $key, $data) = @_;
+ my $store = $self->_deserialize( $session_id );
+ $store->{ $key } = $data;
+ $self->_serialize( $session_id, $store );
+}
+
+sub delete {
+ my ($self, $session_id, $key) = @_;
+ my $store = $self->_deserialize( $session_id );
+ delete $store->{ $key };
+ $self->_serialize( $session_id, $store );
+}
+
+sub cleanup {
+ my ($self, $session_id) = @_;
+ unlink $self->_get_session_file_path( $session_id );
+}
+
+sub _get_session_file_path {
+ my ($self, $session_id) = @_;
+ $self->dir . '/' . $session_id;
+}
+
+sub _serialize {
+ my ($self, $session_id, $value) = @_;
+ my $file_path = $self->_get_session_file_path( $session_id );
+ $self->serializer->( $value, $file_path );
+}
+
+sub _deserialize {
+ my ($self, $session_id) = @_;
+ my $file_path = $self->_get_session_file_path( $session_id );
+ $self->_serialize( $session_id, {} ) unless -f $file_path;
+ $self->deserializer->( $file_path );
+}
+
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Plack::Session::Store::File - Basic file-based session store
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=over 4
+
+=item B<new ( %params )>
+
+=item B<dir>
+
+=item B<serializer>
+
+=item B<deserializer>
+
+=back
+
+=head1 BUGS
+
+All complex software has bugs lurking in it, and this module is no
+exception. If you find a bug please either email me, or add the bug
+to cpan-RT.
+
+=head1 AUTHOR
+
+Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2009 Infinity Interactive, Inc.
+
+L<http://www.iinteractive.com>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+
+use_ok( $_ ) || BAIL_OUT foreach qw[
+ Plack::Middleware::Session
+ Plack::Session
+ Plack::Session::Store
+ Plack::Session::Store::CHI
+ Plack::Session::Store::File
+ Plack::Session::State
+ Plack::Session::State::Cookie
+];
+
+done_testing;
\ No newline at end of file
use warnings;
use Test::More;
-use Test::Exception;
use Plack::Request;
-
use Plack::Session;
use Plack::Session::State;
use Plack::Session::Store;
-sub request {
- open my $in, '<', \do { my $d };
- my $env = {
- 'psgi.version' => [ 1, 0 ],
- 'psgi.input' => $in,
- 'psgi.errors' => *STDERR,
- 'psgi.url_scheme' => 'http',
- SERVER_PORT => 80,
- REQUEST_METHOD => 'GET',
- };
- my $r = Plack::Request->new( $env );
- $r->parameters( @_ );
- $r;
-}
-
-my $storage = Plack::Session::Store->new;
-my $state = Plack::Session::State->new;
-
-my @sids;
-{
- my $r = request();
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
-
- ok(!$s->get('foo'), '... no value stored in foo for session');
-
- lives_ok {
- $s->set( foo => 'bar' );
- } '... set the value successfully in session';
-
- is($s->get('foo'), 'bar', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
-
-{
- my $r = request();
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
-
- isnt($sids[0], $sids[1], "no same Session ID");
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- lives_ok {
- $s->set( foo => 'baz' );
- } '... set the value successfully';
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[0], '... got a basic session id');
-
- is($s->get('foo'), 'bar', '... got the value for foo back successfully from session');
-
- lives_ok {
- $s->remove( 'foo' );
- } '... removed the foo value successfully from session';
-
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
-
-
-{
- my $r = request({ plack_session => $sids[1] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[1], '... got a basic session id');
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[0], '... got a basic session id');
-
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- lives_ok {
- $s->set( bar => 'baz' );
- } '... set the bar value successfully in session';
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->get('bar'), 'baz', '... got the bar value back successfully from session');
-
- lives_ok {
- $s->expire;
- } '... expired session successfully';
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
- isnt($s->id, $sids[0], 'expired ... got a new session id');
-
- ok(!$s->get('bar'), '... no bar value stored');
-}
-
-{
- my $r = request({ plack_session => $sids[1] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[1], '... got a basic session id');
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-}
+use t::lib::TestSession;
+
+t::lib::TestSession::run_all_tests(
+ store => Plack::Session::Store->new,
+ state => Plack::Session::State->new,
+ request_creator => sub {
+ open my $in, '<', \do { my $d };
+ my $env = {
+ 'psgi.version' => [ 1, 0 ],
+ 'psgi.input' => $in,
+ 'psgi.errors' => *STDERR,
+ 'psgi.url_scheme' => 'http',
+ SERVER_PORT => 80,
+ REQUEST_METHOD => 'GET',
+ };
+ my $r = Plack::Request->new( $env );
+ $r->parameters( @_ );
+ $r;
+ },
+);
done_testing;
use warnings;
use Test::More;
-use Test::Exception;
use Plack::Request;
-
use Plack::Session;
use Plack::Session::State::Cookie;
use Plack::Session::Store;
-sub request {
- my $cookies = shift;
- open my $in, '<', \do { my $d };
- my $env = {
- 'psgi.version' => [ 1, 0 ],
- 'psgi.input' => $in,
- 'psgi.errors' => *STDERR,
- 'psgi.url_scheme' => 'http',
- SERVER_PORT => 80,
- REQUEST_METHOD => 'GET',
- HTTP_COOKIE => join "; " => map { $_ . "=" . $cookies->{ $_ } } keys %$cookies,
- };
- return Plack::Request->new( $env );
-}
-
-my $storage = Plack::Session::Store->new;
-my $state = Plack::Session::State::Cookie->new;
-
-my @sids;
-{
- my $r = request();
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
-
- ok(!$s->get('foo'), '... no value stored in foo for session');
-
- lives_ok {
- $s->set( foo => 'bar' );
- } '... set the value successfully in session';
-
- is($s->get('foo'), 'bar', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[0],
- path => '/'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request();
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
-
- isnt($sids[0], $sids[1], "... not the same session id");
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- lives_ok {
- $s->set( foo => 'baz' );
- } '... set the value successfully';
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[1],
- path => '/'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[0], '... got a basic session id');
-
- is($s->get('foo'), 'bar', '... got the value for foo back successfully from session');
-
- lives_ok {
- $s->remove( 'foo' );
- } '... removed the foo value successfully from session';
-
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[0],
- path => '/'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[1] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[1], '... got a basic session id');
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[1],
- path => '/'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[0], '... got a basic session id');
-
- ok(!$s->get('foo'), '... no value stored for foo in session');
-
- lives_ok {
- $s->set( bar => 'baz' );
- } '... set the bar value successfully in session';
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[0],
- path => '/'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->get('bar'), 'baz', '... got the bar value back successfully from session');
-
- lives_ok {
- $s->expire;
- } '... expired session successfully';
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[0],
- path => '/',
- expires => '0'
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[0] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- push @sids, $s->id;
- isnt($s->id, $sids[0], 'expired ... got a new session id');
-
- ok(!$s->get('bar'), '... no bar value stored');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[2],
- path => '/',
- }
- },
- '... got the right cookies in the response'
- );
-}
-
-{
- my $r = request({ plack_session => $sids[1] });
-
- my $s = Plack::Session->new(
- state => $state,
- store => $storage,
- request => $r,
- );
-
- is($s->id, $sids[1], '... got a basic session id');
-
- is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
-
- my $resp = $r->new_response;
-
- lives_ok {
- $s->finalize( $resp );
- } '... finalized session successfully';
-
- is_deeply(
- $resp->cookies,
- {
- plack_session => {
- value => $sids[1],
- path => '/',
- }
- },
- '... got the right cookies in the response'
- );
-}
+use t::lib::TestSession;
+
+t::lib::TestSession::run_all_tests(
+ store => Plack::Session::Store->new,
+ state => Plack::Session::State::Cookie->new,
+ request_creator => sub {
+ my $cookies = shift;
+ open my $in, '<', \do { my $d };
+ my $env = {
+ 'psgi.version' => [ 1, 0 ],
+ 'psgi.input' => $in,
+ 'psgi.errors' => *STDERR,
+ 'psgi.url_scheme' => 'http',
+ SERVER_PORT => 80,
+ REQUEST_METHOD => 'GET',
+ HTTP_COOKIE => join "; " => map { $_ . "=" . $cookies->{ $_ } } keys %$cookies,
+ };
+ return Plack::Request->new( $env );
+ },
+ response_test => sub {
+ my ($response, $session_id, $check_expired) = @_;
+ is_deeply(
+ $response->cookies,
+ {
+ plack_session => {
+ value => $session_id,
+ path => '/',
+ ($check_expired
+ ? ( expires => '0' )
+ : ())
+ }
+ },
+ '... got the right cookies in the response'
+ );
+ }
+);
done_testing;
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use File::Spec;
+
+use Test::More;
+
+use Plack::Request;
+use Plack::Session;
+use Plack::Session::State::Cookie;
+use Plack::Session::Store::File;
+
+use t::lib::TestSession;
+
+my $TMP = File::Spec->catdir('t', 'tmp');
+
+t::lib::TestSession::run_all_tests(
+ store => Plack::Session::Store::File->new( dir => $TMP ),
+ state => Plack::Session::State->new,
+ request_creator => sub {
+ open my $in, '<', \do { my $d };
+ my $env = {
+ 'psgi.version' => [ 1, 0 ],
+ 'psgi.input' => $in,
+ 'psgi.errors' => *STDERR,
+ 'psgi.url_scheme' => 'http',
+ SERVER_PORT => 80,
+ REQUEST_METHOD => 'GET',
+ };
+ my $r = Plack::Request->new( $env );
+ $r->parameters( @_ );
+ $r;
+ },
+);
+
+unlink $_ foreach glob( File::Spec->catdir($TMP, '*') );
+
+done_testing;
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use File::Spec;
+
+use Test::More;
+
+BEGIN {
+ eval "use YAML";
+ plan skip_all => "This test requires YAML" if $@;
+}
+
+use Plack::Request;
+use Plack::Session;
+use Plack::Session::State::Cookie;
+use Plack::Session::Store::File;
+
+use t::lib::TestSession;
+
+my $TMP = File::Spec->catdir('t', 'tmp');
+
+t::lib::TestSession::run_all_tests(
+ store => Plack::Session::Store::File->new(
+ dir => $TMP,
+ serializer => sub { YAML::DumpFile( reverse @_ ) }, # YAML takes it's args the opposite of Storable
+ deserializer => sub { YAML::LoadFile( @_ ) },
+ ),
+ state => Plack::Session::State->new,
+ request_creator => sub {
+ open my $in, '<', \do { my $d };
+ my $env = {
+ 'psgi.version' => [ 1, 0 ],
+ 'psgi.input' => $in,
+ 'psgi.errors' => *STDERR,
+ 'psgi.url_scheme' => 'http',
+ SERVER_PORT => 80,
+ REQUEST_METHOD => 'GET',
+ };
+ my $r = Plack::Request->new( $env );
+ $r->parameters( @_ );
+ $r;
+ },
+);
+
+unlink $_ foreach glob( File::Spec->catdir($TMP, '*') );
+
+done_testing;
--- /dev/null
+package t::lib::TestSession;
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+
+sub run_all_tests {
+ my %params = @_;
+
+ my (
+ $request_creator,
+ $state,
+ $storage,
+ $response_test
+ ) = @params{qw[
+ request_creator
+ state
+ store
+ response_test
+ ]};
+
+ $response_test = sub {
+ my ($response, $session_id, $check_expired) = @_;
+ };
+
+ my @sids;
+ {
+ my $r = $request_creator->();
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ push @sids, $s->id;
+
+ ok(!$s->get('foo'), '... no value stored in foo for session');
+
+ lives_ok {
+ $s->set( foo => 'bar' );
+ } '... set the value successfully in session';
+
+ is($s->get('foo'), 'bar', '... got the foo value back successfully from session');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[0] );
+ }
+
+ {
+ my $r = $request_creator->();
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ push @sids, $s->id;
+
+ isnt($sids[0], $sids[1], "no same Session ID");
+ ok(!$s->get('foo'), '... no value stored for foo in session');
+
+ lives_ok {
+ $s->set( foo => 'baz' );
+ } '... set the value successfully';
+
+ is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[1] );
+ }
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[0] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ is($s->id, $sids[0], '... got a basic session id');
+
+ is($s->get('foo'), 'bar', '... got the value for foo back successfully from session');
+
+ lives_ok {
+ $s->remove( 'foo' );
+ } '... removed the foo value successfully from session';
+
+ ok(!$s->get('foo'), '... no value stored for foo in session');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[0] );
+ }
+
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[1] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ is($s->id, $sids[1], '... got a basic session id');
+
+ is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[1] );
+ }
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[0] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ is($s->id, $sids[0], '... got a basic session id');
+
+ ok(!$s->get('foo'), '... no value stored for foo in session');
+
+ lives_ok {
+ $s->set( bar => 'baz' );
+ } '... set the bar value successfully in session';
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[0] );
+ }
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[0] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ is($s->get('bar'), 'baz', '... got the bar value back successfully from session');
+
+ lives_ok {
+ $s->expire;
+ } '... expired session successfully';
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[0], 1 );
+ }
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[0] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ push @sids, $s->id;
+ isnt($s->id, $sids[0], 'expired ... got a new session id');
+
+ ok(!$s->get('bar'), '... no bar value stored');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[2] );
+ }
+
+ {
+ my $r = $request_creator->({ plack_session => $sids[1] });
+
+ my $s = Plack::Session->new(
+ state => $state,
+ store => $storage,
+ request => $r,
+ );
+
+ is($s->id, $sids[1], '... got a basic session id');
+
+ is($s->get('foo'), 'baz', '... got the foo value back successfully from session');
+
+ my $resp = $r->new_response;
+
+ lives_ok {
+ $s->finalize( $resp );
+ } '... finalized session successfully';
+
+ $response_test->( $resp, $sids[1] );
+ }
+}
+
+1;
\ No newline at end of file