Skip to content

Commit 8ab52c3

Browse files
author
Mohamed Khaled
committed
Implement complete exception hierarchy with ClientException and ServerException
1 parent 4a69461 commit 8ab52c3

File tree

3 files changed

+139
-11
lines changed

3 files changed

+139
-11
lines changed

src/Providers/Http/Exception/ClientException.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace WordPress\AiClient\Providers\Http\Exception;
66

7+
use WordPress\AiClient\Providers\Http\DTO\Response;
8+
79
/**
810
* Exception thrown for 4xx HTTP client errors.
911
*
@@ -25,6 +27,51 @@ class ClientException extends RequestException
2527
public static function fromBadRequestResponse(string $errorDetail = 'Invalid request parameters'): self
2628
{
2729
$message = sprintf('Bad request (400): %s', $errorDetail);
28-
return new self($message);
30+
return new self($message, 400);
31+
}
32+
33+
/**
34+
* Creates a ClientException from a client error response (4xx).
35+
*
36+
* This method extracts error details from common API response formats
37+
* and creates an exception with a descriptive message and status code.
38+
*
39+
* @since n.e.x.t
40+
*
41+
* @param Response $response The HTTP response that failed.
42+
* @return self
43+
*/
44+
public static function fromClientError(Response $response): self
45+
{
46+
$errorMessage = sprintf(
47+
'Client error (%d): Request was rejected due to client-side issue',
48+
$response->getStatusCode()
49+
);
50+
51+
// Handle common error formats in API responses
52+
$data = $response->getData();
53+
if (
54+
is_array($data) &&
55+
isset($data['error']) &&
56+
is_array($data['error']) &&
57+
isset($data['error']['message']) &&
58+
is_string($data['error']['message'])
59+
) {
60+
$errorMessage .= ' - ' . $data['error']['message'];
61+
} elseif (
62+
is_array($data) &&
63+
isset($data['error']) &&
64+
is_string($data['error'])
65+
) {
66+
$errorMessage .= ' - ' . $data['error'];
67+
} elseif (
68+
is_array($data) &&
69+
isset($data['message']) &&
70+
is_string($data['message'])
71+
) {
72+
$errorMessage .= ' - ' . $data['message'];
73+
}
74+
75+
return new self($errorMessage, $response->getStatusCode());
2976
}
3077
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WordPress\AiClient\Providers\Http\Exception;
6+
7+
use WordPress\AiClient\Providers\Http\DTO\Response;
8+
9+
/**
10+
* Exception thrown for 5xx HTTP server errors.
11+
*
12+
* This represents errors where the server failed to fulfill
13+
* a valid request due to internal server errors.
14+
*
15+
* @since n.e.x.t
16+
*/
17+
class ServerException extends RequestException
18+
{
19+
/**
20+
* Creates a ServerException from a server error response.
21+
*
22+
* This method extracts error details from common API response formats
23+
* and creates an exception with a descriptive message and status code.
24+
*
25+
* @since n.e.x.t
26+
*
27+
* @param Response $response The HTTP response that failed.
28+
* @return self
29+
*/
30+
public static function fromServerError(Response $response): self
31+
{
32+
$errorMessage = sprintf(
33+
'Server error (%d): Request failed due to server-side issue',
34+
$response->getStatusCode()
35+
);
36+
37+
// Handle common error formats in API responses
38+
$data = $response->getData();
39+
if (
40+
is_array($data) &&
41+
isset($data['error']) &&
42+
is_array($data['error']) &&
43+
isset($data['error']['message']) &&
44+
is_string($data['error']['message'])
45+
) {
46+
$errorMessage .= ' - ' . $data['error']['message'];
47+
} elseif (
48+
is_array($data) &&
49+
isset($data['error']) &&
50+
is_string($data['error'])
51+
) {
52+
$errorMessage .= ' - ' . $data['error'];
53+
} elseif (
54+
is_array($data) &&
55+
isset($data['message']) &&
56+
is_string($data['message'])
57+
) {
58+
$errorMessage .= ' - ' . $data['message'];
59+
}
60+
61+
return new self($errorMessage, $response->getStatusCode());
62+
}
63+
}

src/Providers/Http/Util/ResponseUtil.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use WordPress\AiClient\Providers\Http\DTO\Response;
88
use WordPress\AiClient\Providers\Http\Exception\ClientException;
99
use WordPress\AiClient\Providers\Http\Exception\ResponseException;
10+
use WordPress\AiClient\Providers\Http\Exception\ServerException;
1011

1112
/**
1213
* Class with static utility methods to process HTTP responses.
@@ -16,31 +17,48 @@
1617
class ResponseUtil
1718
{
1819
/**
19-
* Throws a response exception if the given response is not successful.
20+
* Throws an appropriate exception if the given response is not successful.
2021
*
2122
* This method checks the HTTP status code of the response and throws
22-
* a ResponseException if the status code indicates an error (i.e., not in the
23-
* 2xx range). It also attempts to extract a more detailed error message from
24-
* the response body if available.
23+
* the appropriate exception type based on the status code range:
24+
* - 4xx: ClientException (client errors)
25+
* - 5xx: ServerException (server errors)
26+
* - Other unsuccessful responses: ResponseException (malformed responses)
2527
*
2628
* @since 0.1.0
2729
*
2830
* @param Response $response The HTTP response to check.
29-
* @throws ResponseException If the response is not successful.
31+
* @throws ClientException If the response indicates a client error (4xx).
32+
* @throws ServerException If the response indicates a server error (5xx).
33+
* @throws ResponseException If the response format is unexpected.
3034
*/
3135
public static function throwIfNotSuccessful(Response $response): void
3236
{
3337
if ($response->isSuccessful()) {
3438
return;
3539
}
3640

37-
// Check for 400 Bad Request responses indicating invalid request data
38-
if ($response->getStatusCode() === 400) {
39-
$body = (string) $response->getBody();
40-
$errorDetail = $body ? substr($body, 0, 200) : 'Invalid request parameters';
41-
throw ClientException::fromBadRequestResponse($errorDetail);
41+
$statusCode = $response->getStatusCode();
42+
43+
// 4xx Client Errors
44+
if ($statusCode >= 400 && $statusCode < 500) {
45+
// Special handling for 400 Bad Request
46+
if ($statusCode === 400) {
47+
$body = (string) $response->getBody();
48+
$errorDetail = $body ? substr($body, 0, 200) : 'Invalid request parameters';
49+
throw ClientException::fromBadRequestResponse($errorDetail);
50+
}
51+
// General 4xx client errors
52+
throw ClientException::fromClientError($response);
53+
}
54+
55+
// 5xx Server Errors
56+
if ($statusCode >= 500 && $statusCode < 600) {
57+
throw ServerException::fromServerError($response);
4258
}
4359

60+
// Other unsuccessful responses (3xx redirects, etc.) - these should be rare
61+
// as most HTTP clients handle redirects automatically
4462
throw ResponseException::fromBadResponse($response);
4563
}
4664
}

0 commit comments

Comments
 (0)