fix team pro tag
This commit is contained in:
151
lib/api.ts
151
lib/api.ts
@@ -8,43 +8,132 @@ export interface ApiResponse<T = unknown> {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
// Common function for authenticated API requests to LIMQ
|
||||
/**
|
||||
* 通用的LIMQ API请求函数,包含重试机制和错误处理
|
||||
*/
|
||||
export async function limqRequest<T = unknown>(
|
||||
endpoint: string,
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
|
||||
data?: Record<string, unknown>
|
||||
data?: Record<string, unknown>,
|
||||
options?: {
|
||||
retryCount?: number;
|
||||
retryDelay?: number;
|
||||
timeout?: number;
|
||||
}
|
||||
): Promise<ApiResponse<T>> {
|
||||
// Get current session
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
// 默认配置
|
||||
const retryCount = options?.retryCount ?? 2; // 默认重试2次
|
||||
const retryDelay = options?.retryDelay ?? 1000; // 默认延迟1秒
|
||||
const timeout = options?.timeout ?? 10000; // 默认超时10秒
|
||||
|
||||
if (!session) {
|
||||
throw new Error('No active session. User must be authenticated.');
|
||||
let lastError: Error | null = null;
|
||||
let currentRetry = 0;
|
||||
|
||||
// 创建延迟函数
|
||||
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
// 重试循环
|
||||
while (currentRetry <= retryCount) {
|
||||
try {
|
||||
console.log(`[API] ${method} ${endpoint} 尝试 ${currentRetry + 1}/${retryCount + 1}`);
|
||||
|
||||
// 获取会话
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
|
||||
// 检查会话是否存在
|
||||
if (!session) {
|
||||
console.error(`[API] 未找到活跃会话,用户需要登录`);
|
||||
|
||||
if (currentRetry < retryCount) {
|
||||
currentRetry++;
|
||||
console.log(`[API] 等待 ${retryDelay}ms 后重试获取会话...`);
|
||||
await delay(retryDelay);
|
||||
continue;
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: '需要登录才能访问API'
|
||||
};
|
||||
}
|
||||
|
||||
// 获取API基础URL
|
||||
const baseUrl = process.env.NEXT_PUBLIC_LIMQ_API;
|
||||
if (!baseUrl) {
|
||||
throw new Error('API URL未配置');
|
||||
}
|
||||
|
||||
const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
|
||||
console.log(`[API] 请求URL: ${url}`);
|
||||
|
||||
// 构建请求选项
|
||||
const fetchOptions: RequestInit = {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session.access_token}`
|
||||
},
|
||||
mode: 'cors'
|
||||
};
|
||||
|
||||
if (data && (method === 'POST' || method === 'PUT')) {
|
||||
fetchOptions.body = JSON.stringify(data);
|
||||
console.log(`[API] 请求数据:`, data);
|
||||
}
|
||||
|
||||
// 添加超时控制
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||
fetchOptions.signal = controller.signal;
|
||||
|
||||
// 发送请求
|
||||
const response = await fetch(url, fetchOptions);
|
||||
clearTimeout(timeoutId); // 清除超时控制
|
||||
|
||||
// 处理响应
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null);
|
||||
console.error(`[API] 请求失败: ${response.status} ${response.statusText}`, errorData);
|
||||
|
||||
// 对于认证错误,尝试重试
|
||||
if ((response.status === 401 || response.status === 403) && currentRetry < retryCount) {
|
||||
currentRetry++;
|
||||
console.log(`[API] 认证错误,等待 ${retryDelay}ms 后重试...`);
|
||||
await delay(retryDelay);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Error(errorData?.error || `请求失败: ${response.status}`);
|
||||
}
|
||||
|
||||
// 成功响应
|
||||
const responseData = await response.json();
|
||||
console.log(`[API] ${method} ${endpoint} 成功`);
|
||||
return responseData;
|
||||
|
||||
} catch (error) {
|
||||
lastError = error instanceof Error ? error : new Error(String(error));
|
||||
console.error(`[API] 请求出错:`, lastError);
|
||||
|
||||
// 对于超时和网络错误,尝试重试
|
||||
if (currentRetry < retryCount &&
|
||||
(error instanceof DOMException && error.name === 'AbortError' ||
|
||||
error instanceof TypeError && error.message.includes('network'))) {
|
||||
currentRetry++;
|
||||
console.log(`[API] 网络错误,等待 ${retryDelay}ms 后重试...`);
|
||||
await delay(retryDelay);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 已达到最大重试次数或不是网络错误
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_LIMQ_API;
|
||||
const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
|
||||
|
||||
const options: RequestInit = {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session.access_token}`
|
||||
},
|
||||
mode: 'cors'
|
||||
// 所有重试均失败
|
||||
console.error(`[API] ${method} ${endpoint} 失败,已重试 ${currentRetry} 次`);
|
||||
return {
|
||||
success: false,
|
||||
error: lastError?.message || '请求失败,请稍后重试'
|
||||
};
|
||||
|
||||
if (data && (method === 'POST' || method === 'PUT')) {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
const response = await fetch(url, options);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null);
|
||||
throw new Error(
|
||||
errorData?.error || `Request failed with status ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
Reference in New Issue
Block a user