6f72c782f2ee51c73654fcb3038715527afd1940
[catagits/Web-Session.git] / lib / Plack / Session / State.pm
1 package Plack::Session::State;
2 use strict;
3 use warnings;
4
5 use Digest::SHA1 ();
6
7 use Plack::Util::Accessor qw[
8     session_key
9     sid_generator
10     sid_validator
11 ];
12
13 sub new {
14     my ($class, %params) = @_;
15
16     $params{'_expired'}      ||= +{};
17     $params{'session_key'}   ||= 'plack_session';
18     $params{'sid_generator'} ||= sub {
19         Digest::SHA1::sha1_hex(rand() . $$ . {} . time)
20     };
21     $params{'sid_validator'} ||= qr/\A[0-9a-f]{40}\Z/;
22
23     bless { %params } => $class;
24 }
25
26 sub expire_session_id {
27     my ($self, $id) = @_;
28     $self->{'_expired'}->{ $id }++;
29 }
30
31 sub is_session_expired {
32     my ($self, $id) = @_;
33     exists $self->{'_expired'}->{ $id }
34 }
35
36 sub check_expired {
37     my ($self, $id) = @_;
38     return unless $id && not $self->is_session_expired( $id );
39     return $id;
40 }
41
42 sub validate_request_session_id {
43     my ($self, $request) = @_;
44
45     my $reqest_session_id = $self->get_request_session_id($request);
46
47     defined $reqest_session_id && $reqest_session_id =~ $self->sid_validator;
48 }
49
50 sub get_session_id {
51     my ($self, $request) = @_;
52     (
53         $self->validate_request_session_id($request)
54         &&
55         $self->extract( $request )
56     )
57         ||
58     $self->generate( $request )
59 }
60
61 sub get_request_session_id {
62     my ($self, $request ) = @_;
63
64     $request->param( $self->session_key );
65 }
66
67 sub extract {
68     my ($self, $request) = @_;
69
70     $self->check_expired( $self->get_request_session_id($request) );
71 }
72
73 sub generate {
74     my $self = shift;
75     $self->sid_generator->( @_ );
76 }
77
78
79 sub finalize {
80     my ($self, $id, $response) = @_;
81     ();
82 }
83
84 1;
85
86 __END__
87
88 =pod
89
90 =head1 NAME
91
92 Plack::Session::State - Basic parameter-based session state
93
94 =head1 SYNOPSIS
95
96   use Plack::Builder;
97   use Plack::Middleware::Session;
98   use Plack::Session::State;
99
100   my $app = sub {
101       return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello Foo' ] ];
102   };
103
104   builder {
105       enable 'Session',
106           state => Plack::Session::State->new;
107       $app;
108   };
109
110 =head1 DESCRIPTION
111
112 This will maintain session state by passing the session through
113 the request params. It does not do this automatically though,
114 you are responsible for passing the session param.
115
116 This should be considered the state "base" class (although
117 subclassing is not a requirement) and defines the spec for
118 all B<Plack::Session::State::*> modules. You will only
119 need to override a couple methods if you do subclass. See
120 L<Plack::Session::State::Cookie> for an example of this.
121
122 =head1 METHODS
123
124 =over 4
125
126 =item B<new ( %params )>
127
128 The C<%params> can include I<session_key>, I<sid_generator> and I<sid_checker>
129 however in both cases a default will be provided for you.
130
131 =item B<session_key>
132
133 This is the name of the session key, it default to 'plack_session'.
134
135 =item B<sid_generator>
136
137 This is a CODE ref used to generate unique session ids, by default
138 it will generate a SHA1 using fairly sufficient entropy. If you are
139 concerned or interested, just read the source.
140
141 =item B<sid_validator>
142
143 This is a regex used to validate requested session id,
144
145 =back
146
147 =head2 Session ID Managment
148
149 =over 4
150
151 =item B<get_session_id ( $request )>
152
153 Given a C<$request> this will first attempt to extract the session,
154 if the is expired or does not exist, it will then generate a new
155 session. The C<$request> is expected to be a L<Plack::Request> instance
156 or an object with an equivalent interface.
157
158 =item B<get_request_session_id ( $request )>
159
160 =item B<extract ( $request )>
161
162 This will attempt to extract the session from a C<$request> by looking
163 for the C<session_key> in the C<$request> params. It will then check to
164 see if the session has expired and return the session id if it is not.
165 The C<$request> is expected to be a L<Plack::Request> instance or an
166 object with an equivalent interface.
167
168 =item B<generate ( $request )>
169
170 This will generate a new session id using the C<sid_generator> callback.
171 The C<$request> argument is not used by this method but is there for
172 use by subclasses. The C<$request> is expected to be a L<Plack::Request>
173 instance or an object with an equivalent interface.
174
175 =item B<finalize ( $session_id, $response )>
176
177 Given a C<$session_id> and a C<$response> this will perform any
178 finalization nessecary to preserve state. This method is called by
179 the L<Plack::Session> C<finalize> method. The C<$response> is expected
180 to be a L<Plack::Response> instance or an object with an equivalent
181 interface.
182
183 =back
184
185 =head2 Session Expiration Handling
186
187 =over 4
188
189 =item B<expire_session_id ( $id )>
190
191 This will mark the session for C<$id> as expired. This method is called
192 by the L<Plack::Session> C<expire> method.
193
194 =item B<is_session_expired ( $id )>
195
196 This will check to see if the session C<$id> has been marked as
197 expired.
198
199 =item B<check_expired ( $id )>
200
201 Given an session C<$id> this will return C<undef> if the session is
202 expired or return the C<$id> if it is not.
203
204 =back
205
206 =head1 BUGS
207
208 All complex software has bugs lurking in it, and this module is no
209 exception. If you find a bug please either email me, or add the bug
210 to cpan-RT.
211
212 =head1 AUTHOR
213
214 Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
215
216 =head1 COPYRIGHT AND LICENSE
217
218 Copyright 2009 Infinity Interactive, Inc.
219
220 L<http://www.iinteractive.com>
221
222 This library is free software; you can redistribute it and/or modify
223 it under the same terms as Perl itself.
224
225 =cut
226
227