Skip to content

Commit

Permalink
fix(http-client): improve client configuration handling
Browse files Browse the repository at this point in the history
* add support for HttpMethodsClient to be used directly without wrapping
* handle different client types (PSR-18, HttpClient) properly by wrapping only
  when needed
* fix client initialization to avoid creating new instances on every call
* add tests for client configuration scenarios
* improve type hints and error messages for invalid client configurations
  • Loading branch information
tharropoulos committed Dec 17, 2024
1 parent 5f0202f commit adc2386
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 9 deletions.
33 changes: 24 additions & 9 deletions src/Lib/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 (true === \array_key_exists('client', $config)) {
if ($config['client'] instanceof HttpMethodsClient) {
$this->client = $config['client'];
} elseif ($config['client'] instanceof HttpClient || $config['client'] instanceof ClientInterface) {
$this->client = new HttpMethodsClient(
$config['client'],
Psr17FactoryDiscovery::findRequestFactory(),
Psr17FactoryDiscovery::findStreamFactory()
);
} else {
throw new ConfigError('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient');
}
}
}

Expand Down Expand Up @@ -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;
}
}
71 changes: 71 additions & 0 deletions tests/Feature/HttpClientsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Feature;

use Tests\TestCase;
use Http\Client\Common\HttpMethodsClient;
use Http\Discovery\Psr17FactoryDiscovery;
use Http\Discovery\Psr18ClientDiscovery;
use Typesense\Exceptions\ConfigError;
use Symfony\Component\HttpClient\Psr18Client;
use Typesense\Client;
use \stdClass;

class HttpClientsTest extends TestCase
{
private array $baseConfig;

protected function setUp(): void
{
parent::setUp();
$this->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();
$config = array_merge($this->baseConfig, ['client' => $httpClient]);

$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 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);
}
}

0 comments on commit adc2386

Please sign in to comment.