Skip to content

Commit 126c5d8

Browse files
authored
Merge pull request #78 from tharropoulos/http-clients
Fix HTTP client handling and configuration in Typesense PHP client
2 parents 8a6c358 + 1e65565 commit 126c5d8

File tree

3 files changed

+109
-9
lines changed

3 files changed

+109
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea
22
.tmp
33
.phpunit.result.cache
4+
.env
45
/composer.lock
56
phpunit.xml
67
vendor

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 (isset($config['client'])) {
108+
if ($config['client'] instanceof HttpMethodsClient || $config['client'] instanceof ClientInterface) {
109+
$this->client = $config['client'];
110+
} elseif ($config['client'] instanceof HttpClient) {
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: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
$wrappedClient = new HttpMethodsClient(
42+
$httpClient,
43+
Psr17FactoryDiscovery::findRequestFactory(),
44+
Psr17FactoryDiscovery::findStreamFactory()
45+
);
46+
47+
$config = array_merge($this->baseConfig, ['client' => $wrappedClient]);
48+
$client = new Client($config);
49+
$response = $client->health->retrieve();
50+
$this->assertIsBool($response['ok']);
51+
}
52+
53+
public function testWorksWithHttpMethodsClient(): void
54+
{
55+
$httpClient = new HttpMethodsClient(
56+
Psr18ClientDiscovery::find(),
57+
Psr17FactoryDiscovery::findRequestFactory(),
58+
Psr17FactoryDiscovery::findStreamFactory()
59+
);
60+
61+
$config = array_merge($this->baseConfig, ['client' => $httpClient]);
62+
63+
$client = new Client($config);
64+
$response = $client->health->retrieve();
65+
$this->assertIsBool($response['ok']);
66+
}
67+
68+
public function testWorksWithLegacyPsr18Client(): void
69+
{
70+
$httpClient = $this->createMock(\Psr\Http\Client\ClientInterface::class);
71+
$config = array_merge($this->baseConfig, ['client' => $httpClient]);
72+
$client = new Client($config);
73+
$this->assertInstanceOf(Client::class, $client);
74+
}
75+
76+
public function testRejectsInvalidClient(): void
77+
{
78+
$this->expectException(ConfigError::class);
79+
$this->expectExceptionMessage('Client must implement PSR-18 ClientInterface or Http\Client\HttpClient');
80+
81+
$config = array_merge($this->baseConfig, ['client' => new stdClass()]);
82+
new Client($config);
83+
}
84+
}

0 commit comments

Comments
 (0)