Skip to content

Commit adc2386

Browse files
committed
fix(http-client): improve client configuration handling
* 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
1 parent 5f0202f commit adc2386

File tree

2 files changed

+95
-9
lines changed

2 files changed

+95
-9
lines changed

src/Lib/Configuration.php

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Typesense\Lib;
44

55
use Http\Client\Common\HttpMethodsClient;
6+
use Http\Client\HttpClient;
67
use Http\Discovery\Psr17FactoryDiscovery;
78
use Http\Discovery\Psr18ClientDiscovery;
89
use Monolog\Handler\StreamHandler;
@@ -56,9 +57,9 @@ class Configuration
5657
private LoggerInterface $logger;
5758

5859
/**
59-
* @var null|ClientInterface
60+
* @var HttpMethodsClient|ClientInterface|null
6061
*/
61-
private ?ClientInterface $client = null;
62+
private $client = null;
6263

6364
/**
6465
* @var int
@@ -103,8 +104,18 @@ public function __construct(array $config)
103104
$this->logger = new Logger('typesense');
104105
$this->logger->pushHandler(new StreamHandler('php://stdout', $this->logLevel));
105106

106-
if (true === \array_key_exists('client', $config) && $config['client'] instanceof ClientInterface) {
107-
$this->client = $config['client'];
107+
if (true === \array_key_exists('client', $config)) {
108+
if ($config['client'] instanceof HttpMethodsClient) {
109+
$this->client = $config['client'];
110+
} elseif ($config['client'] instanceof HttpClient || $config['client'] instanceof ClientInterface) {
111+
$this->client = new HttpMethodsClient(
112+
$config['client'],
113+
Psr17FactoryDiscovery::findRequestFactory(),
114+
Psr17FactoryDiscovery::findStreamFactory()
115+
);
116+
} else {
117+
throw new ConfigError('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient');
118+
}
108119
}
109120
}
110121

@@ -216,10 +227,14 @@ public function getLogger(): LoggerInterface
216227
*/
217228
public function getClient(): ClientInterface
218229
{
219-
return new HttpMethodsClient(
220-
$this->client ?? Psr18ClientDiscovery::find(),
221-
Psr17FactoryDiscovery::findRequestFactory(),
222-
Psr17FactoryDiscovery::findStreamFactory(),
223-
);
230+
if ($this->client === null) {
231+
$discoveredClient = Psr18ClientDiscovery::find();
232+
$this->client = new HttpMethodsClient(
233+
$discoveredClient,
234+
Psr17FactoryDiscovery::findRequestFactory(),
235+
Psr17FactoryDiscovery::findStreamFactory()
236+
);
237+
}
238+
return $this->client;
224239
}
225240
}

tests/Feature/HttpClientsTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
namespace Feature;
4+
5+
use Tests\TestCase;
6+
use Http\Client\Common\HttpMethodsClient;
7+
use Http\Discovery\Psr17FactoryDiscovery;
8+
use Http\Discovery\Psr18ClientDiscovery;
9+
use Typesense\Exceptions\ConfigError;
10+
use Symfony\Component\HttpClient\Psr18Client;
11+
use Typesense\Client;
12+
use \stdClass;
13+
14+
class HttpClientsTest extends TestCase
15+
{
16+
private array $baseConfig;
17+
18+
protected function setUp(): void
19+
{
20+
parent::setUp();
21+
$this->baseConfig = [
22+
'api_key' => $_ENV['TYPESENSE_API_KEY'],
23+
'nodes' => [[
24+
'host' => $_ENV['TYPESENSE_NODE_HOST'],
25+
'port' => $_ENV['TYPESENSE_NODE_PORT'],
26+
'protocol' => $_ENV['TYPESENSE_NODE_PROTOCOL']
27+
]]
28+
];
29+
}
30+
31+
public function testWorksWithDefaultClient(): void
32+
{
33+
$client = new Client($this->baseConfig);
34+
$response = $client->health->retrieve();
35+
$this->assertIsBool($response['ok']);
36+
}
37+
38+
public function testWorksWithPsr18Client(): void
39+
{
40+
$httpClient = new Psr18Client();
41+
$config = array_merge($this->baseConfig, ['client' => $httpClient]);
42+
43+
$client = new Client($config);
44+
$response = $client->health->retrieve();
45+
$this->assertIsBool($response['ok']);
46+
}
47+
48+
public function testWorksWithHttpMethodsClient(): void
49+
{
50+
$httpClient = new HttpMethodsClient(
51+
Psr18ClientDiscovery::find(),
52+
Psr17FactoryDiscovery::findRequestFactory(),
53+
Psr17FactoryDiscovery::findStreamFactory()
54+
);
55+
56+
$config = array_merge($this->baseConfig, ['client' => $httpClient]);
57+
58+
$client = new Client($config);
59+
$response = $client->health->retrieve();
60+
$this->assertIsBool($response['ok']);
61+
}
62+
63+
public function testRejectsInvalidClient(): void
64+
{
65+
$this->expectException(ConfigError::class);
66+
$this->expectExceptionMessage('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient');
67+
68+
$config = array_merge($this->baseConfig, ['client' => new stdClass()]);
69+
new Client($config);
70+
}
71+
}

0 commit comments

Comments
 (0)