client: tolerate empty response bodies on 2xx
Every verb ended in an unconditional res.json(), which throws "Unexpected end of JSON input" on 201/204 responses that carry no body — so a request that actually succeeded still surfaced as an error (e.g. a sent chat message toasting a failure). Read text first and only parse when non-empty, otherwise resolve undefined. Non-empty JSON is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,13 @@ export const getHeaders = (isText: boolean = false) => {
|
|||||||
return headers;
|
return headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 2xx responses can legitimately carry no body (201 Created / 204 No Content). res.json() throws on an
|
||||||
|
// empty body, so read text first and only parse when there's something — otherwise resolve undefined.
|
||||||
|
const parseBody = async <T>(res: Response): Promise<T> => {
|
||||||
|
const text = await res.text();
|
||||||
|
return (text ? JSON.parse(text) : undefined) as T;
|
||||||
|
};
|
||||||
|
|
||||||
export const getText = async (uri: string, baseUrl = '') => {
|
export const getText = async (uri: string, baseUrl = '') => {
|
||||||
const headers = getHeaders(true);
|
const headers = getHeaders(true);
|
||||||
const theUrl = baseUrl ? `${baseUrl}/${uri.replace(/^\//, '')}` : uri;
|
const theUrl = baseUrl ? `${baseUrl}/${uri.replace(/^\//, '')}` : uri;
|
||||||
@@ -67,8 +74,7 @@ export const get = async <T>(uri: string, baseUrl = '') => {
|
|||||||
const theUrl = baseUrl ? `${baseUrl}/${uri.replace(/^\//, '')}` : uri;
|
const theUrl = baseUrl ? `${baseUrl}/${uri.replace(/^\//, '')}` : uri;
|
||||||
const res = await fetch(theUrl, { headers });
|
const res = await fetch(theUrl, { headers });
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
return parseBody<T>(res);
|
||||||
return data as T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getBlob = async (uri: string, baseUrl = '') => {
|
export const getBlob = async (uri: string, baseUrl = '') => {
|
||||||
@@ -100,8 +106,7 @@ export const post = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
return parseBody<T>(res);
|
||||||
return data as T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const put = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
export const put = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||||
@@ -119,8 +124,7 @@ export const put = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
return parseBody<T>(res);
|
||||||
return data as T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const patch = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
export const patch = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||||
@@ -132,8 +136,7 @@ export const patch = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
return parseBody<T>(res);
|
||||||
return data as T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DELETE = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
export const DELETE = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||||
@@ -145,8 +148,7 @@ export const DELETE = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
return parseBody<T>(res);
|
||||||
return data as T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateResponse = async (res: Response) => {
|
const validateResponse = async (res: Response) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user