]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add functions to modify cookies to response class
authorLukas Reschke <lukas@owncloud.com>
Thu, 27 Nov 2014 13:19:00 +0000 (14:19 +0100)
committerLukas Reschke <lukas@owncloud.com>
Thu, 27 Nov 2014 13:19:00 +0000 (14:19 +0100)
Currently there is no AppFramework way to modify cookies, which makes it unusable for quite some use-cases or results in untestable code.

This PR adds some basic functionalities to add and invalidate cookies.

Usage:
```php
$response = new TemplateResponse(...);
$response->addCookie('foo', 'bar');
$response->invalidateCookie('foo');
$response->addCookie('bar', 'foo', new \DateTime('2015-01-01 00:00'));
```

Existing cookies can be accessed with the AppFramework using `$this->request->getCookie($name)`.

lib/private/appframework/app.php
lib/private/appframework/http/dispatcher.php
lib/public/appframework/http/response.php
tests/lib/appframework/AppTest.php
tests/lib/appframework/http/DispatcherTest.php
tests/lib/appframework/http/ResponseTest.php

index baf52d02054b17ff218b6bf6f93fda174eb456df..074b6cc3fd28d95f5cbe8ecf5c0a879385257e0c 100644 (file)
@@ -53,7 +53,7 @@ class App {
                // initialize the dispatcher and run all the middleware before the controller
                $dispatcher = $container['Dispatcher'];
 
-               list($httpHeaders, $responseHeaders, $output) =
+               list($httpHeaders, $responseHeaders, $responseCookies, $output) =
                        $dispatcher->dispatch($controller, $methodName);
 
                if(!is_null($httpHeaders)) {
@@ -64,6 +64,14 @@ class App {
                        header($name . ': ' . $value);
                }
 
+               foreach($responseCookies as $name => $value) {
+                       $expireDate = null;
+                       if($value['expireDate'] instanceof \DateTime) {
+                               $expireDate = $value['expireDate']->getTimestamp();
+                       }
+                       setcookie($name, $value['value'], $expireDate, \OC::$WEBROOT, null, \OC::$server->getConfig()->getSystemValue('forcessl', false), true);
+               }
+
                if(!is_null($output)) {
                        header('Content-Length: ' . strlen($output));
                        print($output);
index 29a661d5743ed698f541cc9c3b53929e42a93593..24540ef3c94814229ae02f21e18ccd6ec38abe3d 100644 (file)
@@ -48,7 +48,7 @@ class Dispatcher {
         * @param Http $protocol the http protocol with contains all status headers
         * @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
         * runs the middleware
-        * @param ControllerMethodReflector the reflector that is used to inject
+        * @param ControllerMethodReflector $reflector the reflector that is used to inject
         * the arguments for the controller
         * @param IRequest $request the incoming request
         */
@@ -71,6 +71,7 @@ class Dispatcher {
         * @return array $array[0] contains a string with the http main header,
         * $array[1] contains headers in the form: $key => value, $array[2] contains
         * the response output
+        * @throws \Exception
         */
        public function dispatch(Controller $controller, $methodName) {
                $out = array(null, array(), null);
@@ -102,13 +103,14 @@ class Dispatcher {
                // get the output which should be printed and run the after output
                // middleware to modify the response
                $output = $response->render();
-               $out[2] = $this->middlewareDispatcher->beforeOutput(
+               $out[3] = $this->middlewareDispatcher->beforeOutput(
                        $controller, $methodName, $output);
 
                // depending on the cache object the headers need to be changed
                $out[0] = $this->protocol->getStatusHeader($response->getStatus(),
                        $response->getLastModified(), $response->getETag());
-               $out[1] = $response->getHeaders();
+               $out[1] = array_merge($response->getHeaders());
+               $out[2] = $response->getCookies();
 
                return $out;
        }
index 354911fee2139900e7763e0098ca6c1b01885f99..67e72cff6d9c13ec19962eaf1abf65e85d3fee56 100644 (file)
@@ -45,9 +45,16 @@ class Response {
        );
 
 
+       /**
+        * Cookies that will be need to be constructed as header
+        * @var array
+        */
+       private $cookies = array();
+
+
        /**
         * HTTP status code - defaults to STATUS OK
-        * @var string
+        * @var int
         */
        private $status = Http::STATUS_OK;
 
@@ -70,6 +77,7 @@ class Response {
         * Caches the response
         * @param int $cacheSeconds the amount of seconds that should be cached
         * if 0 then caching will be disabled
+        * @return $this
         */
        public function cacheFor($cacheSeconds) {
 
@@ -83,13 +91,68 @@ class Response {
                return $this;
        }
 
+       /**
+        * Adds a new cookie to the response
+        * @param string $name The name of the cookie
+        * @param string $value The value of the cookie
+        * @param \DateTime|null $expireDate Date on that the cookie should expire, if set
+        *                                                                      to null cookie will be considered as session
+        *                                                                      cookie.
+        * @return $this
+        */
+       public function addCookie($name, $value, \DateTime $expireDate = null) {
+               $this->cookies[$name] = array('value' => $value, 'expireDate' => $expireDate);
+               return $this;
+       }
+
+
+       /**
+        * Set the specified cookies
+        * @param array $cookies array('foo' => array('value' => 'bar', 'expire' => null))
+        * @return $this
+        */
+       public function setCookies(array $cookies) {
+               $this->cookies = $cookies;
+               return $this;
+       }
+
+
+       /**
+        * Invalidates the specified cookie
+        * @param string $name
+        * @return $this
+        */
+       public function invalidateCookie($name) {
+               $this->addCookie($name, 'expired', new \DateTime('1971-01-01 00:00'));
+               return $this;
+       }
+
+       /**
+        * Invalidates the specified cookies
+        * @param array $cookieNames array('foo', 'bar')
+        * @return $this
+        */
+       public function invalidateCookies(array $cookieNames) {
+               foreach($cookieNames as $cookieName) {
+                       $this->invalidateCookie($cookieName);
+               }
+               return $this;
+       }
+
+       /**
+        * Returns the cookies
+        * @return array
+        */
+       public function getCookies() {
+               return $this->cookies;
+       }
 
        /**
         * Adds a new header to the response that will be called before the render
         * function
         * @param string $name The name of the HTTP header
         * @param string $value The value, null will delete it
-        * @return Response Reference to this object
+        * @return $this
         */
        public function addHeader($name, $value) {
                $name = trim($name);  // always remove leading and trailing whitespace
@@ -108,10 +171,10 @@ class Response {
 
        /**
         * Set the headers
-        * @param array key value header pairs
-        * @return Response Reference to this object
+        * @param array $headers value header pairs
+        * @return $this
         */
-       public function setHeaders($headers) {
+       public function setHeaders(array $headers) {
                $this->headers = $headers;
 
                return $this;
index bd565e9765eedc8164798293e476980f7da90c53..86128db118fcc941e050273489a3e8bb6f5b40cb 100644 (file)
@@ -63,7 +63,7 @@ class AppTest extends \Test\TestCase {
 
 
        public function testControllerNameAndMethodAreBeingPassed(){
-               $return = array(null, array(), null);
+               $return = array(null, array(), array(), null);
                $this->dispatcher->expects($this->once())
                        ->method('dispatch')
                        ->with($this->equalTo($this->controller),
index f92e7161e6bc9670b9d13363d29dafeed28e83c7..45ebd6fce966ed7721575c2bcc0f3a9e3b1b316b 100644 (file)
@@ -227,7 +227,7 @@ class DispatcherTest extends \Test\TestCase {
 
                $this->assertEquals($httpHeaders, $response[0]);
                $this->assertEquals($responseHeaders, $response[1]);
-               $this->assertEquals($out, $response[2]);
+               $this->assertEquals($out, $response[3]);
        }
 
 
@@ -246,7 +246,7 @@ class DispatcherTest extends \Test\TestCase {
 
                $this->assertEquals($httpHeaders, $response[0]);
                $this->assertEquals($responseHeaders, $response[1]);
-               $this->assertEquals($out, $response[2]);
+               $this->assertEquals($out, $response[3]);
        }
 
 
@@ -301,7 +301,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'exec');
 
-               $this->assertEquals('[3,true,4,1]', $response[2]);
+               $this->assertEquals('[3,true,4,1]', $response[3]);
        }
 
 
@@ -324,7 +324,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'exec');
 
-               $this->assertEquals('[3,true,4,7]', $response[2]);
+               $this->assertEquals('[3,true,4,7]', $response[3]);
        }
 
 
@@ -350,7 +350,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'exec');
 
-               $this->assertEquals('{"text":[3,false,4,1]}', $response[2]);
+               $this->assertEquals('{"text":[3,false,4,1]}', $response[3]);
        }
 
 
@@ -375,7 +375,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'execDataResponse');
 
-               $this->assertEquals('{"text":[3,false,4,1]}', $response[2]);
+               $this->assertEquals('{"text":[3,false,4,1]}', $response[3]);
        }
 
 
@@ -401,7 +401,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'exec');
 
-               $this->assertEquals('{"text":[3,false,4,1]}', $response[2]);
+               $this->assertEquals('{"text":[3,false,4,1]}', $response[3]);
        }
 
 
@@ -429,7 +429,7 @@ class DispatcherTest extends \Test\TestCase {
                $this->dispatcherPassthrough();
                $response = $this->dispatcher->dispatch($controller, 'exec');
 
-               $this->assertEquals('{"text":[3,true,4,1]}', $response[2]);
+               $this->assertEquals('{"text":[3,true,4,1]}', $response[3]);
        }
 
 
index 04e19fdaf71f82e782238f4487cbc0b0f42c4cce..b4352348bae1322029c4147df45adc5baad9e95f 100644 (file)
@@ -76,6 +76,92 @@ class ResponseTest extends \Test\TestCase {
        }
 
 
+       public function testAddCookie() {
+               $this->childResponse->addCookie('foo', 'bar');
+               $this->childResponse->addCookie('bar', 'foo', new \DateTime('1970-01-01'));
+
+               $expectedResponse = array(
+                       'foo' => array(
+                               'value' => 'bar',
+                               'expireDate' => null,
+                       ),
+                       'bar' => array(
+                               'value' => 'foo',
+                               'expireDate' => new \DateTime('1970-01-01')
+                       )
+               );
+               $this->assertEquals($expectedResponse, $this->childResponse->getCookies());
+       }
+
+
+       function testSetCookies() {
+               $expected = array(
+                       'foo' => array(
+                               'value' => 'bar',
+                               'expireDate' => null,
+                       ),
+                       'bar' => array(
+                               'value' => 'foo',
+                               'expireDate' => new \DateTime('1970-01-01')
+                       )
+               );
+
+               $this->childResponse->setCookies($expected);
+               $cookies = $this->childResponse->getCookies();
+
+               $this->assertEquals($expected, $cookies);
+       }
+
+
+       function testInvalidateCookie() {
+               $this->childResponse->addCookie('foo', 'bar');
+               $this->childResponse->invalidateCookie('foo');
+               $expected = array(
+                       'foo' => array(
+                               'value' => 'expired',
+                               'expireDate' => new \DateTime('1971-01-01')
+                       )
+               );
+
+               $cookies = $this->childResponse->getCookies();
+
+               $this->assertEquals($expected, $cookies);
+       }
+
+
+       function testInvalidateCookies() {
+               $this->childResponse->addCookie('foo', 'bar');
+               $this->childResponse->addCookie('bar', 'foo');
+               $expected = array(
+                       'foo' => array(
+                               'value' => 'bar',
+                               'expireDate' => null
+                       ),
+                       'bar' => array(
+                               'value' => 'foo',
+                               'expireDate' => null
+                       )
+               );
+               $cookies = $this->childResponse->getCookies();
+               $this->assertEquals($expected, $cookies);
+
+               $this->childResponse->invalidateCookies(array('foo', 'bar'));
+               $expected = array(
+                       'foo' => array(
+                               'value' => 'expired',
+                               'expireDate' => new \DateTime('1971-01-01')
+                       ),
+                       'bar' => array(
+                               'value' => 'expired',
+                               'expireDate' => new \DateTime('1971-01-01')
+                       )
+               );
+
+               $cookies = $this->childResponse->getCookies();
+               $this->assertEquals($expected, $cookies);
+       }
+
+
        public function testRenderReturnNullByDefault(){
                $this->assertEquals(null, $this->childResponse->render());
        }