Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move deprecated code into the deprecated client CookieCollection.
This allows the 'new' collection to stay simpler and cleaner.
  • Loading branch information
markstory committed Mar 28, 2017
1 parent 0baa525 commit 24e8b47
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 218 deletions.
77 changes: 26 additions & 51 deletions src/Http/Client/CookieCollection.php
Expand Up @@ -13,22 +13,19 @@
*/
namespace Cake\Http\Client;

use Cake\Http\Cookie\CookieCollection as BaseCollection;

/**
* Container class for cookies used in Http\Client.
*
* Provides cookie jar like features for storing cookies between
* requests, as well as appending cookies to new requests.
*
* @deprecated 3.5.0 Use Cake\Http\Cookie\CookieCollection instead.
*/
class CookieCollection
class CookieCollection extends BaseCollection
{

/**
* The cookies stored in this jar.
*
* @var array
*/
protected $_cookies = [];

/**
* Store the cookies from a response.
*
Expand All @@ -45,27 +42,13 @@ public function store(Response $response, $url)
$path = parse_url($url, PHP_URL_PATH);
$path = $path ?: '/';

$cookies = $response->cookies();
foreach ($cookies as $name => $cookie) {
if (empty($cookie['domain'])) {
$cookie['domain'] = $host;
}
if (empty($cookie['path'])) {
$cookie['path'] = $path;
}
$key = implode(';', [$cookie['name'], $cookie['domain'], $cookie['path']]);

$expires = isset($cookie['expires']) ? $cookie['expires'] : false;
$expiresTime = false;
if ($expires) {
$expiresTime = strtotime($expires);
}
if ($expiresTime && $expiresTime <= time()) {
unset($this->_cookies[$key]);
continue;
}
$this->_cookies[$key] = $cookie;
$header = $response->getHeader('Set-Cookie');
$cookies = $this->parseSetCookieHeader($header);
$cookies = $this->setRequestDefaults($cookies, $host, $path);
foreach ($cookies as $cookie) {
$this->cookies[$cookie->getId()] = $cookie;
}
$this->removeExpiredCookies($host, $path);
}

/**
Expand All @@ -83,28 +66,7 @@ public function get($url)
$host = parse_url($url, PHP_URL_HOST);
$scheme = parse_url($url, PHP_URL_SCHEME);

$out = [];
foreach ($this->_cookies as $cookie) {
if ($scheme === 'http' && !empty($cookie['secure'])) {
continue;
}
if (strpos($path, $cookie['path']) !== 0) {
continue;
}
$leadingDot = $cookie['domain'][0] === '.';
if ($leadingDot) {
$cookie['domain'] = ltrim($cookie['domain'], '.');
}

$pattern = '/' . preg_quote(substr($cookie['domain'], 1), '/') . '$/';
if (!preg_match($pattern, $host)) {
continue;
}

$out[$cookie['name']] = $cookie['value'];
}

return $out;
return $this->findMatchingCookies($scheme, $host, $path);
}

/**
Expand All @@ -114,7 +76,20 @@ public function get($url)
*/
public function getAll()
{
return array_values($this->_cookies);
$out = [];
foreach ($this->cookies as $cookie) {
$out[] = [
'name' => $cookie->getName(),
'value' => $cookie->getValue(),
'path' => $cookie->getPath(),
'domain' => $cookie->getDomain(),
'secure' => $cookie->isSecure(),
'httponly' => $cookie->isHttpOnly(),
'expires' => $cookie->getExpiry()
];
}

return $out;
}
}

Expand Down
85 changes: 5 additions & 80 deletions src/Http/Cookie/CookieCollection.php
Expand Up @@ -82,19 +82,11 @@ public function add(CookieInterface $cookie)
/**
* Get the first cookie by name.
*
* If the provided name matches a URL (starts with `http:`) this method
* will assume you want a list of cookies that match that URL. This is
* backwards compatible behavior that will be removed in 4.0.0
*
* @param string $name The name of the cookie. If the name looks like a URL,
* backwards compatible behavior will be used.
* @return \Cake\Http\Cookie\CookieInterface|null|array
* @param string $name The name of the cookie.
* @return \Cake\Http\Cookie\CookieInterface|null
*/
public function get($name)
{
if (substr($name, 0, 4) === 'http') {
return $this->getByUrl($name);
}
$key = mb_strtolower($name);
foreach ($this->cookies as $cookie) {
if (mb_strtolower($cookie->getName()) === $key) {
Expand All @@ -105,21 +97,6 @@ public function get($name)
return null;
}

/**
* Backwards compatibility helper for consumers of Client\CookieCollection
*
* @param string $url The url to get cookies for.
* @return array An array of matching cookies.
*/
protected function getByUrl($url)
{
$path = parse_url($url, PHP_URL_PATH) ?: '/';
$host = parse_url($url, PHP_URL_HOST);
$scheme = parse_url($url, PHP_URL_SCHEME);

return $this->findMatchingCookies($scheme, $host, $path);
}

/**
* Check if a cookie with the given name exists
*
Expand Down Expand Up @@ -344,7 +321,8 @@ protected function parseSetCookieHeader($values)
}
$expires = null;
if ($cookie['expires']) {
$expires = new DateTime($cookie['expires']);
$expires = new DateTime();
$expires->setTimestamp(strtotime($cookie['expires']));
}

$cookies[] = new Cookie(
Expand All @@ -368,7 +346,7 @@ protected function parseSetCookieHeader($values)
* @param string $path The path to check for expired cookies on.
* @return void
*/
private function removeExpiredCookies($host, $path)
protected function removeExpiredCookies($host, $path)
{
$time = time();
$hostPattern = '/' . preg_quote($host, '/') . '$/';
Expand All @@ -384,57 +362,4 @@ private function removeExpiredCookies($host, $path)
}
}
}

/**
* Store the cookies contained in a response
*
* This method operates on the collection in a mutable way for backwards
* compatibility reasons. This method should not be used and is only
* provided for backwards compatibility.
*
* @param \Cake\Http\Client\Response $response The response to read cookies from
* @param string $url The request URL used for default host/path values.
* @return void
* @deprecated 3.5.0 Will be removed in 4.0.0. Use `addFromResponse()` instead.
*/
public function store(ClientResponse $response, $url)
{
$host = parse_url($url, PHP_URL_HOST);
$path = parse_url($url, PHP_URL_PATH);
$path = $path ?: '/';

$header = $response->getHeader('Set-Cookie');
$cookies = $this->parseSetCookieHeader($header);
$cookies = $this->setRequestDefaults($cookies, $host, $path);
foreach ($cookies as $cookie) {
$this->cookies[] = $cookie;
}
$this->removeExpiredCookies($host, $path);
}

/**
* Get all cookie data as arrays.
*
* This method should not be used and is only provided for backwards compatibility.
*
* @return array
* @deprecated 3.5.0 Will be removed in 4.0.0
*/
public function getAll()
{
$out = [];
foreach ($this->cookies as $cookie) {
$out[] = [
'name' => $cookie->getName(),
'value' => $cookie->getValue(),
'path' => $cookie->getPath(),
'domain' => $cookie->getDomain(),
'secure' => $cookie->isSecure(),
'httponly' => $cookie->isHttpOnly(),
'expires' => $cookie->getExpiry()
];
}

return $out;
}
}
21 changes: 17 additions & 4 deletions tests/TestCase/Http/Client/CookieCollectionTest.php
Expand Up @@ -58,13 +58,19 @@ public function testStore()
'name' => 'first',
'value' => '1',
'path' => '/some/path',
'domain' => 'example.com'
'domain' => 'example.com',
'secure' => false,
'httponly' => false,
'expires' => 0,
],
[
'name' => 'second',
'value' => '2',
'path' => '/',
'domain' => '.foo.example.com'
'domain' => '.foo.example.com',
'secure' => false,
'httponly' => false,
'expires' => 0,
],
];
$this->assertEquals($expected, $result);
Expand Down Expand Up @@ -93,7 +99,10 @@ public function testStoreSecure()
'name' => 'first',
'value' => '1',
'path' => '/some/path',
'domain' => 'example.com'
'domain' => 'example.com',
'secure' => false,
'httponly' => false,
'expires' => 0,
],
[
'name' => 'second',
Expand All @@ -102,6 +111,7 @@ public function testStoreSecure()
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'expires' => 0,
],
];
$this->assertEquals($expected, $result);
Expand Down Expand Up @@ -159,7 +169,10 @@ public function testStoreExpiring()
'name' => 'second',
'value' => '2',
'path' => '/',
'domain' => 'example.com'
'domain' => 'example.com',
'expires' => 0,
'secure' => false,
'httponly' => false,
],
];
$this->assertEquals($expected, $result);
Expand Down
83 changes: 0 additions & 83 deletions tests/TestCase/Http/Cookie/CookieCollectionTest.php
Expand Up @@ -175,34 +175,6 @@ public function testGetByName()
$this->assertSame($cookies[0], $collection->get('remember_me'));
}

/**
* Test that get() provides backwards compat behavior.
*
* When the parameter is a string that looks like a URL
*
* @return void
*/
public function testGetBackwardsCompatibility()
{
$cookies = [
new Cookie('test', 'value', null, '/api', 'example.com', true),
new Cookie('test_two', 'value2', null, '/blog', 'blog.example.com', true),
new Cookie('test3', 'value3', null, '/blog', 'blog.example.com', false),
];
$collection = new CookieCollection($cookies);
$result = $collection->get('http://example.com/api');
$this->assertSame([], $result);

$result = $collection->get('https://example.com/api');
$this->assertSame(['test' => 'value'], $result);

$result = $collection->get('http://foo.blog.example.com/blog/path');
$this->assertSame(['test3' => 'value3'], $result);

$result = $collection->get('https://foo.blog.example.com/blog/path');
$this->assertSame(['test_two' => 'value2', 'test3' => 'value3'], $result);
}

/**
* Test that the constructor takes only an array of objects implementing
* the CookieInterface
Expand Down Expand Up @@ -447,59 +419,4 @@ public function testAddToRequestSecureCrumb()
$request = $collection->addToRequest($request);
$this->assertSame(['public' => 'b'], $request->getCookieParams());
}

/**
* Test that store() provides backwards compat behavior.
*
* @return void
*/
public function testStoreCompatibility()
{
$collection = new CookieCollection();
$response = (new ClientResponse())
->withAddedHeader('Set-Cookie', 'test=value')
->withAddedHeader('Set-Cookie', 'expired=soon; Expires=Wed, 09-Jun-2012 10:18:14 GMT; Path=/;');
$result = $collection->store($response, 'http://example.com/blog');

$this->assertNull($result);
$this->assertCount(1, $collection, 'Should store 1 cookie');
$this->assertTrue($collection->has('test'));
$this->assertFalse($collection->has('expired'));
}

/**
* Test that getAll() provides backwards compat behavior.
*
* @return void
*/
public function testGetAllBackwardsCompatibility()
{
$expires = new DateTime('-2 seconds');
$cookies = [
new Cookie('test', 'value', $expires, '/api', 'example.com', true, true),
new Cookie('test_two', 'value_two', null, '/blog', 'blog.example.com', true, true),
];
$collection = new CookieCollection($cookies);
$expected = [
[
'name' => 'test',
'value' => 'value',
'path' => '/api',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'expires' => $expires->format('U'),
],
[
'name' => 'test_two',
'value' => 'value_two',
'path' => '/blog',
'domain' => 'blog.example.com',
'secure' => true,
'httponly' => true,
'expires' => 0
],
];
$this->assertEquals($expected, $collection->getAll());
}
}

0 comments on commit 24e8b47

Please sign in to comment.