diff --git a/.gitignore b/.gitignore index 7e50fb64..e107f66b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea .tmp .phpunit.result.cache +.env /composer.lock phpunit.xml vendor diff --git a/src/Lib/Configuration.php b/src/Lib/Configuration.php index da53245c..7f60ec07 100644 --- a/src/Lib/Configuration.php +++ b/src/Lib/Configuration.php @@ -3,6 +3,7 @@ namespace Typesense\Lib; use Http\Client\Common\HttpMethodsClient; +use Http\Client\HttpClient; use Http\Discovery\Psr17FactoryDiscovery; use Http\Discovery\Psr18ClientDiscovery; use Monolog\Handler\StreamHandler; @@ -56,9 +57,9 @@ class Configuration private LoggerInterface $logger; /** - * @var null|ClientInterface + * @var HttpMethodsClient|ClientInterface|null */ - private ?ClientInterface $client = null; + private $client = null; /** * @var int @@ -103,8 +104,18 @@ public function __construct(array $config) $this->logger = new Logger('typesense'); $this->logger->pushHandler(new StreamHandler('php://stdout', $this->logLevel)); - if (true === \array_key_exists('client', $config) && $config['client'] instanceof ClientInterface) { - $this->client = $config['client']; + if (isset($config['client'])) { + if ($config['client'] instanceof HttpMethodsClient || $config['client'] instanceof ClientInterface) { + $this->client = $config['client']; + } elseif ($config['client'] instanceof HttpClient) { + $this->client = new HttpMethodsClient( + $config['client'], + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory() + ); + } else { + throw new ConfigError('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient'); + } } } @@ -216,10 +227,14 @@ public function getLogger(): LoggerInterface */ public function getClient(): ClientInterface { - return new HttpMethodsClient( - $this->client ?? Psr18ClientDiscovery::find(), - Psr17FactoryDiscovery::findRequestFactory(), - Psr17FactoryDiscovery::findStreamFactory(), - ); + if ($this->client === null) { + $discoveredClient = Psr18ClientDiscovery::find(); + $this->client = new HttpMethodsClient( + $discoveredClient, + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory() + ); + } + return $this->client; } } diff --git a/tests/Feature/HttpClientsTest.php b/tests/Feature/HttpClientsTest.php new file mode 100644 index 00000000..de3ab05d --- /dev/null +++ b/tests/Feature/HttpClientsTest.php @@ -0,0 +1,84 @@ +baseConfig = [ + 'api_key' => $_ENV['TYPESENSE_API_KEY'], + 'nodes' => [[ + 'host' => $_ENV['TYPESENSE_NODE_HOST'], + 'port' => $_ENV['TYPESENSE_NODE_PORT'], + 'protocol' => $_ENV['TYPESENSE_NODE_PROTOCOL'] + ]] + ]; + } + + public function testWorksWithDefaultClient(): void + { + $client = new Client($this->baseConfig); + $response = $client->health->retrieve(); + $this->assertIsBool($response['ok']); + } + + public function testWorksWithPsr18Client(): void + { + $httpClient = new Psr18Client(); + $wrappedClient = new HttpMethodsClient( + $httpClient, + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory() + ); + + $config = array_merge($this->baseConfig, ['client' => $wrappedClient]); + $client = new Client($config); + $response = $client->health->retrieve(); + $this->assertIsBool($response['ok']); + } + + public function testWorksWithHttpMethodsClient(): void + { + $httpClient = new HttpMethodsClient( + Psr18ClientDiscovery::find(), + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory() + ); + + $config = array_merge($this->baseConfig, ['client' => $httpClient]); + + $client = new Client($config); + $response = $client->health->retrieve(); + $this->assertIsBool($response['ok']); + } + + public function testWorksWithLegacyPsr18Client(): void + { + $httpClient = $this->createMock(\Psr\Http\Client\ClientInterface::class); + $config = array_merge($this->baseConfig, ['client' => $httpClient]); + $client = new Client($config); + $this->assertInstanceOf(Client::class, $client); + } + + public function testRejectsInvalidClient(): void + { + $this->expectException(ConfigError::class); + $this->expectExceptionMessage('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient'); + + $config = array_merge($this->baseConfig, ['client' => new stdClass()]); + new Client($config); + } +}