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