mirror of
https://github.com/rustfs/console.git
synced 2026-09-01 15:17:45 +08:00
137 lines
4.0 KiB
TypeScript
137 lines
4.0 KiB
TypeScript
import { joinURL } from "ufo";
|
|
import type { AwsClient } from "./aws4fetch";
|
|
|
|
class ApiClient {
|
|
private $api: any;
|
|
private config?: { baseUrl?: string; headers?: Record<string, string> };
|
|
|
|
constructor(api: AwsClient, options?: any) {
|
|
this.$api = api;
|
|
this.config = options;
|
|
}
|
|
|
|
async request(url: string, options: any = {}, parseJson: boolean = true) {
|
|
url = this.config?.baseUrl ? joinURL(this.config?.baseUrl, url) : url;
|
|
options.headers = { ...this.config?.headers, ...options.headers };
|
|
// 处理body的数据格式
|
|
options.body ? (options.body = JSON.stringify(options.body)) : null;
|
|
|
|
if (options.params) {
|
|
const queryString = new URLSearchParams(options.params).toString();
|
|
url += `?${queryString}`; // 拼接查询字符串到URL
|
|
delete options.params; // 删除params,以免影响fetch的options
|
|
}
|
|
|
|
console.log("[request] url:", url);
|
|
console.log("[request] options:", options);
|
|
|
|
const response = await this.$api.fetch(url, options);
|
|
|
|
console.log("[request] response:", response);
|
|
|
|
if (!response.ok) {
|
|
let errorMsg = response.statusText;
|
|
try {
|
|
// 优先尝试解析为 JSON
|
|
const errorData = await response.clone().json();
|
|
errorMsg = errorData.message || JSON.stringify(errorData) || errorMsg;
|
|
} catch (e) {
|
|
try {
|
|
// 如果不是 JSON,尝试解析为文本
|
|
const text = await response.clone().text();
|
|
if (text) {
|
|
// 检查是否为 XML
|
|
if (text.trim().startsWith("<")) {
|
|
// 简单提取 <Message> 或 <Error> 标签内容
|
|
const match = text.match(/<Message>(.*?)<\/Message>/i) || text.match(/<Error>(.*?)<\/Error>/i);
|
|
errorMsg = match ? match[1] : text;
|
|
} else {
|
|
errorMsg = text;
|
|
}
|
|
}
|
|
} catch (e2) {
|
|
// 保持原有 statusText
|
|
}
|
|
}
|
|
throw new Error(errorMsg);
|
|
}
|
|
|
|
// 处理401
|
|
if (response.status === 401) {
|
|
const message = useMessage();
|
|
message.error("登录信息已过期,请重新登录");
|
|
// 清除登录信息
|
|
await useAuth().logout();
|
|
window.location.href = "/auth/login";
|
|
return;
|
|
}
|
|
|
|
// 204 or body length is 0
|
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
return null;
|
|
}
|
|
|
|
if (parseJson) {
|
|
return await response.json();
|
|
} else {
|
|
return response;
|
|
}
|
|
}
|
|
|
|
async *streamRequest(url: string, options: any = {}) {
|
|
const response = await this.request(url, options, false);
|
|
|
|
if (!response.body) {
|
|
throw new Error("No response body");
|
|
}
|
|
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder("utf-8");
|
|
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
const chunk = decoder.decode(value, { stream: true });
|
|
try {
|
|
const data = JSON.parse(chunk);
|
|
yield data; // 使用 yield 返回数据
|
|
} catch (error) {
|
|
console.error("Failed to parse chunk:", error);
|
|
}
|
|
}
|
|
}
|
|
async get(url: string, options?: any) {
|
|
return this.request(url, { method: "GET", ...options });
|
|
}
|
|
|
|
async post(url: string, body: any, options?: any) {
|
|
return this.request(url, { method: "POST", body, ...options });
|
|
}
|
|
|
|
async delete(url: string, options?: any) {
|
|
return this.request(url, { method: "DELETE", ...options });
|
|
}
|
|
|
|
async put(url: string, body: any, options?: any) {
|
|
return this.request(url, { method: "PUT", body, ...options });
|
|
}
|
|
|
|
async patch(url: string, body: any, options?: any) {
|
|
return this.request(url, { method: "PATCH", body, ...options });
|
|
}
|
|
|
|
async head(url: string, options?: any) {
|
|
return this.request(url, { method: "HEAD", ...options });
|
|
}
|
|
|
|
async options(url: string, options?: any) {
|
|
return this.request(url, { method: "OPTIONS", ...options });
|
|
}
|
|
|
|
async trace(url: string, options?: any) {
|
|
return this.request(url, { method: "TRACE", ...options });
|
|
}
|
|
}
|
|
|
|
export default ApiClient;
|