Skip to content

Commit

Permalink
Store HTTP response headers in case-insensitive array
Browse files Browse the repository at this point in the history
  • Loading branch information
ob-stripe committed Oct 8, 2018
1 parent 86744d2 commit 9973961
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 1 deletion.
1 change: 1 addition & 0 deletions init.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// Utilities
require(dirname(__FILE__) . '/lib/Util/AutoPagingIterator.php');
require(dirname(__FILE__) . '/lib/Util/CaseInsensitiveArray.php');
require(dirname(__FILE__) . '/lib/Util/LoggerInterface.php');
require(dirname(__FILE__) . '/lib/Util/DefaultLogger.php');
require(dirname(__FILE__) . '/lib/Util/RandomGenerator.php');
Expand Down
2 changes: 1 addition & 1 deletion lib/HttpClient/CurlClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public function request($method, $absUrl, $headers, $params, $hasFile)
}

// Create a callback to capture HTTP headers for the response
$rheaders = [];
$rheaders = new Util\CaseInsensitiveArray();
$headerCallback = function ($curl, $header_line) use (&$rheaders) {
// Ignore the HTTP request line (HTTP/1.1 200 OK)
if (strpos($header_line, ":") === false) {
Expand Down
62 changes: 62 additions & 0 deletions lib/Util/CaseInsensitiveArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Stripe\Util;

use ArrayAccess;

/**
* CaseInsensitiveArray is an array-like class that ignores case for keys.
*
* It is used to store HTTP headers. Per RFC 2616, section 4.2:
* Each header field consists of a name followed by a colon (":") and the field value. Field names
* are case-insensitive.
*
* In the context of stripe-php, this is useful because the API will return headers with different
* case depending on whether HTTP/2 is used or not (with HTTP/2, headers are always in lowercase).
*/
class CaseInsensitiveArray implements ArrayAccess
{
private $container = array();

public function __construct($initial_array = array())
{
$this->container = array_map("strtolower", $initial_array);
}

public function offsetSet($offset, $value)
{
$offset = static::maybeLowercase($offset);
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}

public function offsetExists($offset)
{
$offset = static::maybeLowercase($offset);
return isset($this->container[$offset]);
}

public function offsetUnset($offset)
{
$offset = static::maybeLowercase($offset);
unset($this->container[$offset]);
}

public function offsetGet($offset)
{
$offset = static::maybeLowercase($offset);
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}

private static function maybeLowercase($v)
{
if (is_string($v)) {
return strtolower($v);
} else {
return $v;
}
}
}
9 changes: 9 additions & 0 deletions tests/Stripe/HttpClient/CurlClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,13 @@ public function testSleepTimeShouldAddSomeRandomness()
$this->assertEquals($baseValue * 4, $this->sleepTimeMethod->invoke($curlClient, 3));
$this->assertEquals($baseValue * 8, $this->sleepTimeMethod->invoke($curlClient, 4));
}

public function testResponseHeadersCaseInsensitive()
{
$charge = Charge::all();

$headers = $charge->getLastResponse()->headers;
$this->assertNotNull($headers['request-id']);
$this->assertEquals($headers['request-id'], $headers['Request-Id']);
}
}

0 comments on commit 9973961

Please sign in to comment.