Skip to content

Commit e2f6c3a

Browse files
committed
Fix Guzzle regression: Error log was truncated / http exception not caught
Guzzle 7 renamed the option that disables automatic exception throwing for 4xx/5xx responses from 'exceptions' to 'http_errors'. The old key was silently ignored, leaving Guzzle's httpErrors middleware active. This caused GuzzleHttp\Exception\ClientException to be thrown for any non-2xx response instead of returning the response object for the caller to inspect. In practice this meant that a 400 Bad Request from the attribute aggregation API (AA) was never caught by AttributeAggregator's HttpException handler and propagated as an uncaught CRITICAL-level exception. The exception message was truncated in the logs because Guzzle's BodySummarizer only includes the first 120 characters of the response body when building the ClientException message string.
1 parent ab8a073 commit e2f6c3a

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

src/OpenConext/EngineBlock/Http/HttpClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function read($path, array $parameters = [], array $headers = [])
5353
{
5454
$resource = ResourcePathFormatter::format($path, $parameters);
5555
$response = $this->httpClient->request('GET', $resource, [
56-
'exceptions' => false,
56+
'http_errors' => false,
5757
'headers' => $headers
5858
]);
5959
$statusCode = $response->getStatusCode();
@@ -93,7 +93,7 @@ public function post($data, $path, $parameters = [], array $headers = [], bool $
9393
{
9494
$resource = ResourcePathFormatter::format($path, $parameters);
9595
$response = $this->httpClient->request('POST', $resource, [
96-
'exceptions' => false,
96+
'http_errors' => false,
9797
'body' => $data,
9898
'headers' => $headers,
9999
'verify' => $verify,

tests/unit/OpenConext/EngineBlock/Http/HttpClientTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@
4040

4141
use GuzzleHttp\Client;
4242
use GuzzleHttp\Handler\MockHandler;
43+
use GuzzleHttp\HandlerStack;
4344
use GuzzleHttp\Psr7\Response;
4445
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
4546
use OpenConext\EngineBlock\Http\Exception\AccessDeniedException;
4647
use OpenConext\EngineBlock\Http\Exception\MalformedResponseException;
48+
use OpenConext\EngineBlock\Http\Exception\UnreadableResourceException;
4749
use PHPUnit\Framework\Attributes\Group;
4850
use PHPUnit\Framework\Attributes\Test;
4951
use PHPUnit\Framework\TestCase;
@@ -196,4 +198,36 @@ public function an_access_denied_exception_is_thrown_if_the_response_status_code
196198

197199
$client->post('post-and-give-me/403', 'Post body');
198200
}
201+
202+
#[Group('EngineBlock')]
203+
#[Group('Http')]
204+
#[Test]
205+
public function an_unreadable_resource_exception_is_thrown_if_the_response_status_code_is_400_when_reading()
206+
{
207+
$mockHandler = new MockHandler([
208+
new Response(400, [], '{"error":"Bad Request"}')
209+
]);
210+
$guzzle = new Client(['handler' => HandlerStack::create($mockHandler)]);
211+
$client = new HttpClient($guzzle);
212+
213+
$this->expectException(UnreadableResourceException::class);
214+
215+
$client->read('/some-resource');
216+
}
217+
218+
#[Group('EngineBlock')]
219+
#[Group('Http')]
220+
#[Test]
221+
public function an_unreadable_resource_exception_is_thrown_if_the_response_status_code_is_400_when_posting()
222+
{
223+
$mockHandler = new MockHandler([
224+
new Response(400, [], '{"error":"Bad Request"}')
225+
]);
226+
$guzzle = new Client(['handler' => HandlerStack::create($mockHandler)]);
227+
$client = new HttpClient($guzzle);
228+
229+
$this->expectException(UnreadableResourceException::class);
230+
231+
$client->post('{"id":1}', '/some-resource');
232+
}
199233
}

0 commit comments

Comments
 (0)