Remove $session->commit, and hence remove manager to make Session
[catagits/Web-Session.git] / lib / Plack / Middleware / Session.pm
CommitLineData
bd992981 1package Plack::Middleware::Session;
2use strict;
3use warnings;
4
000c696e 5our $VERSION = '0.03';
30cc0a71 6our $AUTHORITY = 'cpan:STEVAN';
7
bd992981 8use Plack::Request;
9use Plack::Response;
ad80e445 10use Plack::Util;
11use Scalar::Util;
bd992981 12
13use parent 'Plack::Middleware';
14
d6af4aa8 15use Plack::Util::Accessor qw(
16 state
17 store
18 session_class
19);
bd992981 20
fe1bfe7d 21sub prepare_app {
22 my $self = shift;
fe1bfe7d 23
4ff41723 24 $self->state( 'Cookie' ) unless $self->state;
ad80e445 25 $self->state( $self->inflate_backend('Plack::Session::State', $self->state) );
26 $self->store( $self->inflate_backend('Plack::Session::Store', $self->store) );
4ff41723 27
28 Plack::Util::load_class($self->session_class) if $self->session_class;
ad80e445 29}
30
31sub inflate_backend {
32 my($self, $prefix, $backend) = @_;
33
34 return $backend if defined $backend && Scalar::Util::blessed $backend;
35
36 my @class;
37 push @class, $backend if defined $backend; # undef means the root class
38 push @class, $prefix;
39
40 Plack::Util::load_class(@class)->new();
fe1bfe7d 41}
42
bd992981 43sub call {
44 my $self = shift;
45 my $env = shift;
46
4ff41723 47 my $request = Plack::Request->new($env);
48
49 my($id, $session);
50 if ($id = $self->state->extract($request) and
51 $session = $self->store->fetch($id)) {
52 $env->{'psgix.session'} = $session;
53 } else {
54 $id = $self->state->generate($request);
55 $env->{'psgix.session'} = {};
56 }
57
58 $env->{'psgix.session.options'} = { id => $id };
4a0cb5a0 59
4ff41723 60 if ($self->session_class) {
3bf03fd8 61 $env->{'plack.session'} = $self->session_class->new($env);
4ff41723 62 }
bd992981 63
fe1bfe7d 64 my $res = $self->app->($env);
65 $self->response_cb($res, sub {
66 my $res = Plack::Response->new(@{$_[0]});
98b27b31 67 $self->finalize($env->{'psgix.session'}, $env->{'psgix.session.options'}, $res);
b2504d01 68 $res = $res->finalize;
69 $_[0]->[0] = $res->[0];
70 $_[0]->[1] = $res->[1];
fe1bfe7d 71 });
bd992981 72}
73
4ff41723 74sub commit {
75 my($self, $session, $options) = @_;
76 if ($options->{expire}) {
77 $self->store->cleanup($options->{id});
78 } else {
79 $self->store->store($options->{id}, $session);
80 }
81}
82
83sub finalize {
98b27b31 84 my($self, $session, $options, $response) = @_;
4ff41723 85
399edae6 86 $self->commit($session, $options) unless $options->{no_store};
98b27b31 87 if ($options->{expire}) {
88 $self->state->expire_session_id($options->{id}, $response);
4ff41723 89 } else {
98b27b31 90 $self->state->finalize($options->{id}, $response, $options);
4ff41723 91 }
92}
93
bd992981 941;
95
96__END__
ac4892f4 97
98=pod
99
100=head1 NAME
101
102Plack::Middleware::Session - Middleware for session management
103
104=head1 SYNOPSIS
105
3d92cf47 106 use Plack::Builder;
ac4892f4 107
3d92cf47 108 my $app = sub {
536da026 109 my $env = shift;
4ff41723 110 my $session = $env->{'psgix.session'};
536da026 111 return [
112 200,
113 [ 'Content-Type' => 'text/plain' ],
4ff41723 114 [ "Hello, you've been here for ", $session->{counter}++, "th time!" ],
536da026 115 ];
3d92cf47 116 };
117
118 builder {
119 enable 'Session';
120 $app;
121 };
122
ad80e445 123 # Or, use the File store backend (great if you use multiprocess server)
124 # For more options, see perldoc Plack::Session::Store::File
125 builder {
126 enable 'Session', store => 'File';
127 $app;
128 };
129
ac4892f4 130=head1 DESCRIPTION
131
3d92cf47 132This is a Plack Middleware component for session management. By
ad80e445 133default it will use cookies to keep session state and store data in
134memory. This distribution also comes with other state and store
135solutions. See perldoc for these backends how to use them.
3d92cf47 136
4ff41723 137It should be noted that we store the current session as a hash
138reference in the C<psgix.session> key inside the C<$env> where you can
139access it as needed.
140
141B<NOTE:> As of version 0.04 the session is stored in C<psgix.session>
142instead of C<plack.session>.
b84f31d0 143
4ff41723 144Also, if you set I<session_class> option (see below), we create a
145session object out of the hash reference in C<plack.session>.
536da026 146
3d92cf47 147=head2 State
148
149=over 4
150
151=item L<Plack::Session::State>
152
153This will maintain session state by passing the session through
154the request params. It does not do this automatically though,
155you are responsible for passing the session param.
156
157=item L<Plack::Session::State::Cookie>
158
159This will maintain session state using browser cookies.
160
161=back
162
163=head2 Store
164
165=over 4
166
167=item L<Plack::Session::Store>
168
169This is your basic in-memory session data store. It is volatile storage
170and not recommended for multiprocessing environments. However it is
171very useful for development and testing.
172
173=item L<Plack::Session::Store::File>
174
175This will persist session data in a file. By default it uses
176L<Storable> but it can be configured to have a custom serializer and
177deserializer.
178
20ede533 179=item L<Plack::Session::Store::Cache>
3d92cf47 180
20ede533 181This will persist session data using the L<Cache> interface.
3d92cf47 182
183=item L<Plack::Session::Store::Null>
184
185Sometimes you don't care about storing session data, in that case
186you can use this noop module.
187
188=back
189
30cc0a71 190=head1 OPTIONS
191
192The following are options that can be passed to this mdoule.
193
194=over 4
195
196=item I<state>
197
198This is expected to be an instance of L<Plack::Session::State> or an
199object that implements the same interface. If no option is provided
200the default L<Plack::Session::State::Cookie> will be used.
201
202=item I<store>
203
204This is expected to be an instance of L<Plack::Session::Store> or an
205object that implements the same interface. If no option is provided
206the default L<Plack::Session::Store> will be used.
207
208It should be noted that this default is an in-memory volatile store
209is only suitable for development (or single process servers). For a
210more robust solution see L<Plack::Session::Store::File> or
211L<Plack::Session::Store::Cache>.
212
213=item I<session_class>
214
4ff41723 215This can be used to create an actual session object in
216C<plack.session> environment. Defaults to none, which means the
217session object is not created but you can set C<Plack::Session> to
218create an object for you.
30cc0a71 219
220=back
221
ac4892f4 222=head1 BUGS
223
224All complex software has bugs lurking in it, and this module is no
225exception. If you find a bug please either email me, or add the bug
226to cpan-RT.
227
228=head1 AUTHOR
229
230Tatsuhiko Miyagawa
231
232Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
233
234=head1 COPYRIGHT AND LICENSE
235
000c696e 236Copyright 2009, 2010 Infinity Interactive, Inc.
ac4892f4 237
238L<http://www.iinteractive.com>
239
240This library is free software; you can redistribute it and/or modify
241it under the same terms as Perl itself.
242
243=cut
244
245