From 5093d3a218d5ac44051f3d06aa6740069fad4efd Mon Sep 17 00:00:00 2001 From: Pepa Martinec Date: Mon, 22 Jun 2026 11:23:05 +0200 Subject: [PATCH] PAT-1866 Return the response from ApiClient::sendRequest() sendRequest() previously returned void and discarded the response. Return the ResponseInterface (a backward-compatible widening) so callers can decode the raw body themselves -- e.g. clients whose payloads must preserve the JSON object/array distinction -- without going through the array-based sendRequestAndMapResponse(). Now that sendRequest() returns the response, the private doSendRequest() was a redundant indirection: fold it into sendRequest(), which gains the optional per-request $options (already public via sendRequestAndMapResponse). --- libs/php-api-client-base/src/ApiClient.php | 37 ++++++++----------- .../tests/ApiClientTest.php | 13 +++++++ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/libs/php-api-client-base/src/ApiClient.php b/libs/php-api-client-base/src/ApiClient.php index 9640da2a9..8db6e3a14 100644 --- a/libs/php-api-client-base/src/ApiClient.php +++ b/libs/php-api-client-base/src/ApiClient.php @@ -113,9 +113,22 @@ static function (callable $handler) use ($authenticator): callable { ]); } - public function sendRequest(RequestInterface $request): void + /** + * @param array $options + */ + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface { - $this->doSendRequest($request); + try { + return $this->httpClient->send($request, $options); + } catch (RequestException $e) { + throw $this->processRequestException($e); + } catch (GuzzleException $e) { + throw new $this->exceptionClass($e->getMessage(), 0, $e, null, null); + } catch (Throwable $e) { + // Non-Guzzle failure bubbling out of the handler stack — e.g. an authenticator + // that could not produce credentials (after retries are exhausted). + throw new $this->exceptionClass(trim($e->getMessage()), 0, $e, null, null); + } } /** @@ -130,7 +143,7 @@ public function sendRequestAndMapResponse( array $options = [], bool $isList = false, ) { - $response = $this->doSendRequest($request, $options); + $response = $this->sendRequest($request, $options); $body = $response->getBody()->getContents(); try { @@ -165,24 +178,6 @@ public function sendRequestAndMapResponse( } } - /** - * @param array $options - */ - private function doSendRequest(RequestInterface $request, array $options = []): ResponseInterface - { - try { - return $this->httpClient->send($request, $options); - } catch (RequestException $e) { - throw $this->processRequestException($e); - } catch (GuzzleException $e) { - throw new $this->exceptionClass($e->getMessage(), 0, $e, null, null); - } catch (Throwable $e) { - // Non-Guzzle failure bubbling out of the handler stack — e.g. an authenticator - // that could not produce credentials (after retries are exhausted). - throw new $this->exceptionClass(trim($e->getMessage()), 0, $e, null, null); - } - } - private function processRequestException(RequestException $e): ClientException { $response = $e->getResponse(); diff --git a/libs/php-api-client-base/tests/ApiClientTest.php b/libs/php-api-client-base/tests/ApiClientTest.php index 08731ddcb..9ee1c0ce6 100644 --- a/libs/php-api-client-base/tests/ApiClientTest.php +++ b/libs/php-api-client-base/tests/ApiClientTest.php @@ -53,6 +53,19 @@ public function testAddsAuthHeaderPerRequest(): void self::assertSame('secret-token', $last->getHeaderLine('X-KBC-ManageApiToken')); } + public function testSendRequestReturnsResponse(): void + { + $mock = new MockHandler([new Response(201, [], '{"hello":"world"}')]); + $client = new ApiClient('https://example.test', new NoAuthAuthenticator(), new ApiClientOptions( + requestHandler: HandlerStack::create($mock), + )); + + $response = $client->sendRequest(new Request('GET', 'foo')); + + self::assertSame(201, $response->getStatusCode()); + self::assertSame('{"hello":"world"}', (string) $response->getBody()); + } + public function testMapsResponseToModel(): void { $mock = new MockHandler([new Response(200, [], '{"name":"foo"}')]);