Robert Brennan bf8ccc8fc3
fix infinite loop (#4873)
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
2024-11-11 10:59:43 +00:00

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;
}