106 lines
2.5 KiB
JavaScript
106 lines
2.5 KiB
JavaScript
import { API_BASE_URL } from "../config/env.js";
|
|
|
|
const TOKEN_KEY = "hyapp-admin.access-token";
|
|
|
|
let accessToken = window.localStorage.getItem(TOKEN_KEY) || "";
|
|
let refreshHandler = null;
|
|
let unauthorizedHandler = null;
|
|
|
|
export function getAccessToken() {
|
|
return accessToken;
|
|
}
|
|
|
|
export function setAccessToken(token) {
|
|
accessToken = token || "";
|
|
if (accessToken) {
|
|
window.localStorage.setItem(TOKEN_KEY, accessToken);
|
|
} else {
|
|
window.localStorage.removeItem(TOKEN_KEY);
|
|
}
|
|
}
|
|
|
|
export function setRefreshHandler(handler) {
|
|
refreshHandler = handler;
|
|
}
|
|
|
|
export function setUnauthorizedHandler(handler) {
|
|
unauthorizedHandler = handler;
|
|
}
|
|
|
|
export async function apiRequest(path, options = {}) {
|
|
const {
|
|
body,
|
|
headers = {},
|
|
method = body ? "POST" : "GET",
|
|
query,
|
|
retry = true,
|
|
raw = false,
|
|
skipAuth = false
|
|
} = options;
|
|
const url = buildURL(path, query);
|
|
const requestHeaders = { ...headers };
|
|
|
|
if (body !== undefined && !(body instanceof FormData)) {
|
|
requestHeaders["Content-Type"] = "application/json";
|
|
}
|
|
if (accessToken && !skipAuth) {
|
|
requestHeaders.Authorization = `Bearer ${accessToken}`;
|
|
}
|
|
|
|
const response = await fetch(url, {
|
|
method,
|
|
headers: requestHeaders,
|
|
body: body === undefined ? undefined : body instanceof FormData ? body : JSON.stringify(body),
|
|
credentials: "include"
|
|
});
|
|
|
|
if (response.status === 401 && retry && refreshHandler && !skipAuth) {
|
|
const refreshed = await refreshHandler();
|
|
if (refreshed) {
|
|
return apiRequest(path, { ...options, retry: false });
|
|
}
|
|
}
|
|
|
|
if (response.status === 401 && unauthorizedHandler && !skipAuth) {
|
|
unauthorizedHandler();
|
|
}
|
|
|
|
if (raw) {
|
|
if (!response.ok) {
|
|
throw new Error(response.statusText || "请求失败");
|
|
}
|
|
return response;
|
|
}
|
|
|
|
const payload = await readJSON(response);
|
|
if (!response.ok || payload.code !== 0) {
|
|
throw new Error(payload.message || response.statusText || "请求失败");
|
|
}
|
|
|
|
return payload.data;
|
|
}
|
|
|
|
function buildURL(path, query) {
|
|
const url = new URL(`${API_BASE_URL}${path}`, window.location.origin);
|
|
if (query) {
|
|
Object.entries(query).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null && value !== "") {
|
|
url.searchParams.set(key, value);
|
|
}
|
|
});
|
|
}
|
|
return url.toString();
|
|
}
|
|
|
|
async function readJSON(response) {
|
|
const text = await response.text();
|
|
if (!text) {
|
|
return {};
|
|
}
|
|
try {
|
|
return JSON.parse(text);
|
|
} catch {
|
|
return { code: response.ok ? 0 : response.status, message: text, data: text };
|
|
}
|
|
}
|