Skip to content
Permalink
Browse files

Add support for cookie parsing.

Also add support for headers with multiple values, like Set-Cookie.
  • Loading branch information...
markstory committed Dec 27, 2012
1 parent 53e5fd3 commit b0d8b378504e24b7c9c8a439441589347f88e0e9
Showing with 121 additions and 9 deletions.
  1. +83 −7 lib/Cake/Network/Http/Response.php
  2. +38 −2 lib/Cake/Test/TestCase/Network/Http/ResponseTest.php
@@ -44,6 +44,13 @@ class Response {
*/
protected $_headers;
/**
* The array of cookies in the response.
*
* @var array
*/
protected $_cookies;
/**
* The response body
*
@@ -77,13 +84,57 @@ protected function _parseHeaders($headers) {
$this->_code = $matches[1];
continue;
}
if (is_int($key)) {
list($name, $value) = explode(':', $value, 2);
$name = $this->_normalizeHeader($name);
$this->_headers[trim($name)] = trim($value);
list($name, $value) = explode(':', $value, 2);
$value = trim($value);
$name = $this->_normalizeHeader($name);
if ($name === 'Set-Cookie') {
$this->_parseCookie($value);
}
if (isset($this->_headers[$name])) {
$this->_headers[$name] = (array)$this->_headers[$name];
$this->_headers[$name][] = $value;
} else {
$this->_headers[$name] = $value;
}
}
}
/**
* Parse a cookie header into data.
*
* @param string $value The cookie value to parse.
* @return void
*/
protected function _parseCookie($value) {
$nestedSemi = '";"';
if (strpos($value, $nestedSemi) !== false) {
$value = str_replace($nestedSemi, "{__cookie_replace__}", $value);
$parts = explode(';', $value);
$parts = str_replace("{__cookie_replace__}", $nestedSemi, $parts);
} else {
$parts = preg_split('/\;[ \t]*/', $value);
}
$name = false;
$cookie = [];
foreach ($parts as $i => $part) {
if (strpos($part, '=') !== false) {
list($key, $value) = explode('=', $part, 2);
} else {
$key = $part;
$value = true;
}
if ($i === 0) {
$name = $key;
$cookie['value'] = $value;
continue;
}
$key = strtolower($key);
if (!isset($cookie[$key])) {
$cookie[$key] = $value;
}
}
$this->_cookies[$name] = $cookie;
}
/**
@@ -93,7 +144,7 @@ protected function _parseHeaders($headers) {
* @return string Normalized header name.
*/
protected function _normalizeHeader($name) {
$parts = explode('-', $name);
$parts = explode('-', trim($name));
$parts = array_map('strtolower', $parts);
$parts = array_map('ucfirst', $parts);
return implode('-', $parts);
@@ -143,9 +194,12 @@ public function encoding() {
/**
* Read single/multiple header value(s) out.
*
* @param string $name The name of the header you want. Leave
* @param string $name The name of the header you want. Leave
* null to get all headers.
* @return null|string
* @return mixed Null when the header doesn't exist. An array
* will be returned when getting all headers or when getting
* a header that had multiple values set. Otherwise a string
* will be returned.
*/
public function header($name = null) {
if ($name === null) {
@@ -158,6 +212,28 @@ public function header($name = null) {
return $this->_headers[$name];
}
/**
* Read single/multiple cookie values out.
*
* @param string $name The name of the cookie you want. Leave
* null to get all cookies.
* @param boolean $all Get all parts of the cookie. When false only
* the value will be returned.
* @return mixed
*/
public function cookie($name = null, $all = false) {
if ($name === null) {
return $this->_cookies;
}
if (!isset($this->_cookies[$name])) {
return null;
}
if ($all) {
return $this->_cookies[$name];
}
return $this->_cookies[$name]['value'];
}
/**
* Get the response body.
*
@@ -128,12 +128,48 @@ public function testIsRedirect() {
$this->assertFalse($response->isRedirect());
}
/**
* Test parsing / getting cookies.
*
* @return void
*/
public function testCookie() {
$this->markTestIncomplete();
$headers = [
'HTTP/1.0 200 Ok',
'Set-Cookie: test=value',
'Set-Cookie: session=123abc',
'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure',
];
$response = new Response($headers, '');
$this->assertEquals('value', $response->cookie('test'));
$this->assertEquals('123abc', $response->cookie('session'));
$this->assertEquals('soon', $response->cookie('expiring'));
$result = $response->cookie('expiring', true);
$this->assertTrue($result['httponly']);
$this->assertTrue($result['secure']);
$this->assertEquals(
'Wed, 09-Jun-2021 10:18:14 GMT',
$result['expires']
);
$this->assertEquals('/', $result['path']);
$result = $response->header('set-cookie');
$this->assertCount(3, $result, 'Should be an array.');
}
/**
* Test statusCode()
*
* @return void
*/
public function testStatusCode() {
$this->markTestIncomplete();
$headers = [
'HTTP/1.0 404 Not Found',
'Content-Type: text/html'
];
$response = new Response($headers, '');
$this->assertEquals(404, $response->statusCode());
}
public function testEncoding() {

0 comments on commit b0d8b37

Please sign in to comment.
You can’t perform that action at this time.