Browse Source

Retain session cookie data when setting other cookies.

When the `Set-Cookie` header is manually set, session cookie changes are
dropped. If the response contains cookies, also include the session
cookie, as it may have changed and we have no way of knowing whether or
not it actually did.

Refs #9305
mark_story 9 years ago
parent
commit
e497e2517b
2 changed files with 37 additions and 2 deletions
  1. 14 2
      src/Http/ResponseTransformer.php
  2. 23 0
      tests/TestCase/Http/ResponseTransformerTest.php

+ 14 - 2
src/Http/ResponseTransformer.php

@@ -162,8 +162,20 @@ class ResponseTransformer
         if (!isset($headers['Content-Type'])) {
             $headers['Content-Type'] = $response->type();
         }
-        if ($response->cookie()) {
-            $headers['Set-Cookie'] = static::buildCookieHeader($response->cookie());
+        $cookies = $response->cookie();
+        if ($cookies) {
+            $sessionCookie = session_get_cookie_params();
+            $sessionName = session_name();
+            $cookies[$sessionName] = [
+                'name' => $sessionName,
+                'value' => session_id(),
+                'expire' => $sessionCookie['lifetime'],
+                'path' => $sessionCookie['path'],
+                'secure' => $sessionCookie['secure'],
+                'domain' => $sessionCookie['domain'],
+                'httpOnly' => $sessionCookie['httponly'],
+            ];
+            $headers['Set-Cookie'] = static::buildCookieHeader($cookies);
         }
         $stream = static::getStream($response);
 

+ 23 - 0
tests/TestCase/Http/ResponseTransformerTest.php

@@ -15,6 +15,7 @@
 namespace Cake\Test\TestCase\Http;
 
 use Cake\Http\ResponseTransformer;
+use Cake\Network\Session;
 use Cake\Network\Response as CakeResponse;
 use Cake\TestSuite\TestCase;
 use Zend\Diactoros\Response as PsrResponse;
@@ -205,6 +206,28 @@ class ResponseTransformerTest extends TestCase
     }
 
     /**
+     * Test conversion setting cookies including the session cookie
+     *
+     * @return void
+     */
+    public function testToPsrCookieWithSession()
+    {
+        $session = new Session();
+        $session->write('things', 'things');
+        $cake = new CakeResponse(['status' => 200]);
+        $cake->cookie([
+            'name' => 'remember_me',
+            'value' => 1
+        ]);
+        $result = ResponseTransformer::toPsr($cake);
+        $this->assertEquals(
+            'remember_me=1; Path=/,CAKEPHP=; Path=/; HttpOnly',
+            $result->getHeaderLine('Set-Cookie'),
+            'Session cookie data was not retained.'
+        );
+    }
+
+    /**
      * Test conversion setting multiple cookies
      *
      * @return void