mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
96 lines
2.2 KiB
TypeScript
96 lines
2.2 KiB
TypeScript
import { getToken, getGitHubToken } from "./auth";
|
|
import toast from "#/utils/toast";
|
|
|
|
const WAIT_FOR_AUTH_DELAY_MS = 500;
|
|
|
|
const UNAUTHED_ROUTE_PREFIXES = [
|
|
"/api/authenticate",
|
|
"/api/options/",
|
|
"/config.json",
|
|
"/api/github/callback",
|
|
];
|
|
|
|
export async function request(
|
|
url: string,
|
|
options: RequestInit = {},
|
|
disableToast: boolean = false,
|
|
returnResponse: boolean = false,
|
|
maxRetries: number = 3,
|
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
): Promise<any> {
|
|
if (maxRetries < 0) {
|
|
throw new Error("Max retries exceeded");
|
|
}
|
|
const onFail = (msg: string) => {
|
|
if (!disableToast) {
|
|
toast.error("api", msg);
|
|
}
|
|
throw new Error(msg);
|
|
};
|
|
|
|
const needsAuth = !UNAUTHED_ROUTE_PREFIXES.some((prefix) =>
|
|
url.startsWith(prefix),
|
|
);
|
|
const token = getToken();
|
|
const githubToken = getGitHubToken();
|
|
if (!token && needsAuth) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve(
|
|
request(url, options, disableToast, returnResponse, maxRetries - 1),
|
|
);
|
|
}, WAIT_FOR_AUTH_DELAY_MS);
|
|
});
|
|
}
|
|
if (token) {
|
|
// eslint-disable-next-line no-param-reassign
|
|
options.headers = {
|
|
...(options.headers || {}),
|
|
Authorization: `Bearer ${token}`,
|
|
};
|
|
}
|
|
if (githubToken) {
|
|
// eslint-disable-next-line no-param-reassign
|
|
options.headers = {
|
|
...(options.headers || {}),
|
|
"X-GitHub-Token": githubToken,
|
|
};
|
|
}
|
|
|
|
let response = null;
|
|
try {
|
|
response = await fetch(url, options);
|
|
} catch (e) {
|
|
onFail(`Error fetching ${url}`);
|
|
}
|
|
if (response?.status === 401 && !url.startsWith("/api/authenticate")) {
|
|
await request(
|
|
"/api/authenticate",
|
|
{
|
|
method: "POST",
|
|
},
|
|
true,
|
|
);
|
|
return request(url, options, disableToast, returnResponse, maxRetries - 1);
|
|
}
|
|
if (response?.status && response?.status >= 400) {
|
|
onFail(
|
|
`${response.status} error while fetching ${url}: ${response?.statusText}`,
|
|
);
|
|
}
|
|
if (!response?.ok) {
|
|
onFail(`Error fetching ${url}: ${response?.statusText}`);
|
|
}
|
|
|
|
if (returnResponse) {
|
|
return response;
|
|
}
|
|
|
|
try {
|
|
return await (response && response.json());
|
|
} catch (e) {
|
|
onFail(`Error parsing JSON from ${url}`);
|
|
}
|
|
return null;
|
|
}
|