* * For more information visit https://developer.akamai.com * * Copyright 2014 Akamai Technologies, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Akamai\Open\EdgeGrid\Tests; use Akamai\Open\EdgeGrid\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Middleware; use GuzzleHttp\Psr7\Response; /** * Test for Akamai\Open\EdgeGrid\Client * * @author Davey Shafik * @since PHP 5.6 * @version 1.0 */ class ClientTest extends \PHPUnit_Framework_TestCase { public function setUp() { Client::setVerbose(false); Client::setDebug(false); } /** * @param $name * @param $options * @param $request * @param $result * @dataProvider makeAuthHeaderProvider */ public function testMakeAuthHeader($name, $options, $request, $result) { //$this->setName($name); // Mock the response, we don't care about it $container = []; $handler = $this->getMockHandler([new Response(200)], $container); $timestamp = $this->prophesize(\Akamai\Open\EdgeGrid\Authentication\Timestamp::CLASS); $timestamp->__toString()->willReturn($options['timestamp']); $timestamp->isValid()->willReturn(true); $nonce = $this->prophesize(\Akamai\Open\EdgeGrid\Authentication\Nonce::CLASS); $nonce->__toString()->willReturn($options['nonce']); $client = new Client( array_merge($options, [ 'base_uri' => $options['base_url'], 'handler' => $handler, 'timestamp' => $timestamp->reveal(), 'nonce' => $nonce->reveal() ]) ); $client->setAuth($options['client_token'], $options['client_secret'], $options['access_token']); $client->setMaxBodySize($options['max_body']); if (isset($options['headers_to_sign'])) { $client->setHeadersToSign($options['headers_to_sign']); } $headers = array(); if (isset($request['headers'])) { array_walk_recursive($request['headers'], function ($value, $key) use (&$headers) { $headers[$key] = $value; }); } $client->request( $request['method'], $request['path'], [ 'headers' => $headers, 'body' => $request['data'], ] ); $this->assertEquals(1, sizeof($container)); $request = $container[0]['request']; $headers = $request->getHeaders(); $this->assertArrayHasKey('Authorization', $headers); $this->assertEquals(1, sizeof($headers['Authorization'])); $this->assertEquals($result, $headers['Authorization'][0]); } /** * @param $name * @param $options * @param $request * @param $result * @dataProvider makeAuthHeaderProvider */ public function testMakeAuthHeaderPsr7($name, $options, $request, $result) { //$this->setName($name); // Mock the response, we don't care about it $container = []; $handler = $this->getMockHandler([new Response(200)], $container); $timestamp = $this->prophesize(\Akamai\Open\EdgeGrid\Authentication\Timestamp::CLASS); $timestamp->__toString()->willReturn($options['timestamp']); $timestamp->isValid()->willReturn(true); $nonce = $this->prophesize(\Akamai\Open\EdgeGrid\Authentication\Nonce::CLASS); $nonce->__toString()->willReturn($options['nonce']); $client = new Client( array_merge($options, [ 'base_uri' => $options['base_url'], 'handler' => $handler, 'timestamp' => $timestamp->reveal(), 'nonce' => $nonce->reveal() ]) ); $client->setAuth($options['client_token'], $options['client_secret'], $options['access_token']); $client->setMaxBodySize($options['max_body']); if (isset($options['headers_to_sign'])) { $client->setHeadersToSign($options['headers_to_sign']); } $headers = array(); if (isset($request['headers'])) { array_walk_recursive($request['headers'], function ($value, $key) use (&$headers) { $headers[$key] = $value; }); } $request = new \GuzzleHttp\Psr7\Request( $request['method'], $request['path'], $headers, $request['data'] ); $client->send($request); $this->assertEquals(1, sizeof($container)); $request = $container[0]['request']; $headers = $request->getHeaders(); $this->assertArrayHasKey('Authorization', $headers); $this->assertEquals(1, sizeof($headers['Authorization'])); $this->assertEquals($result, $headers['Authorization'][0]); } /** * @dataProvider createFromEdgeRcProvider */ public function testCreateFromEdgeRcDefault($section, $file) { $_SERVER['HOME'] = __DIR__ . '/edgerc'; $client = \Akamai\Open\EdgeGrid\Client::createFromEdgeRcFile($section, $file); $authentication = \PHPUnit_Framework_Assert::readAttribute($client, 'authentication'); $this->assertInstanceOf(\Akamai\Open\EdgeGrid\Client::CLASS, $client); $this->assertEquals( [ 'client_token' => "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 'client_secret' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 'access_token' => "akab-access-token-xxx-xxxxxxxxxxxxxxxx" ], \PHPUnit_Framework_Assert::readAttribute($authentication, 'auth') ); $this->assertEquals( 'https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net', $client->getConfig('base_uri') ); $this->assertEquals(2048, \PHPUnit_Framework_Assert::readAttribute($authentication, 'max_body_size')); } public function testHostnameWithTrailingSlash() { $client = new \Akamai\Open\EdgeGrid\Client(); $client->setHost('akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/'); $this->assertEquals( 'akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net', $client->getConfig('headers')['Host'] ); } public function testDefaultTimeout() { // Mock the response, we don't care about it $container = []; $handler = $this->getMockHandler([new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $this->assertArrayHasKey('timeout', $client->getConfig()); $this->assertEquals(Client::DEFAULT_REQUEST_TIMEOUT, $client->getConfig('timeout')); $client->setAuth('test', 'test', 'test'); $client->get('/test'); $this->assertEquals(Client::DEFAULT_REQUEST_TIMEOUT, $container[0]['options']['timeout']); } public function testTimeoutOption() { // Mock the response, we don't care about it $container = []; $handler = $this->getMockHandler([new Response(200), new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, 'timeout' => 2 ] ); $this->assertArrayHasKey('timeout', $client->getConfig()); $this->assertEquals(2, $client->getConfig('timeout')); $client->setAuth('test', 'test', 'test'); $client->get('/test'); $this->assertEquals(2, end($container)['options']['timeout']); $client->get('/test', ['timeout' => 5]); $this->assertEquals(5, end($container)['options']['timeout']); } public function testSetTimeout() { // Mock the response, we don't care about it $container = []; $handler = $this->getMockHandler([new Response(200), new Response(200), new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $this->assertArrayHasKey('timeout', $client->getConfig()); $this->assertEquals(Client::DEFAULT_REQUEST_TIMEOUT, $client->getConfig('timeout')); $client->get('/test', ['timeout' => 2]); $this->assertEquals(2, end($container)['options']['timeout']); $this->assertEquals(Client::DEFAULT_REQUEST_TIMEOUT, $client->getConfig('timeout')); $client->setTimeout(5); $client->get('/test'); $this->assertEquals(5, $client->getConfig('timeout')); $this->assertEquals(5, end($container)['options']['timeout']); } public function testStaticDebugSingle() { $container = []; $handler = $this->getMockHandler([new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); Client::setDebug(true); $client->get('/test'); $this->assertEquals(true, is_resource(end($container)['options']['debug'])); } public function testInstanceDebugSingle() { $container = []; $handler = $this->getMockHandler([new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $client->setAuth('test', 'test', 'test'); $client->setInstanceDebug(true); $client->get('/test'); $this->assertEquals(true, is_resource(end($container)['options']['debug'])); } public function testDebugOverrideSingle() { $container = []; $handler = $this->getMockHandler([new Response(200), new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $client->setAuth('test', 'test', 'test'); Client::setDebug(true); $client->setInstanceDebug(false); $client->get('/test'); $this->assertEquals(false, is_resource(end($container)['options']['debug'])); } public function testInstanceDebugOptionSingle() { $container = []; $handler = $this->getMockHandler([new Response(200), new Response(200), new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $client->setAuth('test', 'test', 'test'); $client->get('/test', ['debug' => true]); $this->assertEquals(true, is_resource(end($container)['options']['debug'])); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $client->setAuth('test', 'test', 'test'); $client->setDebug(true); $client->get('/test', ['debug' => false]); $this->assertEquals(false, is_resource(end($container)['options']['debug'])); $this->assertFalse(end($container)['options']['debug']); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $client->setAuth('test', 'test', 'test'); Client::setDebug(true); $client->get('/test', ['debug' => false]); $this->assertEquals(false, is_resource(end($container)['options']['debug'])); $this->assertFalse(end($container)['options']['debug']); } public function testNonApiCall() { $container = []; $handler = $this->getMockHandler([new Response(200), new Response(200), new Response(200)], $container); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $response = $client->get('/test'); $this->assertInstanceOf(\GuzzleHttp\Psr7\Response::CLASS, $response); $this->assertEquals('http', end($container)['request']->getUri()->getScheme()); $this->assertEquals('example.org', end($container)['request']->getUri()->getHost()); $this->assertArrayNotHasKey('Authentication', end($container)['request']->getHeaders()); $response = $client->get('http://example.com/test'); $this->assertInstanceOf(\GuzzleHttp\Psr7\Response::CLASS, $response); $this->assertEquals('http', end($container)['request']->getUri()->getScheme()); $this->assertEquals('example.com', end($container)['request']->getUri()->getHost()); $this->assertArrayNotHasKey('Authentication', end($container)['request']->getHeaders()); $response = $client->get('https://example.net/test'); $this->assertInstanceOf(\GuzzleHttp\Psr7\Response::CLASS, $response); $this->assertEquals('https', end($container)['request']->getUri()->getScheme()); $this->assertEquals('example.net', end($container)['request']->getUri()->getHost()); $this->assertArrayNotHasKey('Authentication', end($container)['request']->getHeaders()); } public function testForceHttps() { $client = new Client( [ 'base_uri' => 'example.org' ] ); $uri = $client->getConfig('base_uri'); $this->assertEquals('https', parse_url($uri, PHP_URL_SCHEME)); } /** * @param $response * @param $path * @param $expected * @dataProvider loggingProvider */ public function testLogging($method, $responses, $path, $expected) { $handler = $this->getMockHandler($responses); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $logHandler = $this->setLogger($client); try { $client->{$method}($path); } catch (\Exception $e) { } $records = []; foreach ($logHandler->getRecords() as $record) { $records[] = $record['message']; } $this->assertEquals($expected, $records); } public function testLoggingRedirect() { $handler = $this->getMockHandler([ new Response(301, ['Location' => '/redirected']), new Response(200, ['Content-Type' => 'application/json']) ]); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $logHandler = $this->setLogger($client); try { $client->get("/redirect"); } catch (\Exception $e) { } $records = []; foreach ($logHandler->getRecords() as $record) { $records[] = $record['message']; } $this->assertEquals(["GET /redirect 301 ", "GET /redirected 200 application/json"], $records); } public function testLoggingDefault() { $client = new Client(); $client->setLogger(); $logger = \PHPUnit_Framework_Assert::readAttribute($client, 'logger'); $this->assertInstanceOf( \Closure::CLASS, $logger ); $reflection = new \ReflectionFunction($logger); $args = $reflection->getParameters(); $this->assertTrue(array_shift($args)->isCallable()); } public function testLoggingRequestHandler() { $handler = $this->getMockHandler([ new Response(200, ['Content-Type' => 'application/json']) ]); $client = new Client( [ 'base_uri' => 'http://example.org', ] ); $logHandler = $this->setLogger($client); $client->get("/test", ['handler' => $handler]); $records = []; foreach ($logHandler->getRecords() as $record) { $records[] = $record['message']; } $this->assertEquals(["GET /test 200 application/json"], $records); } public function testSetSimpleLog() { $handler = $this->getMockHandler([ new Response(200, ['Content-Type' => 'application/json']) ]); $client = new Client( [ 'base_uri' => 'http://example.org', 'handler' => $handler, ] ); $fp = fopen("php://memory", "w+"); $client->setSimpleLog($fp, "{method} {target} {code}"); $client->get("/test"); fseek($fp, 0); $this->assertEquals("GET /test 200", fgets($fp)); } public function makeAuthHeaderProvider() { $testdata = json_decode(file_get_contents(__DIR__ . '/testdata.json'), true); $tests = $testdata['tests']; unset($testdata['tests']); foreach ($tests as $test) { yield [ 'name' => $test['testName'], 'options' => array_merge($testdata, $test['request']), 'request' => array_merge(['data' => ""], $test['request']), 'result' => $test['expectedAuthorization'], ]; } } public function createFromEdgeRcProvider() { return [ [ 'section' => null, 'file' => null, ], [ 'section' => 'default', 'file' => null, ], [ 'section' => 'testing', 'file' => __DIR__ . '/edgerc/.edgerc.testing', ], [ 'section' => 'testing', 'file' => __DIR__ . '/edgerc/.edgerc.default-testing', ] ]; } public function loggingProvider() { return [ [ 'get', [new Response(200)], '/test', [ "GET /test 200 " ] ], [ 'get', [new Response(404)], '/error', [ "GET /error 404 " ] ], [ 'post', [new Response(500)], '/error', [ "POST /error 500 " ] ], [ 'put', [new Response(200, ['Content-Type' => 'application/json'])], '/test', [ "PUT /test 200 application/json" ] ], [ 'options', [new Response(405, ['Content-Type' => 'application/json'])], '/error', [ "OPTIONS /error 405 application/json" ] ], [ 'get', [new Response(503, ['Content-Type' => 'text/csv'])], '/error', [ "GET /error 503 text/csv" ] ], [ 'get', [ new Response(301, ['Location' => '/redirect']), new Response(200) ], '/notthere', [ "GET /notthere 301 ", "GET /redirect 200 ", ] ] ]; } public function getMockHandler($requests, array &$container = null) { $mock = new MockHandler($requests); $container = []; $history = Middleware::history($container); $handler = HandlerStack::create($mock); $handler->push($history, 'history'); return $handler; } /** * @return Client */ protected function setLogger(Client $client) { $handler = new \Monolog\Handler\TestHandler(); $logger = new \Monolog\Logger("Test Logger", [$handler]); $client->setLogger($logger, "{method} {target} {code} {res_header_content-type}"); return $handler; } }