From 93a267b496cb7a723c0b8032ca24568c44dc0d87 Mon Sep 17 00:00:00 2001 From: Bailey Herbert Date: Fri, 15 Mar 2024 10:26:46 -0700 Subject: [PATCH] Allow setting custom guzzle options --- src/Envato/Auth/OAuth.php | 41 ++++++++++++++++++++++++++++---- src/Envato/Endpoint.php | 5 ---- src/Envato/RequestWriter.php | 45 +++++++++++++++++++++++++++++++----- src/EnvatoClient.php | 17 +++++++++++++- 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/src/Envato/Auth/OAuth.php b/src/Envato/Auth/OAuth.php index aacfc8b..a28ee02 100644 --- a/src/Envato/Auth/OAuth.php +++ b/src/Envato/Auth/OAuth.php @@ -52,6 +52,17 @@ class OAuth implements AuthProcedure */ private $clientSecret; + /** + * Additional options to pass when constructing the Guzzle client. Defaults to a blank array. + * + * Note that the Envato Client will automatically set the `user-agent` and `authorization` headers, in addition + * to the CA bundle `verify` and `base_uri` properties, on the client. However, you can override those defaults + * here. + * + * @see https://docs.guzzlephp.org/en/stable/quickstart.html#creating-a-client + */ + public $httpOptions = array(); + /** * Starts a new OAuth authentication with a personal token or a stored OAuth session. * @@ -59,10 +70,11 @@ class OAuth implements AuthProcedure * Optionally, a 'store' callback can be provided in this array to in place of the second argument. * @param callable|null $store Optional callable which will execute whenever the token automatically renews * due to becoming expired. Use this to store the updated session in your database. + * @param array $httpOptions Additional options to pass when constructing the Guzzle client. * * @throws MissingPropertyException When the options array does not contain all required properties. */ - public function __construct(array $options, $store = null) + public function __construct(array $options, $store = null, $httpOptions = array()) { // Check for 'store' in the options array if (isset($options['store'])) { @@ -86,6 +98,9 @@ public function __construct(array $options, $store = null) // Store callback $this->store = $store; + // Store HTTP client + $this->httpOptions = $httpOptions; + // Store parameters $this->clientId = $options['client_id']; $this->clientSecret = $options['client_secret']; @@ -227,14 +242,32 @@ public function getAuthorizationUri() * @throws InvalidTokenException */ private function generateToken($code) { - $client = new Client([ + $overrides = $this->httpOptions; + $options = array( 'headers' => [ - 'User-Agent' => 'https://github.com/baileyherbert/envato.php' + 'user-agent' => 'Envato.php (https://github.com/baileyherbert/envato.php)' ], 'verify' => dirname(dirname(dirname(__DIR__))) . '/data/ca-bundle.crt' - ]); + ); + + if (is_array($overrides)) { + foreach ($overrides as $key => $value) { + $key = strtolower($key); + + if ($key !== 'headers') { + $options[$key] = $value; + } + else if (is_array($value)) { + foreach ($value as $headerName => $headerValue) { + $headerName = strtolower($headerName); + $options['headers'][$headerName] = $headerValue; + } + } + } + } try { + $client = new Client($options); $response = $client->request('POST', 'https://api.envato.com/token', [ 'form_params' => [ 'grant_type' => 'authorization_code', diff --git a/src/Envato/Endpoint.php b/src/Envato/Endpoint.php index caa1c77..3ba71b5 100644 --- a/src/Envato/Endpoint.php +++ b/src/Envato/Endpoint.php @@ -2,11 +2,6 @@ namespace Herbert\Envato { - use GuzzleHttp\Client; - use Herbert\Envato\Exceptions\BadRequestException; - use Herbert\Envato\Exceptions\EndpointException; - use Herbert\Envato\Exceptions\TooManyRequestsException; - use Herbert\Envato\Exceptions\UnauthorizedException; use Herbert\EnvatoClient; class Endpoint diff --git a/src/Envato/RequestWriter.php b/src/Envato/RequestWriter.php index b7fd4ba..ab41d96 100644 --- a/src/Envato/RequestWriter.php +++ b/src/Envato/RequestWriter.php @@ -15,6 +15,11 @@ class RequestWriter { */ private $client; + /** + * @var Client|null + */ + private $httpClientCache; + /** * Constructs a new `RequestWriter` instance. * @@ -102,12 +107,17 @@ private function send($method, &$uri, array &$variables) { // 400 Bad Request elseif ($response->getStatusCode() == 400) { - throw new BadRequestException(); + throw new BadRequestException('The request was rejected because one or more parameters were invalid'); } // 401 Unauthorized elseif ($response->getStatusCode() == 401) { - throw new UnauthorizedException(); + throw new UnauthorizedException('The token was missing or not in the correct format'); + } + + // 403 Forbidden + elseif ($response->getStatusCode() == 403) { + throw new UnauthorizedException('The token was not found or did not have sufficient permissions'); } // 429 Too Many Requests @@ -131,14 +141,37 @@ private function send($method, &$uri, array &$variables) { * @throws Exceptions\InvalidTokenException */ private function createHttpClient() { - return new Client([ + if (isset($this->httpClientCache)) { + return $this->httpClientCache; + } + + $overrides = $this->client->httpOptions; + $options = array( 'headers' => [ - 'User-Agent' => $this->client->userAgent, - 'Authorization' => 'Bearer ' . $this->client->getToken() + 'user-agent' => $this->client->userAgent, + 'authorization' => 'Bearer ' . $this->client->getToken() ], 'verify' => dirname(dirname(__DIR__)) . '/data/ca-bundle.crt', 'base_uri' => $this->client->baseUri - ]); + ); + + if (is_array($overrides)) { + foreach ($overrides as $key => $value) { + $key = strtolower($key); + + if ($key !== 'headers') { + $options[$key] = $value; + } + else if (is_array($value)) { + foreach ($value as $headerName => $headerValue) { + $headerName = strtolower($headerName); + $options['headers'][$headerName] = $headerValue; + } + } + } + } + + return $this->httpClientCache = new Client($options); } } diff --git a/src/EnvatoClient.php b/src/EnvatoClient.php index ccf250a..a6f268e 100644 --- a/src/EnvatoClient.php +++ b/src/EnvatoClient.php @@ -54,21 +54,36 @@ class EnvatoClient */ public $request; + /** + * Additional options to pass when constructing the Guzzle client. Defaults to a blank array. + * + * Note that the Envato Client will automatically set the `user-agent` and `authorization` headers, in addition + * to the CA bundle `verify` and `base_uri` properties, on the client. However, you can override those defaults + * here. + * + * @see https://docs.guzzlephp.org/en/stable/quickstart.html#creating-a-client + */ + public $httpOptions = array(); + /** * Starts a new client connection with the specified authentication procedure. The procedure must be * completed prior to the constructor being called; that is, it must have already established the token * and expiration time. * * @param AuthProcedure $auth Procedure to authenticate with. + * @param array $httpOptions Additional options to pass when constructing the Guzzle client. * * @throws NotAuthenticatedException if the authentication procedure is not completed or has failed. */ - public function __construct(AuthProcedure $auth) { + public function __construct(AuthProcedure $auth, $httpOptions = array()) { // Ensure that we are already authenticated if ($auth->token == null) { throw new NotAuthenticatedException(); } + // Store the HTTP options + $this->httpOptions = $httpOptions; + // Store the procedure $this->procedure = $auth; $this->request = new RequestWriter($this);