83fae6f1c2
* [#448] added reconnection logic to websocket * [#448] added test Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
106 lines
2.7 KiB
TypeScript
106 lines
2.7 KiB
TypeScript
import { Auth } from "@/features/User/oidcAuth";
|
|
import ky from "ky";
|
|
import { getRetryDelay } from "./getRetryDelay";
|
|
|
|
const RETRY_CONFIG = {
|
|
maxRetries: 10,
|
|
initialDelay: 1000,
|
|
maxDelay: 120000,
|
|
};
|
|
export const api = ky.extend({
|
|
prefixUrl: (window as any).CALENDAR_BASE_URL,
|
|
retry: {
|
|
limit: RETRY_CONFIG.maxRetries,
|
|
backoffLimit: RETRY_CONFIG.maxDelay,
|
|
delay: (attemptCount) =>
|
|
getRetryDelay(attemptCount - 1, {
|
|
initialDelay: RETRY_CONFIG.initialDelay,
|
|
maxDelay: RETRY_CONFIG.maxDelay,
|
|
}),
|
|
},
|
|
hooks: {
|
|
beforeRequest: [
|
|
async (request) => {
|
|
const saved = sessionStorage.getItem("tokenSet")
|
|
? JSON.parse(sessionStorage.getItem("tokenSet")!)
|
|
: null;
|
|
const access_token = saved?.access_token;
|
|
if (access_token) {
|
|
request.headers.set("Authorization", `Bearer ${access_token}`);
|
|
}
|
|
return request;
|
|
},
|
|
],
|
|
|
|
beforeRetry: [
|
|
async ({ request, error, retryCount }) => {
|
|
console.warn(
|
|
`[API Retry] Attempt ${retryCount}/${RETRY_CONFIG.maxRetries}`,
|
|
{
|
|
url: request.url,
|
|
error: error?.message,
|
|
}
|
|
);
|
|
},
|
|
],
|
|
|
|
afterResponse: [
|
|
async (request, options, response) => {
|
|
if (response.status === 401) {
|
|
// Check if we're already on login flow to prevent redirect loop
|
|
const currentPath = window.location.pathname;
|
|
if (currentPath === "/" || currentPath === "/callback") {
|
|
return response;
|
|
}
|
|
|
|
// Check if we have a token in the request
|
|
const hasAuthHeader = request.headers.has("Authorization");
|
|
if (!hasAuthHeader) {
|
|
return response;
|
|
}
|
|
|
|
// Only redirect to SSO if we're sure token is invalid (not just missing)
|
|
const loginurl = await Auth();
|
|
|
|
sessionStorage.setItem(
|
|
"redirectState",
|
|
JSON.stringify({
|
|
code_verifier: loginurl.code_verifier,
|
|
state: loginurl.state,
|
|
})
|
|
);
|
|
redirectTo(loginurl.redirectTo);
|
|
}
|
|
return response;
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
export function redirectTo(url: URL) {
|
|
window.location.assign(url);
|
|
}
|
|
|
|
export function getLocation() {
|
|
return window.location.href;
|
|
}
|
|
|
|
export function isValidUrl(string?: string) {
|
|
let url;
|
|
|
|
try {
|
|
url = new URL(string ?? "");
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
return url;
|
|
}
|
|
|
|
export async function importFile(file: File) {
|
|
const response = await api.post(
|
|
`api/files?mimetype=${file.type}&name=${file.name}&size=${file.size}`,
|
|
{ body: await file.text() }
|
|
);
|
|
return await response.json();
|
|
}
|