summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Nowack <mdnowack@gmail.com>2016-03-15 14:22:23 -0700
committerMatt Nowack <mdnowack@gmail.com>2016-03-15 14:22:23 -0700
commit088bb3c7c68558be1e75bf6288825c6931d94f2c (patch)
treebf6542f559a44fece85cf36caf0c1376f774b4fc
parent4e793d54c4363ffdb66ded0fa2b815eaa38ae344 (diff)
parent79470b7a5eca090de111739512cf8c7e5842cc4d (diff)
downloadtwilio-php-088bb3c7c68558be1e75bf6288825c6931d94f2c.zip
twilio-php-088bb3c7c68558be1e75bf6288825c6931d94f2c.tar.gz
twilio-php-088bb3c7c68558be1e75bf6288825c6931d94f2c.tar.bz2
Merge pull request #37 from twilio/actually-do-http-right5.0.0-RC2
Actually do http right
-rw-r--r--Twilio/Http/CurlClient.php122
-rw-r--r--Twilio/Tests/Bootstrap.php2
-rw-r--r--Twilio/Tests/Unit/Http/CurlClientTest.php224
-rw-r--r--Twilio/Tests/Unit/UnitTest.php10
4 files changed, 303 insertions, 55 deletions
diff --git a/Twilio/Http/CurlClient.php b/Twilio/Http/CurlClient.php
index c397929..e296b2e 100644
--- a/Twilio/Http/CurlClient.php
+++ b/Twilio/Http/CurlClient.php
@@ -12,59 +12,8 @@ class CurlClient implements Client {
public function request($method, $url, $params = array(), $data = array(),
$headers = array(), $user = null, $password = null,
$timeout = null) {
- $timeout = is_null($timeout)
- ? self::DEFAULT_TIMEOUT
- : $timeout;
-
- $options = array(
- CURLOPT_URL => $url,
- CURLOPT_HEADER => true,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_INFILESIZE => -1,
- CURLOPT_HTTPHEADER => array(),
- CURLOPT_TIMEOUT => $timeout,
- );
-
- foreach ($headers as $key => $value) {
- $options[CURLOPT_HTTPHEADER][] = "$key: $value";
- }
-
- if ($user && $password) {
- $options[CURLOPT_HTTPHEADER][] = 'Authorization: Basic ' . base64_encode("$user:$password");
- }
-
- $body = $this->buildQuery($params);
-
- switch (strtolower(trim($method))) {
- case 'get':
- $options[CURLOPT_HTTPGET] = true;
- if ($body) {
- $options[CURLOPT_URL] = $options[CURLOPT_URL] . '?' . $body;
- }
- break;
- case 'post':
- $options[CURLOPT_POST] = true;
- $options[CURLOPT_POSTFIELDS] = $body;
- break;
- case 'put':
- $options[CURLOPT_PUT] = true;
- if ($body) {
- if ($buffer = fopen('php://memory', 'w+')) {
- fwrite($buffer, $body);
- fseek($buffer, 0);
- $options[CURLOPT_INFILE] = $buffer;
- $options[CURLOPT_INFILESIZE] = strlen($body);
- }
- } else {
- throw new EnvironmentException('Unable to open a temporary file');
- }
- break;
- case 'head':
- $opts[CURLOPT_NOBODY] = true;
- break;
- default:
- $opts[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
- }
+ $options = $this->options($method, $url, $params, $data, $headers,
+ $user, $password, $timeout);
try {
if (!$curl = curl_init()) {
@@ -114,9 +63,74 @@ class CurlClient implements Client {
}
}
- protected function buildQuery($params) {
+ public function options($method, $url, $params = array(), $data = array(),
+ $headers = array(), $user = null, $password = null,
+ $timeout = null) {
+
+ $timeout = is_null($timeout)
+ ? self::DEFAULT_TIMEOUT
+ : $timeout;
+
+ $options = array(
+ CURLOPT_URL => $url,
+ CURLOPT_HEADER => true,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_INFILESIZE => -1,
+ CURLOPT_HTTPHEADER => array(),
+ CURLOPT_TIMEOUT => $timeout,
+ );
+
+ foreach ($headers as $key => $value) {
+ $options[CURLOPT_HTTPHEADER][] = "$key: $value";
+ }
+
+ if ($user && $password) {
+ $options[CURLOPT_HTTPHEADER][] = 'Authorization: Basic ' . base64_encode("$user:$password");
+ }
+
+ $body = $this->buildQuery($params);
+ if ($body) {
+ $options[CURLOPT_URL] .= '?' . $body;
+ }
+
+ switch (strtolower(trim($method))) {
+ case 'get':
+ $options[CURLOPT_HTTPGET] = true;
+ break;
+ case 'post':
+ $options[CURLOPT_POST] = true;
+ $options[CURLOPT_POSTFIELDS] = $this->buildQuery($data);
+
+ break;
+ case 'put':
+ $options[CURLOPT_PUT] = true;
+ if ($data) {
+ if ($buffer = fopen('php://memory', 'w+')) {
+ $dataString = $this->buildQuery($data);
+ fwrite($buffer, $dataString);
+ fseek($buffer, 0);
+ $options[CURLOPT_INFILE] = $buffer;
+ $options[CURLOPT_INFILESIZE] = strlen($dataString);
+ } else {
+ throw new EnvironmentException('Unable to open a temporary file');
+ }
+ }
+ break;
+ case 'head':
+ $options[CURLOPT_NOBODY] = true;
+ break;
+ default:
+ $options[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
+ }
+
+ return $options;
+ }
+
+ public function buildQuery($params) {
$parts = array();
+ $params = $params ?: array();
+
foreach ($params as $key => $value) {
if (is_array($value)) {
foreach ($value as $item) {
diff --git a/Twilio/Tests/Bootstrap.php b/Twilio/Tests/Bootstrap.php
index d3ff346..0a55cb2 100644
--- a/Twilio/Tests/Bootstrap.php
+++ b/Twilio/Tests/Bootstrap.php
@@ -10,7 +10,7 @@ $tests = "$root/Tests";
$path = array($library, $tests, get_include_path());
set_include_path(implode(PATH_SEPARATOR, $path));
-$vendorFilename = dirname(__FILE__) . '/../vendor/autoload.php';
+$vendorFilename = dirname(__FILE__) . '/../../vendor/autoload.php';
if (file_exists($vendorFilename)) {
/* composer install */
/** @noinspection PhpIncludeInspection */
diff --git a/Twilio/Tests/Unit/Http/CurlClientTest.php b/Twilio/Tests/Unit/Http/CurlClientTest.php
new file mode 100644
index 0000000..6d1fb1f
--- /dev/null
+++ b/Twilio/Tests/Unit/Http/CurlClientTest.php
@@ -0,0 +1,224 @@
+<?php
+
+
+namespace Twilio\Tests\Unit\Http;
+
+
+use Twilio\Http\CurlClient;
+use Twilio\Tests\Unit\UnitTest;
+
+class CurlClientTest extends UnitTest {
+
+ public function testPreemptiveAuthorization() {
+ $client = new CurlClient();
+
+ $options = $client->options(
+ 'GET',
+ 'http://api.twilio.com',
+ array(),
+ array(),
+ array(),
+ 'test-user',
+ 'test-password'
+ );
+
+ $this->assertArrayHasKey(CURLOPT_HTTPHEADER, $options);
+
+ $headers = $options[CURLOPT_HTTPHEADER];
+
+ $authorization = null;
+ foreach ($headers as $header) {
+ $parse = explode(':', $header);
+ $headerKey = $parse[0];
+ if ($headerKey == 'Authorization') {
+ $authorization = $header;
+ break;
+ }
+ }
+
+ $this->assertNotNull($authorization);
+
+ $authorizationPayload = explode(' ', $authorization);
+ $encodedAuthorization = array_pop($authorizationPayload);
+ $decodedAuthorization = base64_decode($encodedAuthorization);
+
+ $this->assertEquals('test-user:test-password', $decodedAuthorization);
+ }
+
+
+ /**
+ * @param string $message Failure Message
+ * @param mixed[] $params Params with which to build the query
+ * @param string $expected Expected query string
+ * @dataProvider buildQueryProvider
+ */
+ public function testBuildQuery($message, $params, $expected) {
+ $client = new CurlClient();
+ $actual = $client->buildQuery($params);
+ $this->assertEquals($expected, $actual, $message);
+ }
+
+ public function buildQueryProvider() {
+ return array(
+ array(
+ 'Null Params',
+ null,
+ ''
+ ),
+ array(
+ 'Empty Params',
+ array(),
+ '',
+ ),
+ array(
+ 'Single Scalar',
+ array('a' => 'z'),
+ 'a=z',
+ ),
+ array(
+ 'Multiple Scalars',
+ array(
+ 'a' => 'z',
+ 'b' => 'y',
+ ),
+ 'a=z&b=y',
+ ),
+ array(
+ 'Type Coercion: Booleans',
+ array(
+ 'a' => true,
+ 'b' => false,
+ ),
+ 'a=1&b=',
+ ),
+ array(
+ 'Type Coercion: Integers',
+ array(
+ 'a' => 7,
+ 'b' => -14,
+ 'c' => 0,
+ ),
+ 'a=7&b=-14&c=0',
+ ),
+ array(
+ 'Nested Arrays',
+ array(
+ 'a' => array(1, 2, 3),
+ 'b' => array('x', 'y', 'z'),
+ ),
+ 'a=1&a=2&a=3&b=x&b=y&b=z',
+ ),
+ array(
+ 'URL Safety',
+ array(
+ 'a' => 'un$afe:// value!',
+ ),
+ 'a=un%24afe%3A%2F%2F+value%21',
+ )
+ );
+ }
+
+ /**
+ * @param $method
+ * @param $params
+ * @param $expected
+ * @dataProvider queryStringProvider
+ * @throws \Twilio\Exceptions\EnvironmentException
+ */
+ public function testQueryString($method, $params, $expected) {
+ $client = new CurlClient();
+
+ $actual = $client->options($method, 'url', $params);
+
+ $this->assertEquals($expected, $actual[CURLOPT_URL]);
+ }
+
+ public function queryStringProvider() {
+ $methods = array('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'CUSTOM');
+ $cases = array();
+
+ foreach ($methods as $method) {
+ $cases[] = array(
+ $method,
+ array(),
+ 'url',
+ );
+
+ $cases[] = array(
+ $method,
+ array(
+ 'a' => '$z',
+ 'b' => 7,
+ 'c' => array(1, 'x', 2),
+ ),
+ 'url?a=%24z&b=7&c=1&c=x&c=2',
+ );
+ }
+
+ return $cases;
+ }
+
+ /**
+ * @param $params
+ * @param $data
+ * @dataProvider postFieldsProvider
+ * @throws \Twilio\Exceptions\EnvironmentException
+ */
+ public function testPostFields($params, $data, $expected) {
+ $client = new CurlClient();
+
+ $actual = $client->options('POST', 'url', $params, $data);
+
+ $this->assertEquals($expected, $actual[CURLOPT_POSTFIELDS]);
+ }
+
+ public function postFieldsProvider() {
+ return array(
+ array(
+ array(),
+ array(),
+ '',
+ ),
+
+ array(
+ array(
+ 'a' => 'x',
+ ),
+ array(
+ 'a' => 'b',
+ ),
+ 'a=b'
+ ),
+
+ array(
+ array(
+ 'a' => 'x',
+ ),
+ array(
+ 'a' => 'x',
+ ),
+ 'a=x'
+ ),
+
+ array(
+ array(
+ 'a' => 'x',
+ ),
+ array(
+ 'a' => 'z',
+ 'b' => 7,
+ 'c' => array(1, 2, 3),
+ ),
+ 'a=z&b=7&c=1&c=2&c=3',
+ ),
+ );
+ }
+
+ public function testPutFile() {
+ $client = new CurlClient();
+ $actual = $client->options('PUT', 'url', array(), array('a' => 1, 'b' => 2));
+ $this->assertNotNull($actual[CURLOPT_INFILE]);
+ $this->assertEquals('a=1&b=2', fread($actual[CURLOPT_INFILE], $actual[CURLOPT_INFILESIZE]));
+ $this->assertEquals(7, $actual[CURLOPT_INFILESIZE]);
+ }
+} \ No newline at end of file
diff --git a/Twilio/Tests/Unit/UnitTest.php b/Twilio/Tests/Unit/UnitTest.php
new file mode 100644
index 0000000..50ad366
--- /dev/null
+++ b/Twilio/Tests/Unit/UnitTest.php
@@ -0,0 +1,10 @@
+<?php
+
+
+namespace Twilio\Tests\Unit;
+
+use \PHPUnit_Framework_TestCase;
+
+abstract class UnitTest extends PHPUnit_Framework_TestCase {
+
+} \ No newline at end of file