File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? '';
const ADMIN_LOGIN_URL = '/uat/uia/actionSecurityLogin.do';
const ADMIN_ID = 'admin';
const ADMIN_PASSWORD = '1';
type ApiEnvelope<T> = {
success?: boolean;
message?: string;
data?: T;
};
let loginPromise: Promise<void> | null = null;
function toApiUrl(path: string) {
if (/^https?:\/\//i.test(path)) {
return path;
}
return `${API_BASE_URL}${path}`;
}
function createHeaders(headers?: HeadersInit) {
return new Headers(headers);
}
async function adminLogin() {
if (!loginPromise) {
loginPromise = fetch(toApiUrl(ADMIN_LOGIN_URL), {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest',
},
body: new URLSearchParams({
id: ADMIN_ID,
password: ADMIN_PASSWORD,
}),
})
.then(async (response) => {
if (!response.ok) {
throw new Error(`Admin login failed: ${response.status}`);
}
const contentType = response.headers.get('content-type') ?? '';
if (contentType.includes('application/json')) {
const result = (await response.json()) as ApiEnvelope<unknown>;
if (result.success === false) {
throw new Error(result.message ?? 'Admin login failed');
}
}
})
.finally(() => {
loginPromise = null;
});
}
return loginPromise;
}
async function needsAdminLogin(response: Response) {
if (response.type === 'opaqueredirect' || response.status === 0) {
return true;
}
if (response.status >= 300 && response.status < 400) {
return true;
}
if (response.status === 401 || response.status === 403) {
return true;
}
const contentType = response.headers.get('content-type') ?? '';
if (contentType.includes('text/html')) {
const html = await response.clone().text();
return html.includes('/uat/uia/actionMain.do') || html.includes('actionSecurityLogin.do');
}
if (contentType.includes('application/json')) {
try {
const result = (await response.clone().json()) as ApiEnvelope<unknown>;
const message = result.message ?? '';
return result.success === false && /login|로그인|/.test(message);
} catch {
return false;
}
}
return false;
}
export async function adminAuthFetch(path: string, init: RequestInit = {}, retry = true): Promise<Response> {
const response = await fetch(toApiUrl(path), {
...init,
credentials: 'include',
headers: createHeaders(init.headers),
redirect: 'manual',
});
if (retry && (await needsAdminLogin(response))) {
await adminLogin();
return adminAuthFetch(path, init, false);
}
return response;
}
export async function adminAuthJson<T>(path: string, init?: RequestInit): Promise<T> {
const response = await adminAuthFetch(path, init);
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
const result = (await response.json()) as ApiEnvelope<T>;
if (result.success === false) {
throw new Error(result.message ?? 'API request failed');
}
return result.data as T;
}