Merge flash in session and finalize before sending response patches
[catagits/Catalyst-Plugin-Session.git] / lib / Catalyst / Plugin / Session.pm
index 08ef366..e9c2a13 100644 (file)
@@ -13,7 +13,7 @@ use overload            ();
 use Object::Signature   ();
 use Carp;
 
-our $VERSION = '0.20';
+our $VERSION = '0.19_01';
 
 my @session_data_accessors; # used in delete_session
 BEGIN {
@@ -98,13 +98,15 @@ sub finalize_headers {
     return $c->NEXT::finalize_headers(@_);
 }
 
-sub finalize {
+sub finalize_body {
     my $c = shift;
-    my $ret = $c->NEXT::finalize(@_);
 
-    # then finish the rest
+    # We have to finalize our session *before* $c->engine->finalize_xxx is called,
+    # because we do not want to send the HTTP response before the session is stored/committed to
+    # the session database (or whatever Session::Store you use).
     $c->finalize_session;
-    return $ret;
+
+    return $c->NEXT::finalize_body(@_);
 }
 
 sub finalize_session {
@@ -168,12 +170,15 @@ sub _save_flash {
         
         my $sid = $c->sessionid;
 
+        my $session_data = $c->_session;
         if (%$flash_data) {
-            $c->store_session_data( "flash:$sid", $flash_data );
+            $session_data->{__flash} = $flash_data;
         }
         else {
-            $c->delete_session_data("flash:$sid");
+            delete $session_data->{__flash};
         }
+        $c->_session($session_data);
+        $c->_save_session;
     }
 }
 
@@ -238,8 +243,11 @@ sub _load_flash {
     $c->_tried_loading_flash_data(1);
 
     if ( my $sid = $c->sessionid ) {
-        if ( my $flash_data = $c->_flash
-            || $c->_flash( $c->get_session_data("flash:$sid") ) )
+
+        my $session_data = $c->session;
+        $c->_flash($session_data->{__flash});
+
+        if ( my $flash_data = $c->_flash )
         {
             $c->_flash_key_hashes({ map { $_ => Object::Signature::signature( \$flash_data->{$_} ) } keys %$flash_data });
             
@@ -687,6 +695,8 @@ changed, call C<keep_flash> and pass in the keys as arguments.
 This method is used to invalidate a session. It takes an optional parameter
 which will be saved in C<session_delete_reason> if provided.
 
+NOTE: This method will B<also> delete your flash data.
+
 =item session_delete_reason
 
 This accessor contains a string with the reason a session was deleted. Possible
@@ -745,9 +755,9 @@ listed in L</CONFIGURATION>.
 
 =item prepare_action
 
-This methoid is extended.
+This method is extended.
 
-It's only effect is if the (off by default) C<flash_to_stash> configuration
+Its only effect is if the (off by default) C<flash_to_stash> configuration
 parameter is on - then it will copy the contents of the flash to the stash at
 prepare time.
 
@@ -756,10 +766,10 @@ prepare time.
 This method is extended and will extend the expiry time before sending
 the response.
 
-=item finalize
+=item finalize_body
 
-This method is extended and will call finalize_session after the other
-finalizes run.  Here we persist the session data if a session exists.
+This method is extended and will call finalize_session before the other
+finalize_body methods run.  Here we persist the session data if a session exists.
 
 =item initialize_session_data
 
@@ -768,7 +778,7 @@ called by the C<session> method if appropriate.
 
 =item create_session_id
 
-Creates a new session id using C<generate_session_id> if there is no session ID
+Creates a new session ID using C<generate_session_id> if there is no session ID
 yet.
 
 =item validate_session_id SID
@@ -783,7 +793,7 @@ insensitive hexadecimal characters.
 This method will return a string that can be used as a session ID. It is
 supposed to be a reasonably random string with enough bits to prevent
 collision. It basically takes C<session_hash_seed> and hashes it using SHA-1,
-MD5 or SHA-256, depending on the availibility of these modules.
+MD5 or SHA-256, depending on the availability of these modules.
 
 =item session_hash_seed
 
@@ -806,7 +816,7 @@ Currently it returns a concatenated string which contains:
 
 =back
 
-In the hopes that those combined values are entropic enough for most uses. If
+in the hopes that those combined values are entropic enough for most uses. If
 this is not the case you can replace C<session_hash_seed> with e.g.
 
     sub session_hash_seed {
@@ -951,13 +961,13 @@ users' sessions cannot persist.
 To let these users access your site you can either disable address verification
 as a whole, or provide a checkbox in the login dialog that tells the server
 that it's OK for the address of the client to change. When the server sees that
-this box is checked it should delete the C<__address> sepcial key from the
+this box is checked it should delete the C<__address> special key from the
 session hash when the hash is first created.
 
 =head2 Race Conditions
 
-In this day and age where cleaning detergents and dutch football (not the
-american kind) teams roam the plains in great numbers, requests may happen
+In this day and age where cleaning detergents and Dutch football (not the
+American kind) teams roam the plains in great numbers, requests may happen
 simultaneously. This means that there is some risk of session data being
 overwritten, like this:
 
@@ -965,7 +975,7 @@ overwritten, like this:
 
 =item 1.
 
-request a starts, request b starts, with the same session id
+request a starts, request b starts, with the same session ID
 
 =item 2.
 
@@ -990,7 +1000,7 @@ changes by request a
 
 =back
 
-If this is a concern in your application, a soon to be developed locking
+If this is a concern in your application, a soon-to-be-developed locking
 solution is the only safe way to go. This will have a bigger overhead.
 
 For applications where any given user is only making one request at a time this
@@ -1002,10 +1012,14 @@ Andy Grundman
 
 Christian Hansen
 
-Yuval Kogman, C<nothingmuch@woobling.org> (current maintainer)
+Yuval Kogman, C<nothingmuch@woobling.org>
 
 Sebastian Riedel
 
+Tomas Doran (t0m) C<bobtfish@bobtfish.net> (current maintainer)
+
+Sergio Salvi
+
 And countless other contributers from #catalyst. Thanks guys!
 
 =head1 COPYRIGHT & LICENSE