fix LTJake's always expiring second session issue
[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
1a776a0c 7use NEXT;
74586782 8use Catalyst::Utils ();
bf2bce67 9
ea139a65 10our $VERSION = "0.07";
11
12BEGIN { __PACKAGE__->mk_accessors(qw/_deleted_session_id/) }
81eb8ebf 13
5e50008f 14sub setup_session {
20e33791 15 my $c = shift;
5e50008f 16
20e33791 17 $c->NEXT::setup_session(@_);
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
0b3bde04 30 $c->NEXT::extend_session_id( $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
0b3bde04 38 return $c->NEXT::set_session_id($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;
82 $c->NEXT::calc_expiry( @_ ) || $c->calculate_session_cookie_expires( @_ );
83}
84
85sub calculate_session_cookie_expires {
86 my $c = shift;
87 my $cfg = $c->config->{session};
88
89 my $value = $c->NEXT::calculate_session_cookie_expires(@_);
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
2bde9162 122 $c->NEXT::get_session_id(@_);
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
132 $c->NEXT::delete_session_id($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
168=back
169
1a776a0c 170=head1 EXTENDED METHODS
58c05d1a 171
57dbf608 172=over 4
173
1a776a0c 174=item prepare_cookies
57dbf608 175
1a776a0c 176Will restore if an appropriate cookie is found.
58c05d1a 177
d52e5079 178=item finalize_cookies
58c05d1a 179
19c2baa1 180Will set a cookie called C<session> if it doesn't exist or if it's value is not
181the current session id.
182
183=item setup_session
184
185Will set the C<cookie_name> parameter to it's default value if it isn't set.
58c05d1a 186
57dbf608 187=back
58c05d1a 188
5e50008f 189=head1 CONFIGURATION
190
191=over 4
192
193=item cookie_name
194
ae33e13f 195The name of the cookie to store (defaults to C<Catalyst::Utils::apprefix($c) . '_session'>).
5e50008f 196
41b4b15c 197=item cookie_domain
198
199The name of the domain to store in the cookie (defaults to current host)
200
7022ec4c 201=item cookie_expires
202
203Number of seconds from now you want to elapse before cookie will expire.
204Set to 0 to create a session cookie, ie one which will die when the
205user's browser is shut down.
206
fc4b9d6d 207=item cookie_secure
208
209If this attribute set true, the cookie will only be sent via HTTPS.
210
8bdcbb46 211=item cookie_path
212
213The path of the request url where cookie should be baked.
214
5e50008f 215=back
216
724a6173 217=head1 CAVEATS
db1cda22 218
219Sessions have to be created before the first write to be saved. For example:
220
221 sub action : Local {
222 my ( $self, $c ) = @_;
223 $c->res->write("foo");
224 $c->session( ... );
225 ...
226 }
227
228Will cause a session ID to not be set, because by the time a session is
229actually created the headers have already been sent to the client.
230
bf2bce67 231=head1 SEE ALSO
232
1a776a0c 233L<Catalyst>, L<Catalyst::Plugin::Session>.
bf2bce67 234
47f47da5 235=head1 AUTHORS
bf2bce67 236
47f47da5 237This module is derived from L<Catalyst::Plugin::Session::FastMmap> code, and
238has been heavily modified since.
239
240Andrew Ford
241Andy Grundman
242Christian Hansen
243Yuval Kogman, C<nothingmuch@woobling.org>
244Marcus Ramberg
245Sebastian Riedel
bf2bce67 246
247=head1 COPYRIGHT
248
bfeb5ca0 249This program is free software, you can redistribute it and/or modify it
250under the same terms as Perl itself.
bf2bce67 251
252=cut
253
2541;