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