use strict;
use warnings;
-our $VERSION = '0.01';
+our $VERSION = '0.03';
our $AUTHORITY = 'cpan:STEVAN';
-use Plack::Session;
use Plack::Request;
use Plack::Response;
use Plack::Util;
sub prepare_app {
my $self = shift;
- $self->session_class( 'Plack::Session' ) unless $self->session_class;
- $self->state( 'Cookie' ) unless $self->state;
-
+ $self->state( 'Cookie' ) unless $self->state;
$self->state( $self->inflate_backend('Plack::Session::State', $self->state) );
$self->store( $self->inflate_backend('Plack::Session::Store', $self->store) );
+
+ Plack::Util::load_class($self->session_class) if $self->session_class;
}
sub inflate_backend {
my $self = shift;
my $env = shift;
- $env->{'plack.session'} = $self->session_class->new(
- state => $self->state,
- store => $self->store,
- request => Plack::Request->new( $env )
- );
+ my $request = Plack::Request->new($env);
+
+ my($id, $session) = $self->get_session($request);
+ if ($id && $session) {
+ $env->{'psgix.session'} = $session;
+ } else {
+ $id = $self->generate_id($request);
+ $env->{'psgix.session'} = {};
+ }
+
+ $env->{'psgix.session.options'} = { id => $id };
+
+ if ($self->session_class) {
+ $env->{'plack.session'} = $self->session_class->new($env);
+ }
my $res = $self->app->($env);
$self->response_cb($res, sub {
my $res = Plack::Response->new(@{$_[0]});
- $env->{'plack.session'}->finalize( $res );
- @{$_[0]} = @{$res->finalize};
+ $self->finalize($request, $res);
+ $res = $res->finalize;
+ $_[0]->[0] = $res->[0];
+ $_[0]->[1] = $res->[1];
});
}
+sub get_session {
+ my($self, $request) = @_;
+
+ my $id = $self->state->extract($request) or return;
+ my $session = $self->store->fetch($id) or return;
+
+ return ($id, $session);
+}
+
+sub generate_id {
+ my($self, $request) = @_;
+ $self->state->generate($request);
+}
+
+sub commit {
+ my($self, $session, $options) = @_;
+ if ($options->{expire}) {
+ $self->store->remove($options->{id});
+ } else {
+ $self->store->store($options->{id}, $session);
+ }
+}
+
+sub finalize {
+ my($self, $request, $response) = @_;
+
+ my $session = $request->env->{'psgix.session'};
+ my $options = $request->env->{'psgix.session.options'};
+
+ $self->commit($session, $options) unless $options->{no_store};
+ if ($options->{expire}) {
+ $self->expire_session($options->{id}, $response, $session, $options);
+ } else {
+ $self->save_state($options->{id}, $response, $session, $options);
+ }
+}
+
+sub expire_session {
+ my($self, $id, $res, $session, $options) = @_;
+ $self->state->expire_session_id($options->{id}, $res, $options);
+}
+
+sub save_state {
+ my($self, $id, $res, $session, $options) = @_;
+ $self->state->finalize($id, $res, $options);
+}
+
1;
__END__
my $app = sub {
my $env = shift;
+ my $session = $env->{'psgix.session'};
return [
200,
[ 'Content-Type' => 'text/plain' ],
- [ 'Hello, your Session ID is ' . $env->{'plack.session'}->id ]
+ [ "Hello, you've been here for ", $session->{counter}++, "th time!" ],
];
};
memory. This distribution also comes with other state and store
solutions. See perldoc for these backends how to use them.
-It should be noted that we store the current session in the
-C<plack.session> key inside the C<$env> where you can access it
-as needed. Additionally, as of version 0.09, you can call the
-C<session> method of a L<Plack::Request> instance to fetch
-whatever is stored in C<plack.session>.
+It should be noted that we store the current session as a hash
+reference in the C<psgix.session> key inside the C<$env> where you can
+access it as needed.
+
+B<NOTE:> As of version 0.04 the session is stored in C<psgix.session>
+instead of C<plack.session>.
+
+Also, if you set I<session_class> option (see below), we create a
+session object out of the hash reference in C<plack.session>.
=head2 State
=item I<session_class>
-This can be used to override the actual session class. It currently
-defaults to L<Plack::Session> but you can substitute any class which
-implements the same interface.
+This can be used to create an actual session object in
+C<plack.session> environment. Defaults to none, which means the
+session object is not created but you can set C<Plack::Session> to
+create an object for you.
=back
=head1 COPYRIGHT AND LICENSE
-Copyright 2009 Infinity Interactive, Inc.
+Copyright 2009, 2010 Infinity Interactive, Inc.
L<http://www.iinteractive.com>