mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-15 17:16:07 +00:00
refactor(frontend): replace axios with the native Fetch API
Drop the axios (and qs) dependencies in favor of a native fetch wrapper.
axios only ever handled same-origin JSON/form calls, a CSRF header, a 401
redirect, and a 403-retry, all of which the platform now provides directly.
- New src/api/http-init.ts (replaces axios-init.ts) reimplements the
request/response interceptors on fetch: base-path prefixing,
X-Requested-With, same-origin credentials, the CSRF token on unsafe
methods, a single 403 retry with token refresh, and the 401
redirect-and-latch. A small encodeForm() reproduces qs's
arrayFormat:'repeat' encoding, so the request wire format is unchanged.
- HttpUtil (src/utils/index.ts) keeps its public signatures and the Msg
envelope, so the ~49 API call sites are untouched. HttpOptions is now
hand-rolled instead of extending AxiosRequestConfig.
- PanelUpdateModal drops its lone direct axios.get in favor of HttpUtil.get
with { silent, timeout }.
- Add tests for the fetch core (CSRF header, form/JSON/FormData bodies,
base-path prefix, 403 retry, 401 redirect, tolerant body parse) and for
HttpUtil's envelope unwrap / toast / error mapping; this logic was
previously untested.
- Remove the vendor-axios manualChunks branch and the qs type shim, and
reword stale "axios" mentions in docs and route comments.
This commit is contained in:
+14
-10
@@ -1,6 +1,6 @@
|
||||
import axios from 'axios';
|
||||
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import i18next from 'i18next';
|
||||
import { httpRequest } from '@/api/http-init';
|
||||
import type { HttpResponse } from '@/api/http-init';
|
||||
import { getMessage } from './messageBus';
|
||||
|
||||
type RespEnvelope = { success?: unknown; msg?: unknown; obj?: unknown };
|
||||
@@ -17,7 +17,11 @@ export class Msg<T = unknown> {
|
||||
}
|
||||
}
|
||||
|
||||
export interface HttpOptions extends AxiosRequestConfig {
|
||||
export interface HttpOptions {
|
||||
headers?: Record<string, string> | Headers;
|
||||
params?: unknown;
|
||||
timeout?: number;
|
||||
signal?: AbortSignal;
|
||||
silent?: boolean;
|
||||
silentSuccess?: boolean;
|
||||
}
|
||||
@@ -48,7 +52,7 @@ export class HttpUtil {
|
||||
getMessage().error(msg.msg);
|
||||
}
|
||||
|
||||
static _respToMsg(resp: AxiosResponse | undefined): Msg {
|
||||
static _respToMsg(resp: HttpResponse | undefined): Msg {
|
||||
if (!resp || !resp.data) {
|
||||
return new Msg(false, 'No response data');
|
||||
}
|
||||
@@ -64,15 +68,15 @@ export class HttpUtil {
|
||||
}
|
||||
|
||||
static async get<T = unknown>(url: string, params?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
||||
const { silent, silentSuccess, ...axiosOpts } = options;
|
||||
const { silent, silentSuccess, ...rest } = options;
|
||||
try {
|
||||
const resp = await axios.get(url, { params, ...axiosOpts });
|
||||
const resp = await httpRequest('GET', url, undefined, { ...rest, params });
|
||||
const msg = this._respToMsg(resp) as Msg<T>;
|
||||
if (!silent) this._handleMsg(msg, silentSuccess);
|
||||
return msg;
|
||||
} catch (error) {
|
||||
console.error('GET request failed:', error);
|
||||
const err = error as AxiosError<{ message?: string }>;
|
||||
const err = error as { response?: { data?: { message?: string } }; message?: string };
|
||||
const errorMsg = new Msg<T>(false, err.response?.data?.message || err.message || 'Request failed');
|
||||
if (!silent) this._handleMsg(errorMsg);
|
||||
return errorMsg;
|
||||
@@ -80,15 +84,15 @@ export class HttpUtil {
|
||||
}
|
||||
|
||||
static async post<T = unknown>(url: string, data?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
||||
const { silent, silentSuccess, ...axiosOpts } = options;
|
||||
const { silent, silentSuccess, ...rest } = options;
|
||||
try {
|
||||
const resp = await axios.post(url, data, axiosOpts);
|
||||
const resp = await httpRequest('POST', url, data, rest);
|
||||
const msg = this._respToMsg(resp) as Msg<T>;
|
||||
if (!silent) this._handleMsg(msg, silentSuccess);
|
||||
return msg;
|
||||
} catch (error) {
|
||||
console.error('POST request failed:', error);
|
||||
const err = error as AxiosError<{ message?: string }>;
|
||||
const err = error as { response?: { data?: { message?: string } }; message?: string };
|
||||
const errorMsg = new Msg<T>(false, err.response?.data?.message || err.message || 'Request failed');
|
||||
if (!silent) this._handleMsg(errorMsg);
|
||||
return errorMsg;
|
||||
|
||||
Reference in New Issue
Block a user