Skip to content

Commit

Permalink
Allow cookie collections to store duplicates.
Browse files Browse the repository at this point in the history
Duplicate cookie names are required for Http\Client use cases. Because
a client can make requests to multiple hosts, we need to store and track
all the cookies. This seemed preferrable to having a cookie collection
per domain in the client.
  • Loading branch information
markstory committed Mar 24, 2017
1 parent 32d2f13 commit 0f6dffd
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
35 changes: 25 additions & 10 deletions src/Http/Cookie/CookieCollection.php
Expand Up @@ -65,20 +65,22 @@ public function count()
/**
* Add a cookie and get an updated collection.
*
* Cookie names do not have to be unique in a collection, but
* having duplicate cookie names will change how get() behaves.
*
* @param \Cake\Http\Cookie\CookieInterface $cookie Cookie instance to add.
* @return static
*/
public function add(CookieInterface $cookie)
{
$key = mb_strtolower($cookie->getName());
$new = clone $this;
$new->cookies[$key] = $cookie;
$new->cookies[] = $cookie;

return $new;
}

/**
* Get a cookie by name
* Get the first cookie by name.
*
* If the provided name matches a URL (matches `#^https?://#`) this method
* will assume you want a list of cookies that match that URL. This is
Expand All @@ -91,8 +93,10 @@ public function add(CookieInterface $cookie)
public function get($name)
{
$key = mb_strtolower($name);
if (isset($this->cookies[$key])) {
return $this->cookies[$key];
foreach ($this->cookies as $cookie) {
if (mb_strtolower($cookie->getName()) === $key) {
return $cookie;
}
}

return null;
Expand All @@ -106,11 +110,18 @@ public function get($name)
*/
public function has($name)
{
return isset($this->cookies[mb_strtolower($name)]);
$key = mb_strtolower($name);
foreach ($this->cookies as $cookie) {
if (mb_strtolower($cookie->getName()) === $key) {
return true;
}
}

return false;
}

/**
* Remove a cookie from the collection and get a new collection
* Create a new collection with all cookies matching $name removed.
*
* If the cookie is not in the collection, this method will do nothing.
*
Expand All @@ -120,7 +131,12 @@ public function has($name)
public function remove($name)
{
$new = clone $this;
unset($new->cookies[mb_strtolower($name)]);
$key = mb_strtolower($name);
foreach ($new->cookies as $i => $cookie) {
if (mb_strtolower($cookie->getName()) === $key) {
unset($new->cookies[$i]);
}
}

return $new;
}
Expand Down Expand Up @@ -189,8 +205,7 @@ public function addFromResponse(ResponseInterface $response, RequestInterface $r
if ($expires && $expires <= time()) {
continue;
}
$key = mb_strtolower($cookie->getName());
$new->cookies[$key] = $cookie;
$new->cookies[] = $cookie;
}

return $new;
Expand Down
21 changes: 17 additions & 4 deletions tests/TestCase/Http/Cookie/CookieCollectionTest.php
Expand Up @@ -92,12 +92,24 @@ public function testAdd()
$this->assertFalse($collection->has('remember_me'), 'Original instance not modified');
$this->assertTrue($new->has('remember_me'));
$this->assertSame($remember, $new->get('remember_me'));
}

/**
* Cookie collections need to support duplicate cookie names because
* of use cases in Http\Client
*
* @return void
*/
public function testAddDuplicates()
{
$remember = new Cookie('remember_me', 'yes');
$rememberNo = new Cookie('remember_me', 'no');
$second = $new->add($remember)->add($rememberNo);
$this->assertCount(1, $second);
$this->assertNotSame($second, $new);
$this->assertSame($rememberNo, $second->get('remember_me'));
$collection = new CookieCollection([]);
$new = $collection->add($remember)->add($rememberNo);

$this->assertCount(2, $new);
$this->assertNotSame($new, $collection);
$this->assertSame($remember, $new->get('remember_me'), 'get() fetches first cookie');
}

/**
Expand Down Expand Up @@ -205,6 +217,7 @@ public function testAddFromResponse()
$this->assertSame('/app', $new->get('test')->getPath(), 'cookies should inherit request path');
$this->assertSame('/', $new->get('expiring')->getPath(), 'path attribute should be used.');

$this->assertSame(0, $new->get('test')->getExpiry(), 'No expiry');
$this->assertSame(0, $new->get('session')->getExpiry(), 'No expiry');
$this->assertSame(
'2021-06-09 10:18:14',
Expand Down

0 comments on commit 0f6dffd

Please sign in to comment.