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 {
Plack::Util::load_class(@class)->new();
}
-sub fetch_or_create_session {
- my($self, $req) = @_;
- $self->session_class->fetch_or_create($req, $self);
-}
-
sub call {
my $self = shift;
my $env = shift;
- my $session = $self->fetch_or_create_session(Plack::Request->new($env));
+ my $request = Plack::Request->new($env);
+
+ my($id, $session);
+ if ($id = $self->state->extract($request) and
+ $session = $self->store->fetch($id)) {
+ $env->{'psgix.session'} = $session;
+ } else {
+ $id = $self->state->generate($request);
+ $env->{'psgix.session'} = {};
+ }
+
+ $env->{'psgix.session.options'} = { id => $id };
- $env->{'psgix.session'} = $env->{'plack.session'} = $session;
+ if ($self->session_class) {
+ $env->{'plack.session'} = $self->session_class->new(
+ manager => $self,
+ _data => $env->{'psgix.session'},
+ options => $env->{'psgix.session.options'},
+ );
+ }
my $res = $self->app->($env);
$self->response_cb($res, sub {
my $res = Plack::Response->new(@{$_[0]});
- $env->{'psgix.session'}->finalize($res);
+ $self->finalize($env, $res);
$res = $res->finalize;
$_[0]->[0] = $res->[0];
$_[0]->[1] = $res->[1];
});
}
+sub commit {
+ my($self, $session, $options) = @_;
+ if ($options->{expire}) {
+ $self->store->cleanup($options->{id});
+ } else {
+ $self->store->store($options->{id}, $session);
+ }
+}
+
+sub finalize {
+ my($self, $env, $response) = @_;
+
+ $self->commit($env->{'psgix.session'}, $env->{'psgix.session.options'});
+ if ($env->{'psgix.session.options'}->{expire}) {
+ $self->state->expire_session_id($env->{'psgix.session.options'}->{id}, $response);
+ } else {
+ $self->state->finalize($env->{'psgix.session.options'}->{id}, $response, $env->{'psgix.session.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->{'psgix.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<psgix.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<psgix.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>.
-B<NOTE:> As of version 0.02 the session is stored in C<psgix.session>
-instead of C<plack.session>. We still keep a copy of it in
-C<plack.session>, but this is deprecated and will be removed
-in future versions.
+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
sub prepare_app {
my $self = shift;
- $self->session_class("Plack::Session");
+ Plack::Util::load_class($self->session_class) if $self->session_class;
$self->session_key("plack_session") unless $self->session_key;
my $state_cookie = Plack::Session::State::Cookie->new;
return $cookie;
},
expire_session_id => sub { $state_cookie->expire_session_id(@_) },
- finalize => sub {
- my($id, $response, $session) = @_;
- my $cookie = $self->_serialize($session->dump);
- $state_cookie->finalize($cookie, $response);
- };
+ finalize => sub { $state_cookie->finalize(@_) };
my $store = Plack::Util::inline_object
fetch => sub {
$self->store($store);
}
+sub finalize {
+ my($self, $env, $response) = @_;
+
+ if ($env->{'psgix.session.options'}->{expire}) {
+ $self->state->expire_session_id($env->{'psgix.session.options'}->{id}, $response);
+ } else {
+ my $cookie = $self->_serialize($env->{'psgix.session'});
+ $self->state->finalize($cookie, $response, $env->{'psgix.session.options'});
+ }
+}
+
sub _serialize {
my($self, $session) = @_;
our $VERSION = '0.03';
our $AUTHORITY = 'cpan:STEVAN';
-use Plack::Util::Accessor qw( id expired _manager );
-
-sub fetch_or_create {
- my($class, $request, $manager) = @_;
-
- my($id, $session);
- if ($id = $manager->state->extract($request) and
- $session = $manager->store->fetch($id)) {
- return $class->new( id => $id, _stash => $session, _manager => $manager, _changed => 0 );
- } else {
- $id = $manager->state->generate($request);
- return $class->new( id => $id, _stash => {}, _manager => $manager, _changed=> 1 );
- }
-}
+use Plack::Util::Accessor qw( manager _data options );
sub new {
my ($class, %params) = @_;
sub dump {
my $self = shift;
- $self->{_stash};
+ $self->_data;
}
sub get {
my ($self, $key) = @_;
- $self->{_stash}{$key};
+ $self->_data->{$key};
}
sub set {
my ($self, $key, $value) = @_;
- $self->{_changed}++;
- $self->{_stash}{$key} = $value;
+ delete $self->options->{no_commit};
+ $self->_data->{$key} = $value;
}
sub remove {
my ($self, $key) = @_;
- $self->{_changed}++;
- delete $self->{_stash}{$key};
+ delete $self->options->{no_commit};
+ delete $self->_data->{$key};
}
sub keys {
my $self = shift;
- keys %{$self->{_stash}};
+ keys %{$self->_data};
}
## Lifecycle Management
sub expire {
my $self = shift;
- $self->{_stash} = {};
- $self->expired(1);
+ $self->options->{expire} = 1;
}
sub commit {
my $self = shift;
-
- if ($self->expired) {
- $self->_manager->store->cleanup($self->id);
- } else {
- $self->_manager->store->store($self->id, $self);
- }
-
- $self->{_changed} = 0;
-}
-
-sub is_changed {
- my $self = shift;
- $self->{_changed} > 0;
-}
-
-sub finalize {
- my ($self, $response) = @_;
-
- $self->commit if $self->is_changed || $self->expired;
- if ($self->expired) {
- $self->_manager->state->expire_session_id($self->id, $response);
- } else {
- $self->_manager->state->finalize($self->id, $response, $self);
- }
+ $self->options->{no_commit} = 1;
+ $self->manager->commit($self->_data, $self->options);
}
1;
=head1 SYNOPSIS
- use Plack::Session;
+ # Use with Middleware::Session
+ enable "Session", session_class => "Plack::Session";
- my $store = Plack::Session::Store->new;
- my $state = Plack::Session::State->new;
+ use Plack::Session;
- my $s = Plack::Session->new(
- store => $store,
- state => $state,
- request => Plack::Request->new( $env )
- );
+ my $session =
- # ...
=head1 DESCRIPTION
sub finalize {
- my ($self, $id, $response) = @_;
+ my ($self, $id, $response, $options) = @_;
();
}
}
sub finalize {
- my ($self, $id, $response) = @_;
+ my ($self, $id, $response, $options) = @_;
$response->cookies->{ $self->session_key } = +{
value => $id,
path => ($self->path || '/'),
sub store {
my ($self, $session_id, $session) = @_;
- $self->_stash->{ $session_id } = $session->dump;
+ $self->_stash->{ $session_id } = $session;
}
sub cleanup {
my $env = shift;
my $session = $env->{'psgix.session'};
- my $counter = $session->get('counter') || 0;
- if ($counter >= 2) {
- $session->expire;
- } else {
- $session->set(counter => $counter + 1);
+ my $counter = $session->{counter} || 0;
+ if ($session->{counter}++ >= 2) {
+ $env->{'psgix.session.options'}->{expire} = 1;
}
return [ 200, [], [ "counter=$counter" ] ];