diff --git a/src/Client/CurseForgeAPIClient.php b/src/Client/CurseForgeAPIClient.php index 0301e0e..aa7bbe8 100644 --- a/src/Client/CurseForgeAPIClient.php +++ b/src/Client/CurseForgeAPIClient.php @@ -72,7 +72,7 @@ class CurseForgeAPIClient public function __construct(string $apiToken, ?Configuration $configuration = null, ?ClientInterface $httpClient = null) { $this->httpClient = $httpClient; - $this->configuration = $configuration ?? (Configuration::getDefaultConfiguration()) + $this->configuration = $configuration ?? (new Configuration()) ->setUserAgent(static::getDefaultUserAgent()); $this->setApiToken($apiToken); } diff --git a/tests/Unit/Client/ClientTestCase.php b/tests/Unit/Client/ClientTestCase.php index 62b45d6..9782448 100644 --- a/tests/Unit/Client/ClientTestCase.php +++ b/tests/Unit/Client/ClientTestCase.php @@ -3,7 +3,6 @@ namespace Aternos\CurseForgeApi\Tests\Unit\Client; use Aternos\CurseForgeApi\Client\CurseForgeAPIClient; -use Aternos\CurseForgeApi\Configuration; use GuzzleHttp\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; @@ -37,7 +36,6 @@ public function setUp(): void * Create a client that answers every request with one of the given responses, in order, * and records all requests in {@see $requests}. * - * The client gets its own configuration, because the default configuration is shared by all clients. * @param Response[] $responses * @return CurseForgeAPIClient */ @@ -45,7 +43,7 @@ protected function createClient(array $responses = []): CurseForgeAPIClient { $stack = HandlerStack::create(new MockHandler($responses)); $stack->push(Middleware::history($this->requests)); - return new CurseForgeAPIClient(static::API_TOKEN, new Configuration(), new Client(['handler' => $stack])); + return new CurseForgeAPIClient(static::API_TOKEN, null, new Client(['handler' => $stack])); } /** diff --git a/tests/Unit/Client/CurseForgeAPIClientTest.php b/tests/Unit/Client/CurseForgeAPIClientTest.php index 6fe663e..2ca5ffb 100644 --- a/tests/Unit/Client/CurseForgeAPIClientTest.php +++ b/tests/Unit/Client/CurseForgeAPIClientTest.php @@ -129,6 +129,52 @@ public function testSetHttpClientReplacesHttpClient(): void $this->assertRequestCount(0); } + /** + * Clients created without an explicit configuration must not share one, + * otherwise setting the API token or user agent of one client would change it for all others. + * + * @throws ApiException + */ + public function testClientsWithoutExplicitConfigurationDoNotShareOne(): void + { + $defaultConfiguration = Configuration::getDefaultConfiguration(); + $defaultApiKey = $defaultConfiguration->getApiKey("x-api-key"); + $defaultUserAgent = $defaultConfiguration->getUserAgent(); + + $firstHistory = []; + $secondHistory = []; + $first = new CurseForgeAPIClient("first-api-token", null, $this->createHttpClient($firstHistory)); + $second = new CurseForgeAPIClient("second-api-token", null, $this->createHttpClient($secondHistory)); + $first->setUserAgent("first-agent/1.0"); + + $first->getGame(432); + $second->getGame(432); + + $this->assertSame("first-api-token", $firstHistory[0]['request']->getHeaderLine("x-api-key")); + $this->assertSame("first-agent/1.0", $firstHistory[0]['request']->getHeaderLine("User-Agent")); + $this->assertSame("second-api-token", $secondHistory[0]['request']->getHeaderLine("x-api-key")); + $this->assertSame(CurseForgeAPIClient::getDefaultUserAgent(), $secondHistory[0]['request']->getHeaderLine("User-Agent")); + $this->assertSame($defaultApiKey, $defaultConfiguration->getApiKey("x-api-key")); + $this->assertSame($defaultUserAgent, $defaultConfiguration->getUserAgent()); + } + + /** + * @throws ApiException + */ + public function testExplicitConfigurationIsUsed(): void + { + $history = []; + $configuration = new Configuration(); + $client = new CurseForgeAPIClient(static::API_TOKEN, $configuration, $this->createHttpClient($history)); + + $client->setUserAgent("custom-agent/1.0"); + $client->getGame(432); + + $this->assertSame(static::API_TOKEN, $configuration->getApiKey("x-api-key")); + $this->assertSame("custom-agent/1.0", $configuration->getUserAgent()); + $this->assertSame("custom-agent/1.0", $history[0]['request']->getHeaderLine("User-Agent")); + } + /** * ObjectSerializer reads the boolean format from the default configuration, * so boolean query parameters must also be sent as strings if the client uses its own configuration. @@ -608,4 +654,17 @@ public function testGetModFileDownloadURL(): void $this->assertGetRequest("/v1/mods/420561/files/8946029/download-url"); $this->assertSame("https://edge.forgecdn.net/files/8946/29/mclogs-neoforge-26.1-3.3.4.jar", $url); } + + /** + * Create an HTTP client that answers with a single game and records all requests in the given history + * + * @param array $history + * @return Client + */ + protected function createHttpClient(array &$history): Client + { + $stack = HandlerStack::create(new MockHandler([new Response(200, [], '{"data": {"id": 432}}')])); + $stack->push(Middleware::history($history)); + return new Client(['handler' => $stack]); + } }