diff --git a/apigee_edge.services.yml b/apigee_edge.services.yml index 0582af15..bcee9b90 100644 --- a/apigee_edge.services.yml +++ b/apigee_edge.services.yml @@ -15,7 +15,7 @@ services: apigee_edge.sdk_connector: class: Drupal\apigee_edge\SDKConnector - arguments: ['@http_client_factory', '@key.repository', '@entity_type.manager', '@config.factory', '@module_handler', '@info_parser'] + arguments: ['@http_client_factory', '@key.repository', '@config.factory', '@module_handler', '@info_parser'] apigee_edge.key_entity_form_enhancer: class: Drupal\apigee_edge\KeyEntityFormEnhancer diff --git a/modules/apigee_edge_debug/apigee_edge_debug.services.yml b/modules/apigee_edge_debug/apigee_edge_debug.services.yml index 51d6c631..01ff15e6 100644 --- a/modules/apigee_edge_debug/apigee_edge_debug.services.yml +++ b/modules/apigee_edge_debug/apigee_edge_debug.services.yml @@ -8,7 +8,7 @@ services: decorates: apigee_edge.sdk_connector decoration_priority: -10 public: false - arguments: ['@apigee_edge_debug.sdk_connector.inner', '@http_client_factory', '@key.repository', '@entity_type.manager', '@config.factory', '@module_handler', '@info_parser'] + arguments: ['@apigee_edge_debug.sdk_connector.inner'] properties: # Without this property for decorated services, serialization will fail. @see: https://www.drupal.org/project/drupal/issues/2536370 _serviceId: apigee_edge.sdk_connector diff --git a/modules/apigee_edge_debug/src/SDKConnector.php b/modules/apigee_edge_debug/src/SDKConnector.php index 3f736627..97043ccf 100644 --- a/modules/apigee_edge_debug/src/SDKConnector.php +++ b/modules/apigee_edge_debug/src/SDKConnector.php @@ -20,22 +20,19 @@ namespace Drupal\apigee_edge_debug; +use Apigee\Edge\ClientInterface; use Drupal\apigee_edge\SDKConnector as OriginalSDKConnector; use Drupal\apigee_edge\SDKConnectorInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\InfoParserInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Http\ClientFactory; -use Drupal\key\KeyRepositoryInterface; +use Drupal\key\KeyInterface; +use Http\Message\Authentication; /** * Service decorator for SDKConnector. */ -class SDKConnector extends OriginalSDKConnector implements SDKConnectorInterface { +final class SDKConnector implements SDKConnectorInterface { /** - * Customer http request header. + * Custom HTTP request header. * * This tells the ApiClientProfiler to profile requests made by the underlying * HTTP client. @@ -49,40 +46,60 @@ class SDKConnector extends OriginalSDKConnector implements SDKConnectorInterface /** * The inner SDK connector service. * - * @var \Drupal\apigee_edge\SDKConnector + * @var \Drupal\apigee_edge\SDKConnectorInterface */ private $innerService; + /** + * The API client initialized from the saved credentials and default config. + * + * @var null|\Apigee\Edge\ClientInterface + * + * @see getClient() + */ + private $defaultClient; + /** * Constructs a new SDKConnector. * * @param \Drupal\apigee_edge\SDKConnectorInterface $inner_service * The decorated SDK connector service. - * @param \Drupal\Core\Http\ClientFactory $client_factory - * Http client. - * @param \Drupal\key\KeyRepositoryInterface $key_repository - * The key repository. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * Entity type manager service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The factory for configuration objects. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * Module handler service. - * @param \Drupal\Core\Extension\InfoParserInterface $info_parser - * Info file parser service. */ - public function __construct(SDKConnectorInterface $inner_service, ClientFactory $client_factory, KeyRepositoryInterface $key_repository, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, InfoParserInterface $info_parser) { + public function __construct(SDKConnectorInterface $inner_service) { $this->innerService = $inner_service; - parent::__construct($client_factory, $key_repository, $entity_type_manager, $config_factory, $module_handler, $info_parser); } /** * {@inheritdoc} */ - protected function httpClientConfiguration(): array { - $config = $this->innerService->httpClientConfiguration(); - $config['headers'][static::HEADER] = static::HEADER; - return $config; + public function getOrganization(): string { + return $this->innerService->getOrganization(); + } + + /** + * {@inheritdoc} + */ + public function getClient(?Authentication $authentication = NULL, ?string $endpoint = NULL, array $options = []): ClientInterface { + $extra_options[OriginalSDKConnector::CLIENT_FACTORY_OPTIONS]['headers'][static::HEADER] = static::HEADER; + + // If method got called without default parameters, initialize and/or + // return the default API client from the internal cache. + if (!isset($authentication, $endpoint) && empty($options)) { + if ($this->defaultClient === NULL) { + $this->defaultClient = $this->innerService->getClient($authentication, $endpoint, $extra_options); + } + + return $this->defaultClient; + } + + return $this->innerService->getClient($authentication, $endpoint, array_merge($options, $extra_options)); + } + + /** + * {@inheritdoc} + */ + public function testConnection(KeyInterface $key = NULL): void { + $this->innerService->testConnection($key); } } diff --git a/src/OauthAuthentication.php b/src/OauthAuthentication.php index 17edb239..2ebdeb56 100644 --- a/src/OauthAuthentication.php +++ b/src/OauthAuthentication.php @@ -35,7 +35,7 @@ class OauthAuthentication extends Oauth { protected function authClient(): ClientInterface { /** @var \Drupal\apigee_edge\SDKConnectorInterface $sdk_connector */ $sdk_connector = \Drupal::service('apigee_edge.sdk_connector'); - return $sdk_connector->buildClient(new BasicAuth($this->clientId, $this->clientSecret), $this->auth_server); + return $sdk_connector->getClient(new BasicAuth($this->clientId, $this->clientSecret), $this->auth_server); } } diff --git a/src/SDKConnector.php b/src/SDKConnector.php index 0a2b8bbe..d9a601c8 100644 --- a/src/SDKConnector.php +++ b/src/SDKConnector.php @@ -26,8 +26,8 @@ use Drupal\apigee_edge\Exception\AuthenticationKeyException; use Drupal\apigee_edge\Exception\AuthenticationKeyNotFoundException; use Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\InfoParserInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Http\ClientFactory; @@ -39,63 +39,67 @@ /** * Provides an Apigee Edge SDK connector. */ -class SDKConnector implements SDKConnectorInterface { +final class SDKConnector implements SDKConnectorInterface { /** - * The client object. + * HTTP client configuration options for ClientFactory. * - * @var null|\Http\Client\HttpClient + * @param string */ - private static $client = NULL; + public const CLIENT_FACTORY_OPTIONS = 'client_factory_options'; + + /** + * The API client initialized from the saved credentials and default config. + * + * @var null|\Apigee\Edge\ClientInterface + * + * @see getClient() + */ + private $defaultClient; /** * The currently used credentials object. * * @var null|\Drupal\apigee_edge\CredentialsInterface */ - private static $credentials = NULL; + private $credentials; /** * Custom user agent prefix. * * @var null|string + * + * @see userAgentPrefix() */ - private static $userAgentPrefix = NULL; + private $userAgentPrefix; /** * The config factory. * * @var \Drupal\Core\Config\ConfigFactoryInterface */ - protected $configFactory; + private $configFactory; /** * The key repository. * * @var \Drupal\key\KeyRepositoryInterface */ - protected $keyRepository; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; + private $keyRepository; /** * The module handler service. * * @var \Drupal\Core\Extension\ModuleHandlerInterface */ - protected $moduleHandler; + private $moduleHandler; /** * The info parser. * * @var \Drupal\Core\Extension\InfoParserInterface */ - protected $infoParser; + private $infoParser; /** * The HTTP client factory. @@ -111,8 +115,6 @@ class SDKConnector implements SDKConnectorInterface { * Http client. * @param \Drupal\key\KeyRepositoryInterface $key_repository * The key repository. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * Entity type manager service. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The factory for configuration objects. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler @@ -120,66 +122,71 @@ class SDKConnector implements SDKConnectorInterface { * @param \Drupal\Core\Extension\InfoParserInterface $info_parser * Info file parser service. */ - public function __construct(ClientFactory $client_factory, KeyRepositoryInterface $key_repository, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, InfoParserInterface $info_parser) { + public function __construct(ClientFactory $client_factory, KeyRepositoryInterface $key_repository, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, InfoParserInterface $info_parser) { $this->clientFactory = $client_factory; - $this->entityTypeManager = $entity_type_manager; $this->keyRepository = $key_repository; $this->configFactory = $config_factory; $this->moduleHandler = $module_handler; $this->infoParser = $info_parser; } - /** - * Get HTTP client overrides for Apigee Edge API client. - * - * Allows to override some configuration of the http client built by the - * factory for the API client. - * - * @return array - * Associative array of configuration settings. - * - * @see http://docs.guzzlephp.org/en/stable/request-options.html - */ - protected function httpClientConfiguration(): array { - return [ - 'connect_timeout' => $this->configFactory->get('apigee_edge.client')->get('http_client_connect_timeout') ?? 30, - 'timeout' => $this->configFactory->get('apigee_edge.client')->get('http_client_timeout') ?? 30, - 'proxy' => $this->configFactory->get('apigee_edge.client')->get('http_client_proxy') ?? '', - ]; - } - /** * {@inheritdoc} */ public function getOrganization(): string { - $credentials = $this->getCredentials(); + try { + $credentials = $this->getCredentials(); + } + catch (AuthenticationKeyException $e) { + return ''; + } return $credentials->getKeyType()->getOrganization($credentials->getKey()); } /** * {@inheritdoc} */ - public function getClient(?Authentication $authentication = NULL, ?string $endpoint = NULL): ClientInterface { - if ($authentication === NULL) { - if (self::$client === NULL) { + public function getClient(?Authentication $authentication = NULL, ?string $endpoint = NULL, array $options = []): ClientInterface { + // If method got called without default parameters, initialize and/or + // return the default API client from the internal cache. + if (!isset($authentication, $endpoint) && empty($options)) { + if ($this->defaultClient === NULL) { $credentials = $this->getCredentials(); - /** @var \Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface $key_type */ - self::$client = $this->buildClient($credentials->getAuthentication(), $credentials->getKeyType()->getEndpoint($credentials->getKey())); + $this->defaultClient = $this->buildClient($credentials->getAuthentication(), $credentials->getKeyType()->getEndpoint($credentials->getKey())); } - return self::$client; + return $this->defaultClient; } - else { - return $this->buildClient($authentication, $endpoint); + + // Fallback to the saved credentials. + if ($authentication === NULL) { + $credentials = $this->getCredentials(); + $authentication = $credentials->getAuthentication(); } + + return $this->buildClient($authentication, $endpoint, $options); } /** * {@inheritdoc} */ - public function buildClient(Authentication $authentication, ?string $endpoint = NULL, array $options = []): ClientInterface { + private function buildClient(Authentication $authentication, ?string $endpoint = NULL, array $options = []): ClientInterface { + $default_client_options = [ + 'connect_timeout' => $this->configFactory->get('apigee_edge.client')->get('http_client_connect_timeout') ?? 30, + 'timeout' => $this->configFactory->get('apigee_edge.client')->get('http_client_timeout') ?? 30, + 'proxy' => $this->configFactory->get('apigee_edge.client')->get('http_client_proxy') ?? '', + ]; + if (isset($options[static::CLIENT_FACTORY_OPTIONS])) { + $http_client_options = NestedArray::mergeDeep($default_client_options, $options[static::CLIENT_FACTORY_OPTIONS]); + unset($options[static::CLIENT_FACTORY_OPTIONS]); + } + else { + $http_client_options = $default_client_options; + } + + // Builder and user-agent prefix can not be overridden. $options += [ - Client::CONFIG_HTTP_CLIENT_BUILDER => new Builder(new GuzzleClientAdapter($this->clientFactory->fromOptions($this->httpClientConfiguration()))), + Client::CONFIG_HTTP_CLIENT_BUILDER => new Builder(new GuzzleClientAdapter($this->clientFactory->fromOptions($http_client_options))), Client::CONFIG_USER_AGENT_PREFIX => $this->userAgentPrefix(), ]; return new Client($authentication, $endpoint, $options); @@ -192,30 +199,19 @@ public function buildClient(Authentication $authentication, ?string $endpoint = * The key entity. */ private function getCredentials(): CredentialsInterface { - if (self::$credentials === NULL) { + if ($this->credentials === NULL) { $active_key = $this->configFactory->get('apigee_edge.auth')->get('active_key'); if (empty($active_key)) { throw new AuthenticationKeyException('Apigee Edge API authentication key is not set.'); } - if (!($key = $this->keyRepository->getKey($active_key))) { + $key = $this->keyRepository->getKey($active_key); + if (!$key) { throw new AuthenticationKeyNotFoundException($active_key, 'Apigee Edge API authentication key not found with "@id" id.'); } - self::$credentials = $this->buildCredentials($key); + $this->credentials = $this->buildCredentials($key); } - return self::$credentials; - } - - /** - * Changes credentials used by the API client. - * - * @param \Drupal\apigee_edge\CredentialsInterface $credentials - * The new credentials object. - */ - private function setCredentials(CredentialsInterface $credentials) { - self::$credentials = $credentials; - // Ensure that client will be rebuilt with the new key. - self::$client = NULL; + return $this->credentials; } /** @@ -228,47 +224,45 @@ private function setCredentials(CredentialsInterface $credentials) { * The credentials. */ private function buildCredentials(KeyInterface $key): CredentialsInterface { - /** @var \Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface $key */ if ($key->getKeyType() instanceof EdgeKeyTypeInterface) { if ($key->getKeyType()->getAuthenticationType($key) === EdgeKeyTypeInterface::EDGE_AUTH_TYPE_OAUTH) { return new OauthCredentials($key); } return new Credentials($key); } - else { - throw new AuthenticationKeyException("Type of {$key->id()} key does not implement EdgeKeyTypeInterface."); - } + + throw new AuthenticationKeyException("Type of {$key->id()} key does not implement EdgeKeyTypeInterface."); } /** * Generates a custom user agent prefix. */ - protected function userAgentPrefix(): string { - if (NULL === self::$userAgentPrefix) { + private function userAgentPrefix(): string { + if ($this->userAgentPrefix === NULL) { $module_info = $this->infoParser->parse($this->moduleHandler->getModule('apigee_edge')->getPathname()); if (!isset($module_info['version'])) { $module_info['version'] = '8.x-1.x-dev'; } // TODO Change "DevPortal" to "Drupal module" later. It has been added for // Apigee's convenience this way. - self::$userAgentPrefix = $module_info['name'] . ' DevPortal ' . $module_info['version']; + $this->userAgentPrefix = $module_info['name'] . ' DevPortal ' . $module_info['version']; } - return self::$userAgentPrefix; + return $this->userAgentPrefix; } /** * {@inheritdoc} */ - public function testConnection(KeyInterface $key = NULL) { - if ($key !== NULL) { - $credentials = $this->buildCredentials($key); - $client = $this->buildClient($credentials->getAuthentication(), $credentials->getKeyType()->getEndpoint($credentials->getKey())); - } - else { + public function testConnection(KeyInterface $key = NULL): void { + if ($key === NULL) { $client = $this->getClient(); $credentials = $this->getCredentials(); } + else { + $credentials = $this->buildCredentials($key); + $client = $this->buildClient($credentials->getAuthentication(), $credentials->getKeyType()->getEndpoint($credentials->getKey())); + } try { // We use the original, non-decorated organization controller here. @@ -276,12 +270,7 @@ public function testConnection(KeyInterface $key = NULL) { $oc->load($credentials->getKeyType()->getOrganization($credentials->getKey())); } catch (\Exception $e) { - throw $e; - } - finally { - if (isset($original_credentials)) { - self::$credentials = $this->setCredentials($original_credentials); - } + throw new AuthenticationKeyException($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/SDKConnectorInterface.php b/src/SDKConnectorInterface.php index 61e2fadf..d8d84df2 100644 --- a/src/SDKConnectorInterface.php +++ b/src/SDKConnectorInterface.php @@ -29,45 +29,43 @@ interface SDKConnectorInterface { /** - * Gets the organization. + * Gets the organization used by the API client. * * @return string - * The organization. + * The organization or an empty string if the Apigee Edge authentication + * key has not been saved yet. */ public function getOrganization(): string; /** - * Returns the http client. + * Returns a pre-configured API client. + * + * @param null|\Http\Message\Authentication $authentication + * The authentication method, default is retrieved from the active key. + * @param null|string $endpoint + * API endpoint, default is https://api.enterprise.apigee.com/v1. + * @param array $options + * The API Client configuration options. * * @return \Apigee\Edge\ClientInterface - * The http client. + * The API client. + * + * @throws \Drupal\apigee_edge\Exception\AuthenticationKeyException + * If the API client could not be built, ex.: missing Apigee Edge + * authentication key. */ - public function getClient(): ClientInterface; + public function getClient(?Authentication $authentication = NULL, ?string $endpoint = NULL, array $options = []): ClientInterface; /** * Test connection with the Edge Management Server. * * @param \Drupal\key\KeyInterface|null $key - * Key entity to check connection with Edge, - * if NULL, then use the stored key. - * - * @throws \Exception - */ - public function testConnection(KeyInterface $key = NULL); - - /** - * Returns a pre-configured API client with the provided credentials. + * Key entity with Apigee Edge credentials or NULL if the saved key should + * be used. * - * @param \Http\Message\Authentication $authentication - * Authentication. - * @param null|string $endpoint - * API endpoint, default is https://api.enterprise.apigee.com/v1. - * @param array $options - * Client configuration option. - * - * @return \Apigee\Edge\ClientInterface - * Configured API client. + * @throws \Drupal\apigee_edge\Exception\AuthenticationKeyException + * If the authentication fails with the saved- or provided key. */ - public function buildClient(Authentication $authentication, ?string $endpoint = NULL, array $options = []): ClientInterface; + public function testConnection(KeyInterface $key = NULL): void; } diff --git a/tests/modules/apigee_edge_test/apigee_edge_test.services.yml b/tests/modules/apigee_edge_test/apigee_edge_test.services.yml index 92cab64d..a40fbd34 100644 --- a/tests/modules/apigee_edge_test/apigee_edge_test.services.yml +++ b/tests/modules/apigee_edge_test/apigee_edge_test.services.yml @@ -22,7 +22,7 @@ services: decorates: apigee_edge_debug.sdk_connector decoration_priority: 0 public: false - arguments: ['@apigee_edge_test.sdk_connector.inner', '@logger.channel.apigee_edge_test', '@http_client_factory', '@key.repository', '@entity_type.manager', '@config.factory', '@module_handler', '@info_parser'] + arguments: ['@apigee_edge_test.sdk_connector.inner', '@logger.channel.apigee_edge_test'] properties: # Without this property for decorated services, serialization will fail. @see: https://www.drupal.org/project/drupal/issues/2536370 _serviceId: apigee_edge.sdk_connector diff --git a/tests/modules/apigee_edge_test/src/SDKConnector.php b/tests/modules/apigee_edge_test/src/SDKConnector.php index df6be696..8a400d4b 100644 --- a/tests/modules/apigee_edge_test/src/SDKConnector.php +++ b/tests/modules/apigee_edge_test/src/SDKConnector.php @@ -23,68 +23,88 @@ use Apigee\Edge\Client; use Apigee\Edge\ClientInterface; use Apigee\Edge\Exception\ApiResponseException; -use Drupal\apigee_edge\SDKConnector as DecoratedSDKConnector; use Drupal\apigee_edge\SDKConnectorInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\InfoParserInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Http\ClientFactory; -use Drupal\Core\Logger\LoggerChannelInterface; -use Drupal\key\KeyRepositoryInterface; +use Drupal\key\KeyInterface; use Http\Client\Exception; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; +use Psr\Log\LoggerInterface; /** * Service decorator for SDKConnector. */ -final class SDKConnector extends DecoratedSDKConnector implements SDKConnectorInterface { +final class SDKConnector implements SDKConnectorInterface { /** * The decorated SDK connector service. * - * @var \Drupal\apigee_edge\SDKConnector + * @var \Drupal\apigee_edge\SDKConnectorInterface */ private $innerService; /** * A logger instance. * - * @var \Drupal\Core\Logger\LoggerChannelInterface + * @var \Psr\Log\LoggerInterface */ private $logger; + /** + * The API client initialized from the saved credentials and default config. + * + * @var null|\Apigee\Edge\ClientInterface + * + * @see getClient() + */ + private $defaultClient; + /** * Constructs a new SDKConnector. * * @param \Drupal\apigee_edge\SDKConnectorInterface $inner_service * The decorated SDK connector service. - * @param \Drupal\Core\Logger\LoggerChannelInterface $logger - * Logger interface. - * @param \Drupal\Core\Http\ClientFactory $clientFactory - * Http client. - * @param \Drupal\key\KeyRepositoryInterface $key_repository - * The key repository. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * Entity type manager service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The factory for configuration objects. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler - * Module handler service. - * @param \Drupal\Core\Extension\InfoParserInterface $infoParser - * Info file parser service. + * @param \Psr\Log\LoggerInterface $logger + * The logger. */ - public function __construct(SDKConnectorInterface $inner_service, LoggerChannelInterface $logger, ClientFactory $clientFactory, KeyRepositoryInterface $key_repository, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $moduleHandler, InfoParserInterface $infoParser) { + public function __construct(SDKConnectorInterface $inner_service, LoggerInterface $logger) { $this->innerService = $inner_service; $this->logger = $logger; - parent::__construct($clientFactory, $key_repository, $entity_type_manager, $config_factory, $moduleHandler, $infoParser); } /** * {@inheritdoc} */ - public function buildClient(Authentication $authentication, ?string $endpoint = NULL, array $options = []): ClientInterface { + public function getOrganization(): string { + return $this->innerService->getOrganization(); + } + + /** + * {@inheritdoc} + */ + public function getClient(?Authentication $authentication = NULL, ?string $endpoint = NULL, array $options = []): ClientInterface { + // If method got called without default parameters, initialize and/or + // return the default API client from the internal cache. + if (!isset($authentication, $endpoint) && empty($options)) { + if ($this->defaultClient === NULL) { + $this->defaultClient = $this->innerService->getClient($authentication, $endpoint, $this->getOptionsWithRetryPlugin($options)); + } + + return $this->defaultClient; + } + + return $this->innerService->getClient($authentication, $endpoint, $this->getOptionsWithRetryPlugin($options)); + } + + /** + * Returns the options array with the retry decider plugin. + * + * @param array $options + * Array if API client options. + * + * @return array + * Array of API client options. + */ + private function getOptionsWithRetryPlugin(array $options): array { $decider = function (RequestInterface $request, Exception $e) { // Only retry API calls that failed with this specific error. if ($e instanceof ApiResponseException && $e->getEdgeErrorCode() === 'messaging.adaptors.http.flow.ApplicationNotFound') { @@ -99,11 +119,11 @@ public function buildClient(Authentication $authentication, ?string $endpoint = return FALSE; }; // Use the retry plugin in tests. - return $this->innerService->buildClient($authentication, $endpoint, [ + return array_merge($options, [ Client::CONFIG_RETRY_PLUGIN_CONFIG => [ 'retries' => 5, 'exception_decider' => $decider, - 'exception_delay' => function (RequestInterface $request, Exception $e, $retries) : int { + 'exception_delay' => static function (RequestInterface $request, Exception $e, $retries) : int { return $retries * 15000000; }, ], @@ -113,8 +133,8 @@ public function buildClient(Authentication $authentication, ?string $endpoint = /** * {@inheritdoc} */ - protected function httpClientConfiguration(): array { - return $this->innerService->httpClientConfiguration(); + public function testConnection(KeyInterface $key = NULL): void { + $this->innerService->testConnection($key); } }