Skip to content

Commit 1936d06

Browse files
mridangclaude
andcommitted
refactor: deep harmonization of exception hierarchy, field names, and API surface
- Python: rename ApiException fields (status→code, reason→message, body→response_body, headers→response_headers), remove legacy data field - Python/Ruby: add response_headers parameter to all exception subclasses and pass actual headers from base_api throw methods - Java: reduce ApiException from 9 constructors to 3, pass response headers (was null) in throwApiException, fix NullAway in DefaultApiClient - PHP: align error message format to "API returned status code {code}", fix responseHeaders doc type to array<string, string>, flatten headers - Java/C#/PHP: standardize Configuration.server() parameter name to serverConfig Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 88f4fb1 commit 1936d06

53 files changed

Lines changed: 304 additions & 339 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/resources/templates/csharp/configuration.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ public sealed class ConfigurationBuilder
108108
/// <summary>
109109
/// Set the base URL by resolving a server configuration with optional variable overrides.
110110
/// </summary>
111-
/// <param name="server">The server configuration to resolve.</param>
111+
/// <param name="serverConfig">The server configuration to resolve.</param>
112112
/// <param name="variables">Optional variable overrides. Defaults are used for unspecified variables.</param>
113113
/// <returns>This builder.</returns>
114-
public ConfigurationBuilder Server(ServerConfiguration server, Dictionary<string, string>? variables = null)
114+
public ConfigurationBuilder Server(ServerConfiguration serverConfig, Dictionary<string, string>? variables = null)
115115
{
116-
ArgumentNullException.ThrowIfNull(server);
117-
_baseUrl = server.GetUrl(variables ?? []);
116+
ArgumentNullException.ThrowIfNull(serverConfig);
117+
_baseUrl = serverConfig.GetUrl(variables ?? []);
118118
return this;
119119
}
120120

src/main/resources/templates/java/api_exception.mustache

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,6 @@ public class ApiException extends Exception {
1414
@Nullable private final String responseBody;
1515
@Nullable private final transient Object errorBody;
1616
17-
public ApiException() {
18-
this.code = 0;
19-
this.responseHeaders = null;
20-
this.responseBody = null;
21-
this.errorBody = null;
22-
}
23-
24-
public ApiException(Throwable throwable) {
25-
super(throwable);
26-
this.code = 0;
27-
this.responseHeaders = null;
28-
this.responseBody = null;
29-
this.errorBody = null;
30-
}
31-
3217
public ApiException(String message) {
3318
super(message);
3419
this.code = 0;
@@ -37,54 +22,12 @@ public class ApiException extends Exception {
3722
this.errorBody = null;
3823
}
3924

40-
public ApiException(
41-
String message,
42-
@Nullable Throwable throwable,
43-
int code,
44-
@Nullable Map<String, String> responseHeaders,
45-
@Nullable String responseBody) {
46-
super(message, throwable);
47-
this.code = code;
48-
this.responseHeaders = responseHeaders;
49-
this.responseBody = responseBody;
50-
this.errorBody = null;
51-
}
52-
53-
public ApiException(
54-
String message,
55-
int code,
56-
@Nullable Map<String, String> responseHeaders,
57-
@Nullable String responseBody) {
58-
this(message, null, code, responseHeaders, responseBody);
59-
}
60-
61-
public ApiException(
62-
String message,
63-
@Nullable Throwable throwable,
64-
int code,
65-
@Nullable Map<String, String> responseHeaders) {
66-
this(message, throwable, code, responseHeaders, null);
67-
}
68-
69-
public ApiException(int code, Map<String, String> responseHeaders, String responseBody) {
70-
this(
71-
"Response Code: " + code + " Response Body: " + responseBody,
72-
null,
73-
code,
74-
responseHeaders,
75-
responseBody);
76-
}
77-
78-
public ApiException(int code, String message) {
79-
this(message, null, code, null, null);
80-
}
81-
8225
public ApiException(
8326
int code,
8427
String message,
8528
@Nullable Map<String, String> responseHeaders,
8629
@Nullable String responseBody) {
87-
this(message, null, code, responseHeaders, responseBody);
30+
this(code, message, responseHeaders, responseBody, null);
8831
}
8932

9033
public ApiException(

src/main/resources/templates/java/base_api.mustache

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ public abstract class BaseApi {
275275
int code = response.statusCode();
276276
String message = "API returned status code " + code;
277277
String body = response.body();
278+
Map<String, String> headers = response.headers();
278279
279280
Object errorBody = null;
280281
if (body != null && !body.isEmpty()) {
@@ -287,22 +288,22 @@ public abstract class BaseApi {
287288

288289
if (code >= 400 && code < 500) {
289290
throw switch (code) {
290-
case 400 -> new BadRequestException(message, null, body, errorBody);
291-
case 401 -> new UnauthorizedException(message, null, body, errorBody);
292-
case 403 -> new ForbiddenException(message, null, body, errorBody);
293-
case 404 -> new NotFoundException(message, null, body, errorBody);
294-
case 409 -> new ConflictException(message, null, body, errorBody);
295-
case 422 -> new UnprocessableEntityException(message, null, body, errorBody);
296-
default -> new ClientException(code, message, null, body, errorBody);
291+
case 400 -> new BadRequestException(message, headers, body, errorBody);
292+
case 401 -> new UnauthorizedException(message, headers, body, errorBody);
293+
case 403 -> new ForbiddenException(message, headers, body, errorBody);
294+
case 404 -> new NotFoundException(message, headers, body, errorBody);
295+
case 409 -> new ConflictException(message, headers, body, errorBody);
296+
case 422 -> new UnprocessableEntityException(message, headers, body, errorBody);
297+
default -> new ClientException(code, message, headers, body, errorBody);
297298
};
298299
}
299300
if (code >= 500) {
300301
throw switch (code) {
301-
case 500 -> new InternalServerErrorException(message, null, body, errorBody);
302-
default -> new ServerException(code, message, null, body, errorBody);
302+
case 500 -> new InternalServerErrorException(message, headers, body, errorBody);
303+
default -> new ServerException(code, message, headers, body, errorBody);
303304
};
304305
}
305-
throw new ApiException(code, message, null, body);
306+
throw new ApiException(code, message, headers, body);
306307
}
307308

308309
/**

src/main/resources/templates/java/configuration.mustache

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,23 @@ public final class Configuration {
143143
* use their default values. Enum validation is performed by
144144
* {@link ServerConfiguration#getUrl(Map)}.
145145
*
146-
* @param server the server configuration to use
147-
* @param variables variable overrides (may be null for defaults)
146+
* @param serverConfig the server configuration to use
147+
* @param variables variable overrides (may be null for defaults)
148148
* @return this builder
149149
*/
150-
public Builder server(ServerConfiguration server, @Nullable Map<String, String> variables) {
151-
this.baseUrl = server.getUrl(variables != null ? variables : Map.of());
150+
public Builder server(ServerConfiguration serverConfig, @Nullable Map<String, String> variables) {
151+
this.baseUrl = serverConfig.getUrl(variables != null ? variables : Map.of());
152152
return this;
153153
}
154154

155155
/**
156156
* Use a server configuration with default variables to set the base URL.
157157
*
158-
* @param server the server configuration to use
158+
* @param serverConfig the server configuration to use
159159
* @return this builder
160160
*/
161-
public Builder server(ServerConfiguration server) {
162-
return server(server, null);
161+
public Builder server(ServerConfiguration serverConfig) {
162+
return server(serverConfig, null);
163163
}
164164

165165
/**

src/main/resources/templates/java/default_api_client.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,10 @@ public final class DefaultApiClient implements ApiClient {
219219
responseBody,
220220
responseHeaders);
221221
} catch (IOException e) {
222-
throw new ApiException(e);
222+
throw new ApiException(e.toString());
223223
} catch (InterruptedException e) {
224224
Thread.currentThread().interrupt();
225-
throw new ApiException(e);
225+
throw new ApiException(e.toString());
226226
}
227227
}
228228

src/main/resources/templates/php/api_exception.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ApiException extends Exception
1818
/**
1919
* The HTTP headers of the server response.
2020
*
21-
* @var string[][]|null
21+
* @var array<string, string>|null
2222
*/
2323
protected ?array $responseHeaders;
2424
@@ -28,7 +28,7 @@ class ApiException extends Exception
2828
protected mixed $errorBody;
2929
3030
/**
31-
* @param string[][]|null $responseHeaders HTTP response headers
31+
* @param array<string, string>|null $responseHeaders HTTP response headers
3232
*/
3333
public function __construct(
3434
string $message = "",
@@ -46,7 +46,7 @@ class ApiException extends Exception
4646
/**
4747
* Gets the HTTP response headers.
4848
*
49-
* @return string[][]|null HTTP response headers
49+
* @return array<string, string>|null HTTP response headers
5050
*/
5151
public function getResponseHeaders(): ?array
5252
{

src/main/resources/templates/php/base_api.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ class BaseApi
197197
private function throwApiException(ApiResponse $response): never
198198
{
199199
$code = $response->statusCode;
200-
$message = sprintf('[%d] Error', $code);
201-
$headers = $response->headers;
200+
$message = "API returned status code $code";
201+
$headers = array_map(fn(array $values): string => $values[0] ?? '', $response->headers);
202202
$body = $response->body;
203203
204204
$errorBody = null;

src/main/resources/templates/php/configuration_builder.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ final class ConfigurationBuilder
6060
* Enum validation is performed by {@see ServerConfiguration::getUrl()}.
6161
* If the user also calls baseUrl() after server(), the explicit baseUrl wins (last-write-wins).
6262
*
63-
* @param ServerConfiguration $server the server configuration to resolve
64-
* @param array<string, string> $variables variable name to value overrides
63+
* @param ServerConfiguration $serverConfig the server configuration to resolve
64+
* @param array<string, string> $variables variable name to value overrides
6565
* @return self this builder
6666
*/
67-
public function server(ServerConfiguration $server, array $variables = []): self
67+
public function server(ServerConfiguration $serverConfig, array $variables = []): self
6868
{
69-
$this->baseUrl = $server->getUrl($variables);
69+
$this->baseUrl = $serverConfig->getUrl($variables);
7070
return $this;
7171
}
7272

src/main/resources/templates/python/base_api.mustache

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ class BaseApi:
225225
code = response.status_code
226226
message = f'API returned status code {code}'
227227
body = response.body
228+
headers = dict(response.headers) if response.headers else None
228229

229230
error_body = None
230231
if body:
@@ -235,20 +236,20 @@ class BaseApi:
235236

236237
if 400 <= code < 500:
237238
if code == 400:
238-
raise BadRequestException(reason=message, body=body, error_body=error_body)
239+
raise BadRequestException(message=message, response_body=body, response_headers=headers, error_body=error_body)
239240
if code == 401:
240-
raise UnauthorizedException(reason=message, body=body, error_body=error_body)
241+
raise UnauthorizedException(message=message, response_body=body, response_headers=headers, error_body=error_body)
241242
if code == 403:
242-
raise ForbiddenException(reason=message, body=body, error_body=error_body)
243+
raise ForbiddenException(message=message, response_body=body, response_headers=headers, error_body=error_body)
243244
if code == 404:
244-
raise NotFoundException(reason=message, body=body, error_body=error_body)
245+
raise NotFoundException(message=message, response_body=body, response_headers=headers, error_body=error_body)
245246
if code == 409:
246-
raise ConflictException(reason=message, body=body, error_body=error_body)
247+
raise ConflictException(message=message, response_body=body, response_headers=headers, error_body=error_body)
247248
if code == 422:
248-
raise UnprocessableEntityException(reason=message, body=body, error_body=error_body)
249-
raise ClientException(status=code, reason=message, body=body, error_body=error_body)
249+
raise UnprocessableEntityException(message=message, response_body=body, response_headers=headers, error_body=error_body)
250+
raise ClientException(code=code, message=message, response_body=body, response_headers=headers, error_body=error_body)
250251
if code >= 500:
251252
if code == 500:
252-
raise InternalServerErrorException(reason=message, body=body, error_body=error_body)
253-
raise ServerException(status=code, reason=message, body=body, error_body=error_body)
254-
raise ApiException(status=code, reason=message, body=body, error_body=error_body)
253+
raise InternalServerErrorException(message=message, response_body=body, response_headers=headers, error_body=error_body)
254+
raise ServerException(code=code, message=message, response_body=body, response_headers=headers, error_body=error_body)
255+
raise ApiException(code=code, message=message, response_body=body, response_headers=headers, error_body=error_body)

src/main/resources/templates/python/exceptions.mustache

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -97,41 +97,40 @@ class ApiKeyError(OpenApiException, KeyError):
9797
class ApiException(OpenApiException):
9898
def __init__(
9999
self,
100-
status: Optional[int] = None,
101-
reason: Optional[str] = None,
100+
code: Optional[int] = None,
101+
message: Optional[str] = None,
102102
http_resp: Optional[Any] = None,
103103
*,
104-
body: Optional[str] = None,
105-
data: Optional[Any] = None,
104+
response_body: Optional[str] = None,
105+
response_headers: Optional[Any] = None,
106106
error_body: Optional[Any] = None,
107107
) -> None:
108-
self.status = status
109-
self.reason = reason
110-
self.body = body
111-
self.data = data
112-
self.headers: Optional[Any] = None
108+
self.code = code
109+
self.message = message
110+
self.response_body = response_body
111+
self.response_headers = response_headers
113112
self.error_body = error_body
114113

115114
if http_resp:
116-
if self.status is None:
117-
self.status = http_resp.status
118-
if self.reason is None:
119-
self.reason = http_resp.reason
120-
if self.body is None:
115+
if self.code is None:
116+
self.code = http_resp.status
117+
if self.message is None:
118+
self.message = http_resp.reason
119+
if self.response_body is None:
121120
try:
122-
self.body = http_resp.data.decode('utf-8')
121+
self.response_body = http_resp.data.decode('utf-8')
123122
except Exception:
124123
pass
125-
self.headers = http_resp.getheaders()
124+
self.response_headers = http_resp.getheaders()
126125

127126
def __str__(self) -> str:
128127
"""Custom error messages for exception"""
129-
error_message = '({0})\nReason: {1}\n'.format(self.status, self.reason)
130-
if self.headers:
131-
error_message += 'HTTP response headers: {0}\n'.format(self.headers)
128+
error_message = '({0})\nReason: {1}\n'.format(self.code, self.message)
129+
if self.response_headers:
130+
error_message += 'HTTP response headers: {0}\n'.format(self.response_headers)
132131

133-
if self.data or self.body:
134-
error_message += 'HTTP response body: {0}\n'.format(self.data or self.body)
132+
if self.response_body:
133+
error_message += 'HTTP response body: {0}\n'.format(self.response_body)
135134

136135
return error_message
137136

0 commit comments

Comments
 (0)