Navigation Menu

Skip to content

Commit

Permalink
Adapt Network\Http\Client for path based cookies.
Browse files Browse the repository at this point in the history
Following the details on http://curl.haxx.se/rfc/cookie_spec.html
cookies are matched by path now.
  • Loading branch information
markstory committed Jan 12, 2013
1 parent b4a5edf commit 64890e5
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 19 deletions.
28 changes: 19 additions & 9 deletions lib/Cake/Network/Http/Client.php
Expand Up @@ -323,18 +323,20 @@ protected function _storeCookies(Response $response, $host) {
$cookies = $response->cookies();
foreach ($cookies as $name => $cookie) {
$expires = isset($cookie['expires']) ? $cookie['expires'] : false;
$domain = isset($cookie['domain']) ? $cookie['domain'] : $host;
$domain = trim($domain, '.');
if ($expires) {
$expires = \DateTime::createFromFormat('D, j-M-Y H:i:s e', $expires);
}
if ($expires && $expires->getTimestamp() <= time()) {
continue;
}
if (empty($this->_cookies[$domain])) {
$this->_cookies[$domain] = [];
if (empty($cookie['domain'])) {
$cookie['domain'] = $host;
}
$this->_cookies[$domain][$name] = $cookie['value'];
$cookie['domain'] = trim($cookie['domain'], '.');
if (empty($cookie['path'])) {
$cookie['path'] = '/';
}
$this->_cookies[] = $cookie;
}
}

Expand All @@ -349,11 +351,19 @@ protected function _storeCookies(Response $response, $host) {
* @return void
*/
protected function _addCookies(Request $request) {
$parts = explode('.', parse_url($request->url(), PHP_URL_HOST));
$url = $request->url();
$path = parse_url($url, PHP_URL_PATH);
$parts = explode('.', parse_url($url, PHP_URL_HOST));
$domains = [];
for ($i = 0, $len = count($parts); $i < $len - 1; $i++) {
$host = implode('.', array_slice($parts, $i));
if (isset($this->_cookies[$host])) {
$request->cookie($this->_cookies[$host]);
$domains[] = implode('.', array_slice($parts, $i));
}
foreach ($this->_cookies as $cookie) {
if (
in_array($cookie['domain'], $domains) &&
strpos($path, $cookie['path']) === 0
) {
$request->cookie($cookie['name'], $cookie['value']);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Cake/Network/Http/Response.php
Expand Up @@ -146,7 +146,6 @@ protected function _parseCookie($value) {
}

$name = false;
$cookie = [];
foreach ($parts as $i => $part) {
if (strpos($part, '=') !== false) {
list($key, $value) = explode('=', $part, 2);
Expand All @@ -164,6 +163,7 @@ protected function _parseCookie($value) {
$cookie[$key] = $value;
}
}
$cookie['name'] = $name;
$this->_cookies[$name] = $cookie;
}

Expand Down
97 changes: 88 additions & 9 deletions lib/Cake/Test/TestCase/Network/Http/ClientTest.php
Expand Up @@ -450,10 +450,18 @@ public function testCookiesExpiring() {

$result = $http->cookies();
$expected = [
'cakephp.org' => [
'first' => 1,
'second' => 2
]
[
'name' => 'first',
'value' => '1',
'domain' => 'cakephp.org',
'path' => '/'
],
[
'name' => 'second',
'value' => '2',
'domain' => 'cakephp.org',
'path' => '/'
],
];
$this->assertEquals($expected, $result);
}
Expand Down Expand Up @@ -514,12 +522,83 @@ public function testCookiesWithDomain() {

$result = $http->cookies();
$expected = [
'cakephp.org' => [
'first' => '1',
'third' => '3',
[
'domain' => 'cakephp.org',
'path' => '/',
'name' => 'first',
'value' => 1,
],
[
'domain' => 'test.cakephp.org',
'path' => '/',
'name' => 'second',
'value' => 2,
],
'test.cakephp.org' => [
'second' => '2',
[
'domain' => 'cakephp.org',
'path' => '/',
'name' => 'third',
'value' => 3,
],
];
$this->assertEquals($expected, $result);
}

/**
* Test path based cookies
*
* @return void
*/
public function testCookiesWithPath() {
$firstHeaders = [
'HTTP/1.0 200 Ok',
'Set-Cookie: first=1; Domain=.cakephp.org; Path=/projects',
];
$firstResponse = new Response($firstHeaders, '');

$secondResponse = new Response([], '');

$mock = $this->getMock(
'Cake\Network\Http\Adapter\Stream',
['send']
);

$mock->expects($this->at(0))
->method('send')
->will($this->returnValue([$firstResponse]));

$mock->expects($this->at(1))
->method('send')
->with($this->attributeEqualTo(
'_cookies',
[]
))
->will($this->returnValue([$secondResponse]));

$mock->expects($this->at(2))
->method('send')
->with($this->attributeEqualTo(
'_cookies',
['first' => '1']
))
->will($this->returnValue([$secondResponse]));

$http = new Client([
'host' => 'cakephp.org',
'adapter' => $mock
]);

$http->get('/projects');
$http->get('/versions');
$http->get('/projects/foo');

$result = $http->cookies();
$expected = [
[
'domain' => 'cakephp.org',
'name' => 'first',
'value' => 1,
'path' => '/projects'
]
];
$this->assertEquals($expected, $result);
Expand Down

0 comments on commit 64890e5

Please sign in to comment.