Middleware added, cookie state added, and example psgi app
Stevan Little [Sat, 12 Dec 2009 02:26:07 +0000 (21:26 -0500)]
examples/app.psgi [new file with mode: 0644]
lib/Plack/Middleware/Session.pm [new file with mode: 0644]
lib/Plack/Session.pm
lib/Plack/Session/State.pm
lib/Plack/Session/State/Cookie.pm [new file with mode: 0644]
t/001_basic.t

diff --git a/examples/app.psgi b/examples/app.psgi
new file mode 100644 (file)
index 0000000..c46d7f1
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+
+use Plack::Session;
+use Plack::Session::State;
+use Plack::Session::State::Cookie;
+use Plack::Session::Store;
+use Plack::Middleware::Session;
+
+my $app = Plack::Middleware::Session->wrap(
+    sub {
+        my $env = shift;
+        my $r   = Plack::Request->new( $env );
+
+        return [ 404, [], [] ] if $r->path_info =~ /favicon.ico/;
+
+        my $session = $env->{'psgix.session'};
+
+        my $id      = $session->id;
+        my $counter = $session->get('counter') || 0;
+
+        $session->set( 'counter' => $counter + 1 );
+
+        my $resp;
+
+        if ( $r->param( 'logout' ) ) {
+            $session->expire;
+            $resp = $r->new_response;
+            $resp->redirect( $r->path_info );
+        }
+        else {
+            $resp = $r->new_response(
+                200,
+                [ 'Content-Type' => 'text/html' ],
+                [
+                    qq{
+                        <html>
+                        <head>
+                            <title>Plack::Middleware::Session Example</title>
+                        </head>
+                        <body>
+                            <h1>Session Id: ${id}</h1>
+                            <h2>Counter: ${counter}</h2>
+                            <hr/>
+                            <a href="/?logout=1">Logout</a>
+                        </body>
+                        </html>
+                    }
+                ]
+            );
+        }
+
+        $resp->finalize;
+    },
+    state => Plack::Session::State::Cookie->new,
+    store => Plack::Session::Store->new,
+);
\ No newline at end of file
diff --git a/lib/Plack/Middleware/Session.pm b/lib/Plack/Middleware/Session.pm
new file mode 100644 (file)
index 0000000..4a345f1
--- /dev/null
@@ -0,0 +1,32 @@
+package Plack::Middleware::Session;
+use strict;
+use warnings;
+
+use Plack::Session;
+use Plack::Request;
+use Plack::Response;
+
+use parent 'Plack::Middleware';
+
+use Plack::Util::Accessor qw( state store );
+
+sub call {
+    my $self = shift;
+    my $env  = shift;
+
+    $env->{'psgix.session'} = Plack::Session->new(
+        state   => $self->state,
+        store   => $self->store,
+        request => Plack::Request->new( $env )
+    );
+
+    my $res = Plack::Response->new( @{ $self->app->( $env ) } );
+
+    $env->{'psgix.session'}->finalize( $res );
+
+    $res->finalize();
+}
+
+1;
+
+__END__
index 14c93b6..5a41010 100644 (file)
@@ -43,8 +43,9 @@ sub expire {
 }
 
 sub finalize {
-    my $self = shift;
-    $self->store->persist( $self->id )
+    my ($self, $response) = @_;
+    $self->store->persist( $self->id, $response );
+    $self->state->finalize( $self->id, $response );
 }
 
 1;
\ No newline at end of file
index d1407c1..f4141a9 100644 (file)
@@ -2,18 +2,12 @@ package Plack::Session::State;
 use strict;
 use warnings;
 
-use Plack::Util::Accessor qw[
-    generator
-    extractor
-    session_key
-];
+use Plack::Util::Accessor qw[ session_key ];
 
 sub new {
     my ($class, %params) = @_;
     bless {
         session_key => $params{ session_key } || 'plack_session',
-        generator   => do { my $id = 1; sub { $id++ } },
-        extractor   => sub { $_[0]->param( $_[1] ) },
         expired     => {}
     } => $class;
 }
@@ -23,25 +17,34 @@ sub expire_session_id {
     $self->{expired}->{ $id }++;
 }
 
-sub extract {
-    my ($self, $request) = @_;
-    my $id = $self->extractor->( $request, $self->session_key );
+sub check_expired {
+    my ($self, $id) = @_;
     return unless $id && not exists $self->{expired}->{ $id };
     return $id;
 }
 
-sub generate {
-    my $self = shift;
-    $self->generator->()
-}
-
 # given a request, get the
 # session id from it
 sub get_session_id {
     my ($self, $request) = @_;
     $self->extract( $request )
         ||
-    $self->generate
+    $self->generate( $request )
+}
+
+sub extract {
+    my ($self, $request) = @_;
+    $self->check_expired( $request->param( $self->session_key ) );
+}
+
+{
+    my $id = 1;
+    sub generate { $id++ }
+}
+
+sub finalize {
+    my ($self, $id, $response) = @_;
+    ();
 }
 
 1;
\ No newline at end of file
diff --git a/lib/Plack/Session/State/Cookie.pm b/lib/Plack/Session/State/Cookie.pm
new file mode 100644 (file)
index 0000000..d1727b2
--- /dev/null
@@ -0,0 +1,31 @@
+package Plack::Session::State::Cookie;
+use strict;
+use warnings;
+
+use parent 'Plack::Session::State';
+
+use Plack::Util::Accessor qw[ path domain expires secure ];
+
+sub expire_session_id {
+    my ($self, $id) = @_;
+    $self->SUPER::expire_session_id( $id );
+    $self->expires( 0 );
+}
+
+sub extract {
+    my ($self, $request) = @_;
+    $self->check_expired( ( $request->cookie( $self->session_key ) || return )->value );
+}
+
+sub finalize {
+    my ($self, $id, $response) = @_;
+    $response->cookies->{ $self->session_key } = +{
+        value => $id,
+        path  => ($self->path || '/'),
+        ( $self->domain  ? ( domain  => $self->domain  ) : () ),
+        ( $self->expires ? ( expires => $self->expires ) : () ),
+        ( $self->secure  ? ( secure  => $self->secure  ) : () ),
+    };
+}
+
+1;
\ No newline at end of file
index ac90b03..3291b5c 100644 (file)
@@ -31,10 +31,12 @@ my $storage = Plack::Session::Store->new;
 my $state   = Plack::Session::State->new;
 
 {
+    my $r = request();
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request(),
+        request => $r,
     );
 
     is($s->id, 1, '... got a basic session id (1)');
@@ -47,16 +49,20 @@ my $state   = Plack::Session::State->new;
 
     is($s->get('foo'), 'bar', '... got the foo value back successfully from session (1)');
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (1) successfully';
 }
 
 {
+    my $r = request();
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request(),
+        request => $r,
     );
 
     is($s->id, 2, '... got a basic session id (2)');
@@ -69,16 +75,20 @@ my $state   = Plack::Session::State->new;
 
     is($s->get('foo'), 'baz', '... got the foo value back successfully from session (2)');
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (2) successfully';
 }
 
 {
+    my $r = request({ plack_session => 1 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 1 }),
+        request => $r,
     );
 
     is($s->id, 1, '... got a basic session id (1)');
@@ -91,33 +101,41 @@ my $state   = Plack::Session::State->new;
 
     ok(!$s->get('foo'), '... no value stored for foo in session (1)');
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (1) successfully';
 }
 
 
 {
+    my $r = request({ plack_session => 2 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 2 }),
+        request => $r,
     );
 
     is($s->id, 2, '... got a basic session id (2)');
 
     is($s->get('foo'), 'baz', '... got the foo value back successfully from session (2)');
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (2) successfully';
 }
 
 {
+    my $r = request({ plack_session => 1 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 1 }),
+        request => $r,
     );
 
     is($s->id, 1, '... got a basic session id (1)');
@@ -128,16 +146,20 @@ my $state   = Plack::Session::State->new;
         $s->set( bar => 'baz' );
     } '... set the bar value successfully in session (1)';
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (1) successfully';
 }
 
 {
+    my $r = request({ plack_session => 1 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 1 }),
+        request => $r,
     );
 
     is($s->id, 1, '... got a basic session id (1)');
@@ -150,10 +172,12 @@ my $state   = Plack::Session::State->new;
 }
 
 {
+    my $r = request({ plack_session => 1 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 1 }),
+        request => $r,
     );
 
     is($s->id, 3, '... got a new session id (3)');
@@ -162,18 +186,22 @@ my $state   = Plack::Session::State->new;
 }
 
 {
+    my $r = request({ plack_session => 2 });
+
     my $s = Plack::Session->new(
         state   => $state,
         store   => $storage,
-        request => request({ plack_session => 2 }),
+        request => $r,
     );
 
     is($s->id, 2, '... got a basic session id (2)');
 
     is($s->get('foo'), 'baz', '... got the foo value back successfully from session (2)');
 
+    my $resp = $r->new_response;
+
     lives_ok {
-        $s->finalize;
+        $s->finalize( $resp );
     } '... finalized session (2) successfully';
 }