Checking in changes prior to tagging of version 0.11. Changelog diff is:
[catagits/Catalyst-Plugin-Session-State-Cookie.git] / lib / Catalyst / Plugin / Session / State / Cookie.pm
CommitLineData
1a776a0c 1package Catalyst::Plugin::Session::State::Cookie;
ea139a65 2use base qw/Catalyst::Plugin::Session::State Class::Accessor::Fast/;
bf2bce67 3
4use strict;
1a776a0c 5use warnings;
bf2bce67 6
45c96680 7use MRO::Compat;
74586782 8use Catalyst::Utils ();
bf2bce67 9
602b9593 10our $VERSION = "0.11";
ea139a65 11
12BEGIN { __PACKAGE__->mk_accessors(qw/_deleted_session_id/) }
81eb8ebf 13
5e50008f 14sub setup_session {
20e33791 15 my $c = shift;
5e50008f 16
45c96680 17 $c->maybe::next::method(@_);
2bde9162 18
7022ec4c 19 $c->config->{session}{cookie_name}
20 ||= Catalyst::Utils::appprefix($c) . '_session';
5e50008f 21}
22
0ff18b66 23sub extend_session_id {
24 my ( $c, $sid, $expires ) = @_;
1a776a0c 25
2bde9162 26 if ( my $cookie = $c->get_session_cookie ) {
0ff18b66 27 $c->update_session_cookie( $c->make_session_cookie( $sid ) );
58730edc 28 }
db1cda22 29
45c96680 30 $c->maybe::next::method( $sid, $expires );
2bde9162 31}
32
33sub set_session_id {
34 my ( $c, $sid ) = @_;
35
36 $c->update_session_cookie( $c->make_session_cookie( $sid ) );
37
45c96680 38 return $c->maybe::next::method($sid);
db1cda22 39}
40
41sub update_session_cookie {
58730edc 42 my ( $c, $updated ) = @_;
8bdcbb46 43
44 unless ( $c->cookie_is_rejecting( $updated ) ) {
45 my $cookie_name = $c->config->{session}{cookie_name};
46 $c->response->cookies->{$cookie_name} = $updated;
47 }
48}
49
50sub cookie_is_rejecting {
51 my ( $c, $cookie ) = @_;
52
53 if ( $cookie->{path} ) {
91e4fe2d 54 return 1 if index '/'.$c->request->path, $cookie->{path};
8bdcbb46 55 }
56
57 return 0;
db1cda22 58}
5e50008f 59
db1cda22 60sub make_session_cookie {
2bde9162 61 my ( $c, $sid, %attrs ) = @_;
58730edc 62
63 my $cfg = $c->config->{session};
64 my $cookie = {
2bde9162 65 value => $sid,
58730edc 66 ( $cfg->{cookie_domain} ? ( domain => $cfg->{cookie_domain} ) : () ),
8bdcbb46 67 ( $cfg->{cookie_path} ? ( path => $cfg->{cookie_path} ) : () ),
df55e818 68 %attrs,
58730edc 69 };
70
2bde9162 71 unless ( exists $cookie->{expires} ) {
72 $cookie->{expires} = $c->calculate_session_cookie_expires();
73 }
1e986fd5 74
fc4b9d6d 75 $cookie->{secure} = 1 if $cfg->{cookie_secure};
76
1e986fd5 77 return $cookie;
78}
79
2bde9162 80sub calc_expiry { # compat
81 my $c = shift;
45c96680 82 $c->maybe::next::method( @_ ) || $c->calculate_session_cookie_expires( @_ );
2bde9162 83}
84
85sub calculate_session_cookie_expires {
86 my $c = shift;
87 my $cfg = $c->config->{session};
88
45c96680 89 my $value = $c->maybe::next::method(@_);
1e986fd5 90 return $value if $value;
2bde9162 91
58730edc 92 if ( exists $cfg->{cookie_expires} ) {
7022ec4c 93 if ( $cfg->{cookie_expires} > 0 ) {
1e986fd5 94 return time() + $cfg->{cookie_expires};
7022ec4c 95 }
96 else {
1e986fd5 97 return undef;
7022ec4c 98 }
58730edc 99 }
100 else {
2bde9162 101 return $c->session_expires;
58730edc 102 }
bf2bce67 103}
104
2bde9162 105sub get_session_cookie {
bf2bce67 106 my $c = shift;
1a776a0c 107
20e33791 108 my $cookie_name = $c->config->{session}{cookie_name};
5e50008f 109
2bde9162 110 return $c->request->cookies->{$cookie_name};
111}
112
113sub get_session_id {
114 my $c = shift;
115
ea139a65 116 if ( !$c->_deleted_session_id and my $cookie = $c->get_session_cookie ) {
bf2bce67 117 my $sid = $cookie->value;
bf2bce67 118 $c->log->debug(qq/Found sessionid "$sid" in cookie/) if $c->debug;
2bde9162 119 return $sid if $sid;
bf2bce67 120 }
bf2bce67 121
45c96680 122 $c->maybe::next::method(@_);
2bde9162 123}
124
125sub delete_session_id {
df55e818 126 my ( $c, $sid ) = @_;
ea139a65 127
128 $c->_deleted_session_id(1); # to prevent get_session_id from returning it
df55e818 129
130 $c->update_session_cookie( $c->make_session_cookie( $sid, expires => 0 ) );
131
45c96680 132 $c->maybe::next::method($sid);
bf2bce67 133}
134
1a776a0c 135__PACKAGE__
57dbf608 136
1a776a0c 137__END__
bf2bce67 138
1a776a0c 139=pod
b2f8df5e 140
1a776a0c 141=head1 NAME
bf2bce67 142
75d3560d 143Catalyst::Plugin::Session::State::Cookie - Maintain session IDs using cookies.
bf2bce67 144
1a776a0c 145=head1 SYNOPSIS
bf2bce67 146
20e33791 147 use Catalyst qw/Session Session::State::Cookie Session::Store::Foo/;
bf2bce67 148
1a776a0c 149=head1 DESCRIPTION
bf2bce67 150
1a776a0c 151In order for L<Catalyst::Plugin::Session> to work the session ID needs to be
152stored on the client, and the session data needs to be stored on the server.
bf2bce67 153
1a776a0c 154This plugin stores the session ID on the client using the cookie mechanism.
57dbf608 155
724a6173 156=head1 METHODS
157
158=over 4
159
160=item make_session_cookie
161
162Returns a hash reference with the default values for new cookies.
163
164=item update_session_cookie $hash_ref
165
166Sets the cookie based on C<cookie_name> in the response object.
167
2cfb85de 168=item calc_expiry
169
170=item calculate_session_cookie_expires
171
172=item cookie_is_rejecting
173
174=item delete_session_id
175
176=item extend_session_id
177
178=item get_session_cookie
179
180=item get_session_id
181
182=item set_session_id
183
724a6173 184=back
185
1a776a0c 186=head1 EXTENDED METHODS
58c05d1a 187
57dbf608 188=over 4
189
1a776a0c 190=item prepare_cookies
57dbf608 191
1a776a0c 192Will restore if an appropriate cookie is found.
58c05d1a 193
d52e5079 194=item finalize_cookies
58c05d1a 195
1536d9aa 196Will set a cookie called C<session> if it doesn't exist or if its value is not
19c2baa1 197the current session id.
198
199=item setup_session
200
1536d9aa 201Will set the C<cookie_name> parameter to its default value if it isn't set.
58c05d1a 202
57dbf608 203=back
58c05d1a 204
5e50008f 205=head1 CONFIGURATION
206
207=over 4
208
209=item cookie_name
210
ae33e13f 211The name of the cookie to store (defaults to C<Catalyst::Utils::apprefix($c) . '_session'>).
5e50008f 212
41b4b15c 213=item cookie_domain
214
215The name of the domain to store in the cookie (defaults to current host)
216
7022ec4c 217=item cookie_expires
218
219Number of seconds from now you want to elapse before cookie will expire.
220Set to 0 to create a session cookie, ie one which will die when the
221user's browser is shut down.
222
fc4b9d6d 223=item cookie_secure
224
225If this attribute set true, the cookie will only be sent via HTTPS.
226
8bdcbb46 227=item cookie_path
228
229The path of the request url where cookie should be baked.
230
5e50008f 231=back
232
d6bdceb5 233For example, you could stick this in MyApp.pm:
234
235 __PACKAGE__->config( session => {
236 cookie_domain => '.mydomain.com',
237 });
238
724a6173 239=head1 CAVEATS
db1cda22 240
241Sessions have to be created before the first write to be saved. For example:
242
243 sub action : Local {
244 my ( $self, $c ) = @_;
245 $c->res->write("foo");
246 $c->session( ... );
247 ...
248 }
249
250Will cause a session ID to not be set, because by the time a session is
251actually created the headers have already been sent to the client.
252
bf2bce67 253=head1 SEE ALSO
254
1a776a0c 255L<Catalyst>, L<Catalyst::Plugin::Session>.
bf2bce67 256
47f47da5 257=head1 AUTHORS
bf2bce67 258
8ae6d944 259Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
260
261=head1 CONTRIBUTORS
262
47f47da5 263This module is derived from L<Catalyst::Plugin::Session::FastMmap> code, and
264has been heavily modified since.
265
d6bdceb5 266 Andrew Ford
267 Andy Grundman
268 Christian Hansen
269 Marcus Ramberg
270 Jonathan Rockway E<lt>jrockway@cpan.orgE<gt>
271 Sebastian Riedel
bf2bce67 272
273=head1 COPYRIGHT
274
bfeb5ca0 275This program is free software, you can redistribute it and/or modify it
276under the same terms as Perl itself.
bf2bce67 277
278=cut
279
2801;