From 13f31f1c79df04e2120495d268ce86b2910da4a5 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 4 Sep 2019 01:27:42 +0300 Subject: [PATCH 1/3] $httpOptions for \GuzzleHttp\Client --- README.md | 31 ++++++++++++++++++++++++++++++- src/Client.php | 18 ++++++++++++++++-- tests/ClientTest.php | 26 +++++++++++++++++++++++++- tests/MockClient.php | 7 ++++--- 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 509810f..15663e6 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,9 @@ $gql = $builder->getQuery(); # Constructing The Client A Client object can easily be instantiated by providing the GraphQL endpoint -URL. The Client constructor also receives an optional "authorizationHeaders" +URL. + +The Client constructor also receives an optional "authorizationHeaders" array, which can be used to add authorization headers to all requests being sent to the GraphQL server. @@ -236,6 +238,33 @@ $client = new Client( ); ``` + +The Client constructor also receives an optional "httpOptions" array, which can be used to add custom [Guzzle HTTP Client request options](https://guzzle.readthedocs.io/en/latest/request-options.html). + +Example: + +``` +$client = new Client( + 'http://api.graphql.com', + [], + [ + 'connect_timeout' => 5, + 'timeout' => 5, + 'headers' => [ + 'Authorization' => 'Basic xyz' + 'User-Agent' => 'testing/1.0', + ], + 'proxy' => [ + 'http' => 'tcp://localhost:8125', // Use this proxy with "http" + 'https' => 'tcp://localhost:9124', // Use this proxy with "https", + 'no' => ['.mit.edu', 'foo.com'] // Don't use a proxy with these + ], + 'cert' => ['/path/server.pem', 'password'] + ... + ] +); +``` + # Running Queries ## Result Formatting diff --git a/src/Client.php b/src/Client.php index ed519fe..9cd6269 100644 --- a/src/Client.php +++ b/src/Client.php @@ -29,17 +29,25 @@ class Client */ protected $httpClient; + /** + * @var array + */ + protected $httpOptions; + + /** * Client constructor. * * @param string $endpointUrl - * @param array $authorizationHeaders + * @param array $authorizationHeaders + * @param array $httpOptions */ - public function __construct(string $endpointUrl, array $authorizationHeaders = []) + public function __construct(string $endpointUrl, array $authorizationHeaders = [], array $httpOptions = []) { $this->endpointUrl = $endpointUrl; $this->authorizationHeaders = $authorizationHeaders; $this->httpClient = new \GuzzleHttp\Client(); + $this->httpOptions = $httpOptions; } /** @@ -77,6 +85,12 @@ public function runRawQuery(string $queryString, $resultsAsArray = false, array if (!empty($this->authorizationHeaders)) { $options['headers'] = $this->authorizationHeaders; } + + // Set request options for \GuzzleHttp\Client + if (!empty($this->httpOptions)) { + $options = $this->httpOptions; + } + $options['headers']['Content-Type'] = 'application/json'; // Convert empty variables array to empty json object diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 390b1de..ad68cd7 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -7,6 +7,7 @@ use GraphQL\QueryBuilder\QueryBuilder; use GraphQL\RawObject; use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ServerException; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; @@ -58,6 +59,7 @@ public function testConstructClient() $mockHandler->append(new Response(200)); $mockHandler->append(new Response(200)); $mockHandler->append(new Response(200)); + $mockHandler->append(new Response(200)); $client = new MockClient('', $handler); $client->runRawQuery('query_string'); @@ -68,13 +70,16 @@ public function testConstructClient() $client = new MockClient('', $handler); $client->runRawQuery('query_string', false, ['name' => 'val']); + $client = new MockClient('', $handler, [], ['headers' => [ 'Authorization' => 'Basic xyz', 'User-Agent' => 'test' ]]); + $client->runRawQuery('query_string'); + /** @var Request $firstRequest */ $firstRequest = $container[0]['request']; $this->assertEquals('{"query":"query_string","variables":{}}', $firstRequest->getBody()->getContents()); /** @var Request $thirdRequest */ $thirdRequest = $container[1]['request']; - $this->assertNotNull($thirdRequest->getHeader('Authorization')); + $this->assertNotEmpty($thirdRequest->getHeader('Authorization')); $this->assertEquals( ['Basic xyz'], $thirdRequest->getHeader('Authorization') @@ -83,6 +88,15 @@ public function testConstructClient() /** @var Request $secondRequest */ $secondRequest = $container[2]['request']; $this->assertEquals('{"query":"query_string","variables":{"name":"val"}}', $secondRequest->getBody()->getContents()); + + + /** @var Request $fourthRequest */ + $fourthRequest = $container[3]['request']; + $this->assertNotNull($fourthRequest->getHeader('Authorization')); + $this->assertNotEmpty($fourthRequest->getHeader('User-Agent')); + $this->assertEquals(['Basic xyz'], $fourthRequest->getHeader('Authorization')); + $this->assertEquals(['test'], $fourthRequest->getHeader('User-Agent')); + } /** @@ -232,4 +246,14 @@ public function testInternalServerErrorResponse() $this->expectException(ServerException::class); $this->client->runRawQuery(''); } + + /** + * @covers \GraphQL\Client::runRawQuery + */ + public function testConnectTimeoutResponse() + { + $this->mockHandler->append(new ConnectException('Time Out', new Request('post', ''))); + $this->expectException(ConnectException::class); + $this->client->runRawQuery(''); + } } \ No newline at end of file diff --git a/tests/MockClient.php b/tests/MockClient.php index 6d14e9f..c908ec5 100644 --- a/tests/MockClient.php +++ b/tests/MockClient.php @@ -16,11 +16,12 @@ class MockClient extends Client * * @param string $endpointUrl * @param object $handler - * @param array $authorizationHeaders + * @param array $authorizationHeaders + * @param array $httpOptions */ - public function __construct(string $endpointUrl, $handler, array $authorizationHeaders = []) + public function __construct(string $endpointUrl, $handler, array $authorizationHeaders = [], array $httpOptions = []) { - parent::__construct($endpointUrl, $authorizationHeaders); + parent::__construct($endpointUrl, $authorizationHeaders, $httpOptions); $this->httpClient = new \GuzzleHttp\Client(['handler' => $handler]); } } \ No newline at end of file From efdcdbf9141e9e7f9ffa2728064d8e932d3cd012 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 5 Sep 2019 09:16:56 +0300 Subject: [PATCH 2/3] fix test --- tests/ClientTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index ad68cd7..68d7e58 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -70,7 +70,7 @@ public function testConstructClient() $client = new MockClient('', $handler); $client->runRawQuery('query_string', false, ['name' => 'val']); - $client = new MockClient('', $handler, [], ['headers' => [ 'Authorization' => 'Basic xyz', 'User-Agent' => 'test' ]]); + $client = new MockClient('', $handler, ['Authorization' => 'Basic xyz'], ['headers' => [ 'Authorization' => 'Basic zyx', 'User-Agent' => 'test' ]]); $client->runRawQuery('query_string'); /** @var Request $firstRequest */ @@ -94,7 +94,7 @@ public function testConstructClient() $fourthRequest = $container[3]['request']; $this->assertNotNull($fourthRequest->getHeader('Authorization')); $this->assertNotEmpty($fourthRequest->getHeader('User-Agent')); - $this->assertEquals(['Basic xyz'], $fourthRequest->getHeader('Authorization')); + $this->assertEquals(['Basic zyx'], $fourthRequest->getHeader('Authorization')); $this->assertEquals(['test'], $fourthRequest->getHeader('User-Agent')); } From 9dfde7c3f64da901d2b4ce99343db81ce5e2054b Mon Sep 17 00:00:00 2001 From: user Date: Thu, 5 Sep 2019 09:35:13 +0300 Subject: [PATCH 3/3] fix test and README --- README.md | 2 +- tests/ClientTest.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 15663e6..ba55f15 100644 --- a/README.md +++ b/README.md @@ -239,7 +239,7 @@ $client = new Client( ``` -The Client constructor also receives an optional "httpOptions" array, which can be used to add custom [Guzzle HTTP Client request options](https://guzzle.readthedocs.io/en/latest/request-options.html). +The Client constructor also receives an optional "httpOptions" array, which **overrides** the "authorizationHeaders" and can be used to add custom [Guzzle HTTP Client request options](https://guzzle.readthedocs.io/en/latest/request-options.html). Example: diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 68d7e58..b8342dc 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -89,14 +89,12 @@ public function testConstructClient() $secondRequest = $container[2]['request']; $this->assertEquals('{"query":"query_string","variables":{"name":"val"}}', $secondRequest->getBody()->getContents()); - /** @var Request $fourthRequest */ $fourthRequest = $container[3]['request']; - $this->assertNotNull($fourthRequest->getHeader('Authorization')); + $this->assertNotEmpty($fourthRequest->getHeader('Authorization')); $this->assertNotEmpty($fourthRequest->getHeader('User-Agent')); $this->assertEquals(['Basic zyx'], $fourthRequest->getHeader('Authorization')); $this->assertEquals(['test'], $fourthRequest->getHeader('User-Agent')); - } /**