Improves API client response handling and idempotency
Extends `X-Idempotency-Key` header usage to `DELETE` and `PUT` requests, ensuring idempotent behavior for a wider range of modifying API operations. Updates the documentation and client implementation for `DELETE` requests. Refactors `handleResponse` to robustly parse API responses. It now reads the response body once as text, enabling graceful handling of non-JSON error bodies and consistent processing of successful or empty responses.
This commit is contained in:
+16
-6
@@ -40,14 +40,24 @@ async function buildHeaders(
|
||||
}
|
||||
|
||||
async function handleResponse<T>(response: Response): Promise<T> {
|
||||
const rawBody = await response.text();
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({}));
|
||||
const msg = (error as { message?: string }).message ?? response.statusText;
|
||||
let msg = response.statusText;
|
||||
if (rawBody) {
|
||||
try {
|
||||
const error = JSON.parse(rawBody) as { message?: string };
|
||||
msg = error.message ?? rawBody;
|
||||
} catch {
|
||||
msg = rawBody;
|
||||
}
|
||||
}
|
||||
throw new Error(`API error [${response.status}]: ${msg}`);
|
||||
}
|
||||
// 204 No Content
|
||||
if (response.status === 204) return {} as T;
|
||||
return response.json() as Promise<T>;
|
||||
|
||||
if (!rawBody) return {} as T;
|
||||
|
||||
return JSON.parse(rawBody) as T;
|
||||
}
|
||||
|
||||
export async function apiGet<T>(
|
||||
@@ -98,7 +108,7 @@ export async function apiPatch<T>(
|
||||
}
|
||||
|
||||
export async function apiDelete<T>(path: string): Promise<T> {
|
||||
const headers = await buildHeaders("DELETE", path, "", false);
|
||||
const headers = await buildHeaders("DELETE", path, "", true);
|
||||
|
||||
const response = await fetch(`${config.baseUrl}${path}`, {
|
||||
method: "DELETE",
|
||||
|
||||
Reference in New Issue
Block a user