Fix #27: Allow case-insensitive access to request headers and response headers

This commit is contained in:
Zach Borboa
2014-03-14 01:27:06 -07:00
parent 875f636931
commit 6c9709af59
3 changed files with 98 additions and 1 deletions
+35 -1
View File
@@ -204,7 +204,7 @@ class Curl {
private function _parseHeaders($raw_headers) {
$raw_headers = preg_split('/\r\n/', $raw_headers, null, PREG_SPLIT_NO_EMPTY);
$http_headers = array();
$http_headers = new CaseInsensitiveArray();
for ($i = 1; $i < count($raw_headers); $i++) {
list($key, $value) = explode(':', $raw_headers[$i], 2);
@@ -305,6 +305,40 @@ class Curl {
}
}
class CaseInsensitiveArray implements ArrayAccess, Countable {
private $container = array();
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
}
else {
$index = array_search(strtolower($offset), array_keys(array_change_key_case($this->container, CASE_LOWER)));
if (!($index === false)) {
unset($this->container[array_keys($this->container)[$index]]);
}
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return array_key_exists(strtolower($offset), array_change_key_case($this->container, CASE_LOWER));
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
$index = array_search(strtolower($offset), array_keys(array_change_key_case($this->container, CASE_LOWER)));
return $index === false ? null : array_values($this->container)[$index];
}
public function count() {
return count($this->container);
}
}
function is_array_assoc($array) {
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
+58
View File
@@ -26,6 +26,43 @@ class CurlTest extends PHPUnit_Framework_TestCase {
)));
}
public function testCaseInsensitiveArrayGet() {
$array = new CaseInsensitiveArray();
$this->assertTrue(is_object($array));
$this->assertCount(0, $array);
$this->assertNull($array[(string)rand()]);
$array['foo'] = 'bar';
$this->assertNotEmpty($array);
$this->assertCount(1, $array);
}
public function testCaseInsensitiveArraySet() {
function assertions($array, $count=1) {
PHPUnit_Framework_Assert::assertCount($count, $array);
PHPUnit_Framework_Assert::assertTrue($array['foo'] === 'bar');
PHPUnit_Framework_Assert::assertTrue($array['Foo'] === 'bar');
PHPUnit_Framework_Assert::assertTrue($array['FOo'] === 'bar');
PHPUnit_Framework_Assert::assertTrue($array['FOO'] === 'bar');
}
$array = new CaseInsensitiveArray();
$array['foo'] = 'bar';
assertions($array);
$array['Foo'] = 'bar';
assertions($array);
$array['FOo'] = 'bar';
assertions($array);
$array['FOO'] = 'bar';
assertions($array);
$array['baz'] = 'qux';
assertions($array, 2);
}
public function testUserAgent() {
$test = new Test();
$test->curl->setUserAgent(Curl::USER_AGENT);
@@ -248,6 +285,27 @@ class CurlTest extends PHPUnit_Framework_TestCase {
)) === 'application/json');
}
public function testHeaderCaseSensitivity() {
$content_type = 'application/json';
$test = new Test();
$test->curl->setHeader('Content-Type', $content_type);
$test->server('response_header', 'GET');
$request_headers = $test->curl->request_headers;
$response_headers = $test->curl->response_headers;
$this->assertEquals($request_headers['Content-Type'], $content_type);
$this->assertEquals($request_headers['Content-Type'], $content_type);
$this->assertEquals($request_headers['content-type'], $content_type);
$this->assertEquals($request_headers['CONTENT-TYPE'], $content_type);
$etag = $response_headers['ETag'];
$this->assertEquals($response_headers['ETAG'], $etag);
$this->assertEquals($response_headers['etag'], $etag);
$this->assertEquals($response_headers['eTAG'], $etag);
$this->assertEquals($response_headers['eTaG'], $etag);
}
public function testRequestURL() {
$test = new Test();
$this->assertFalse(substr($test->server('request_uri', 'GET'), -1) === '?');
+5
View File
@@ -79,6 +79,11 @@ else if ($test === 'cookiejar') {
setcookie('mycookie', 'yum');
exit;
}
else if ($test === 'response_header') {
header('Content-Type: application/json');
header('ETag: ' . md5('worldpeace'));
exit;
}
header('Content-Type: text/plain');