Include error response body in API client errors
This commit is contained in:
parent
a823863d0b
commit
95af305966
@ -1,3 +1,5 @@
|
|||||||
|
import { readErrorBody } from "../utils/fetch";
|
||||||
|
|
||||||
/** CurseForge API 客户端,封装两套 API 的鉴权与 User-Agent。 */
|
/** CurseForge API 客户端,封装两套 API 的鉴权与 User-Agent。 */
|
||||||
export class CurseForgeClient {
|
export class CurseForgeClient {
|
||||||
/** GET /v1/mods/{modId}/files 等只读接口 */
|
/** GET /v1/mods/{modId}/files 等只读接口 */
|
||||||
@ -38,8 +40,9 @@ export class CurseForgeClient {
|
|||||||
headers: this.apiHeaders(),
|
headers: this.apiHeaders(),
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
const body = await readErrorBody(res);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`CurseForge API GET ${path} failed: ${res.status} ${res.statusText}`,
|
`CurseForge API GET ${path} failed: ${res.status} ${res.statusText}\n${body}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<T>;
|
return res.json() as Promise<T>;
|
||||||
@ -51,8 +54,9 @@ export class CurseForgeClient {
|
|||||||
headers: this.uploadHeaders(),
|
headers: this.uploadHeaders(),
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
const body = await readErrorBody(res);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`CurseForge Upload GET ${path} failed: ${res.status} ${res.statusText}`,
|
`CurseForge Upload GET ${path} failed: ${res.status} ${res.statusText}\n${body}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<T>;
|
return res.json() as Promise<T>;
|
||||||
@ -69,8 +73,9 @@ export class CurseForgeClient {
|
|||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
const resBody = await readErrorBody(res);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`CurseForge Upload POST ${path} failed: ${res.status} ${res.statusText}`,
|
`CurseForge Upload POST ${path} failed: ${res.status} ${res.statusText}\n${resBody}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<T>;
|
return res.json() as Promise<T>;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { readErrorBody } from "../utils/fetch";
|
||||||
|
|
||||||
/** Modrinth API v2 的基础请求客户端,封装鉴权与 User-Agent。 */
|
/** Modrinth API v2 的基础请求客户端,封装鉴权与 User-Agent。 */
|
||||||
export class ModrinthClient {
|
export class ModrinthClient {
|
||||||
private base = "https://api.modrinth.com/v2";
|
private base = "https://api.modrinth.com/v2";
|
||||||
@ -26,8 +28,9 @@ export class ModrinthClient {
|
|||||||
headers: this.headers(),
|
headers: this.headers(),
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
const body = await readErrorBody(res);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Modrinth API GET ${path} failed: ${res.status} ${res.statusText}`,
|
`Modrinth API GET ${path} failed: ${res.status} ${res.statusText}\n${body}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<T>;
|
return res.json() as Promise<T>;
|
||||||
@ -44,8 +47,9 @@ export class ModrinthClient {
|
|||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
const resBody = await readErrorBody(res);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Modrinth API POST ${path} failed: ${res.status} ${res.statusText}`,
|
`Modrinth API POST ${path} failed: ${res.status} ${res.statusText}\n${resBody}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<T>;
|
return res.json() as Promise<T>;
|
||||||
|
|||||||
12
src/lib/utils/fetch.ts
Normal file
12
src/lib/utils/fetch.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* 读取错误响应体文本(最多 4096 字符),用于拼入错误信息。
|
||||||
|
* 若读取失败则返回兜底字符串。
|
||||||
|
*/
|
||||||
|
export async function readErrorBody(res: Response): Promise<string> {
|
||||||
|
try {
|
||||||
|
const text = await res.text();
|
||||||
|
return text.slice(0, 4096);
|
||||||
|
} catch {
|
||||||
|
return "(unable to read response body)";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user