parent
6263759ba9
commit
9093e1bdff
|
@ -140,11 +140,11 @@ export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
|
||||||
/**
|
/**
|
||||||
* 成功的回调
|
* 成功的回调
|
||||||
*/
|
*/
|
||||||
success(response: AxiosAdapterResponse): void;
|
success(response: AnyObject): void;
|
||||||
/**
|
/**
|
||||||
* 失败的回调
|
* 失败的回调
|
||||||
*/
|
*/
|
||||||
fail(error: AxiosAdapterResponseError): void;
|
fail(error: AnyObject): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,11 +271,11 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
|
||||||
return {
|
return {
|
||||||
...config,
|
...config,
|
||||||
header: config.headers,
|
header: config.headers,
|
||||||
success(response) {
|
success(response: AxiosAdapterResponse) {
|
||||||
transformResponse(response);
|
transformResponse(response);
|
||||||
config.success(response);
|
config.success(response);
|
||||||
},
|
},
|
||||||
fail(responseError) {
|
fail(responseError: AxiosAdapterResponseError) {
|
||||||
responseError.data = {
|
responseError.data = {
|
||||||
errMsg: responseError.errMsg,
|
errMsg: responseError.errMsg,
|
||||||
errno: responseError.errno,
|
errno: responseError.errno,
|
||||||
|
@ -284,14 +284,14 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
|
||||||
config.fail(responseError);
|
config.fail(responseError);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function transformResponse(
|
function transformResponse(
|
||||||
response: AxiosAdapterResponse | AxiosAdapterResponseError,
|
response: AxiosAdapterResponse | AxiosAdapterResponseError,
|
||||||
) {
|
) {
|
||||||
response.status = response.status ?? response.statusCode;
|
response.status = response.status ?? response.statusCode;
|
||||||
response.headers = response.headers ?? response.header;
|
response.headers = response.headers ?? response.header;
|
||||||
clean(response, ['statusCode', 'errMsg', 'errno', 'header']);
|
clean(response, ['statusCode', 'errMsg', 'errno', 'header']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function processRequest(
|
function processRequest(
|
||||||
|
|
56
src/axios.ts
56
src/axios.ts
|
@ -4,37 +4,13 @@ import {
|
||||||
isCancel,
|
isCancel,
|
||||||
} from './request/cancel';
|
} from './request/cancel';
|
||||||
import { isAxiosError } from './request/createError';
|
import { isAxiosError } from './request/createError';
|
||||||
|
import Axios, { AxiosConstructor, AxiosRequestConfig } from './core/Axios';
|
||||||
|
import { AxiosInstance, createInstance } from './core/createInstance';
|
||||||
import { mergeConfig } from './core/mergeConfig';
|
import { mergeConfig } from './core/mergeConfig';
|
||||||
import { AxiosDomainRequest } from './core/AxiosDomain';
|
|
||||||
import Axios, {
|
|
||||||
AxiosConstructor,
|
|
||||||
AxiosRequestConfig,
|
|
||||||
AxiosRequestHeaders,
|
|
||||||
} from './core/Axios';
|
|
||||||
import { createAdapter } from './adpater/createAdapter';
|
import { createAdapter } from './adpater/createAdapter';
|
||||||
import defaults from './defaults';
|
import defaults from './defaults';
|
||||||
import { version } from './version';
|
import { version } from './version';
|
||||||
|
|
||||||
/**
|
|
||||||
* axios 实例默认配置
|
|
||||||
*/
|
|
||||||
export interface AxiosInstanceDefaults extends AxiosRequestConfig {
|
|
||||||
/**
|
|
||||||
* 请求头
|
|
||||||
*/
|
|
||||||
headers: Required<AxiosRequestHeaders>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* axios 实例
|
|
||||||
*/
|
|
||||||
export interface AxiosInstance extends AxiosDomainRequest, Axios {
|
|
||||||
/**
|
|
||||||
* 默认请求配置
|
|
||||||
*/
|
|
||||||
defaults: AxiosInstanceDefaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* axios 静态对象
|
* axios 静态对象
|
||||||
*/
|
*/
|
||||||
|
@ -51,12 +27,6 @@ export interface AxiosStatic extends AxiosInstance {
|
||||||
* 取消令牌
|
* 取消令牌
|
||||||
*/
|
*/
|
||||||
CancelToken: CancelTokenConstructor;
|
CancelToken: CancelTokenConstructor;
|
||||||
/**
|
|
||||||
* 创建 axios 实例
|
|
||||||
*
|
|
||||||
* @param config 默认配置
|
|
||||||
*/
|
|
||||||
create(config?: AxiosRequestConfig): AxiosInstance;
|
|
||||||
/**
|
/**
|
||||||
* 创建适配器
|
* 创建适配器
|
||||||
*/
|
*/
|
||||||
|
@ -69,26 +39,18 @@ export interface AxiosStatic extends AxiosInstance {
|
||||||
* 传入响应错误返回 true
|
* 传入响应错误返回 true
|
||||||
*/
|
*/
|
||||||
isAxiosError: typeof isAxiosError;
|
isAxiosError: typeof isAxiosError;
|
||||||
}
|
/**
|
||||||
|
* 创建 axios 实例
|
||||||
function createInstance(config: AxiosRequestConfig) {
|
*
|
||||||
const context = new Axios(config);
|
* @param config 默认配置
|
||||||
const instance = context.request as AxiosInstance;
|
*/
|
||||||
|
create(config?: AxiosRequestConfig): AxiosInstance;
|
||||||
Object.assign(instance, context);
|
|
||||||
Object.setPrototypeOf(instance, Axios.prototype);
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const axios = createInstance(defaults) as AxiosStatic;
|
const axios = createInstance(defaults) as AxiosStatic;
|
||||||
|
|
||||||
axios.create = function create(config) {
|
axios.create = function create(config) {
|
||||||
const instance = createInstance(mergeConfig(axios.defaults, config));
|
return createInstance(mergeConfig(axios.defaults, config));
|
||||||
instance.flush = axios.middleware.wrap(instance.flush);
|
|
||||||
return instance;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
axios.version = version;
|
axios.version = version;
|
||||||
axios.Axios = Axios;
|
axios.Axios = Axios;
|
||||||
axios.CancelToken = CancelToken;
|
axios.CancelToken = CancelToken;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { buildURL } from '../helpers/buildURL';
|
|
||||||
import { combineURL } from '../helpers/combineURL';
|
import { combineURL } from '../helpers/combineURL';
|
||||||
|
import { isString } from '../helpers/isTypes';
|
||||||
|
import { dispatchRequest } from '../request/dispatchRequest';
|
||||||
import { CancelToken } from '../request/cancel';
|
import { CancelToken } from '../request/cancel';
|
||||||
import { AxiosTransformer } from '../request/transformData';
|
import { AxiosTransformer } from '../request/transformData';
|
||||||
|
import { deepMerge } from '../helpers/deepMerge';
|
||||||
import {
|
import {
|
||||||
AxiosAdapter,
|
AxiosAdapter,
|
||||||
AxiosAdapterRequestMethod,
|
AxiosAdapterRequestMethod,
|
||||||
|
@ -9,9 +11,17 @@ import {
|
||||||
AxiosAdapterRequestConfig,
|
AxiosAdapterRequestConfig,
|
||||||
AxiosAdapterResponseData,
|
AxiosAdapterResponseData,
|
||||||
} from '../adpater/createAdapter';
|
} from '../adpater/createAdapter';
|
||||||
import InterceptorManager, { Interceptor } from './InterceptorManager';
|
import InterceptorManager, {
|
||||||
|
Interceptor,
|
||||||
|
InterceptorExecutor,
|
||||||
|
} from './InterceptorManager';
|
||||||
import { mergeConfig } from './mergeConfig';
|
import { mergeConfig } from './mergeConfig';
|
||||||
import AxiosDomain, { AxiosDomainRequestHandler } from './AxiosDomain';
|
import {
|
||||||
|
PLAIN_METHODS,
|
||||||
|
WITH_DATA_METHODS,
|
||||||
|
WITH_PARAMS_METHODS,
|
||||||
|
} from '../constants/methods';
|
||||||
|
import MiddlewareManager from './MiddlewareManager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求方法
|
* 请求方法
|
||||||
|
@ -293,6 +303,51 @@ export interface AxiosResponseError extends AnyObject {
|
||||||
request?: AxiosAdapterPlatformTask;
|
request?: AxiosAdapterPlatformTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AxiosContext {
|
||||||
|
req: AxiosRequestConfig;
|
||||||
|
res: null | AxiosResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AxiosRequest {
|
||||||
|
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
|
||||||
|
AxiosResponse<TData>
|
||||||
|
>;
|
||||||
|
<TData extends AxiosResponseData>(
|
||||||
|
url: string,
|
||||||
|
config?: AxiosRequestConfig,
|
||||||
|
): Promise<AxiosResponse<TData>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的请求方法
|
||||||
|
*/
|
||||||
|
export type AxiosRequestMethodFn = <TData extends AxiosResponseData>(
|
||||||
|
url: string,
|
||||||
|
config?: AxiosRequestConfig,
|
||||||
|
) => Promise<AxiosResponse<TData>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带参数的请求方法
|
||||||
|
*/
|
||||||
|
export type AxiosRequestMethodFnWithParams = <TData extends AxiosResponseData>(
|
||||||
|
url: string,
|
||||||
|
params?: AnyObject,
|
||||||
|
config?: AxiosRequestConfig,
|
||||||
|
) => Promise<AxiosResponse<TData>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带数据的请求方法
|
||||||
|
*/
|
||||||
|
export type AxiosRequestMethodFnWithData = <TData extends AxiosResponseData>(
|
||||||
|
url: string,
|
||||||
|
data?: AxiosRequestData,
|
||||||
|
config?: AxiosRequestConfig,
|
||||||
|
) => Promise<AxiosResponse<TData>>;
|
||||||
|
|
||||||
|
export interface AxiosDomainRequestHandler {
|
||||||
|
(config: AxiosRequestConfig): Promise<AxiosResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Axios 构造函数
|
* Axios 构造函数
|
||||||
*/
|
*/
|
||||||
|
@ -300,7 +355,13 @@ export interface AxiosConstructor {
|
||||||
new (config: AxiosRequestConfig): Axios;
|
new (config: AxiosRequestConfig): Axios;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Axios extends AxiosDomain {
|
export default class Axios {
|
||||||
|
#parent?: Axios;
|
||||||
|
/**
|
||||||
|
* 默认请求配置
|
||||||
|
*/
|
||||||
|
defaults: AxiosRequestConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拦截器
|
* 拦截器
|
||||||
*/
|
*/
|
||||||
|
@ -315,37 +376,102 @@ export default class Axios extends AxiosDomain {
|
||||||
response: new InterceptorManager<AxiosResponse>(),
|
response: new InterceptorManager<AxiosResponse>(),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(defaults: AxiosRequestConfig = {}) {
|
/**
|
||||||
super(defaults, (...args) => this.#processRequest(...args));
|
* 中间件
|
||||||
}
|
*/
|
||||||
|
#middleware = new MiddlewareManager<AxiosContext>(async (ctx) => {
|
||||||
|
ctx.res = await dispatchRequest(ctx.req);
|
||||||
|
});
|
||||||
|
|
||||||
getUri(config: AxiosRequestConfig): string {
|
/**
|
||||||
const { url, params, paramsSerializer } = mergeConfig(
|
* 发送 options 请求
|
||||||
this.defaults,
|
*/
|
||||||
config,
|
options!: AxiosRequestMethodFn;
|
||||||
);
|
|
||||||
return buildURL(url, params, paramsSerializer).replace(/^\?/, '');
|
/**
|
||||||
|
* 发送 get 请求
|
||||||
|
*/
|
||||||
|
get!: AxiosRequestMethodFnWithParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 head 请求
|
||||||
|
*/
|
||||||
|
head!: AxiosRequestMethodFnWithParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 post 请求
|
||||||
|
*/
|
||||||
|
post!: AxiosRequestMethodFnWithData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 put 请求
|
||||||
|
*/
|
||||||
|
put!: AxiosRequestMethodFnWithData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 patch 请求
|
||||||
|
*/
|
||||||
|
patch!: AxiosRequestMethodFnWithData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 delete 请求
|
||||||
|
*/
|
||||||
|
delete!: AxiosRequestMethodFnWithParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 trace 请求
|
||||||
|
*/
|
||||||
|
trace!: AxiosRequestMethodFn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 connect 请求
|
||||||
|
*/
|
||||||
|
connect!: AxiosRequestMethodFn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加中间件
|
||||||
|
*/
|
||||||
|
use: MiddlewareManager<AxiosContext>['use'];
|
||||||
|
|
||||||
|
constructor(defaults: AxiosRequestConfig = {}, parent?: Axios) {
|
||||||
|
this.defaults = defaults;
|
||||||
|
this.#parent = parent;
|
||||||
|
if (this.#parent) {
|
||||||
|
this.#middleware.flush = this.#parent.#middleware.wrap(
|
||||||
|
this.#middleware.flush,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.use = this.#middleware.use.bind(this.#middleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 派生领域
|
* 发送请求
|
||||||
*/
|
*/
|
||||||
fork = (config: AxiosRequestConfig = {}) => {
|
request: AxiosRequest = (
|
||||||
config.baseURL = combineURL(this.defaults.baseURL, config.baseURL);
|
urlOrConfig: string | AxiosRequestConfig,
|
||||||
const domain = new AxiosDomain(
|
config: AxiosRequestConfig = {},
|
||||||
mergeConfig(this.defaults, config),
|
) => {
|
||||||
(...args) => this.#processRequest(...args),
|
if (isString(urlOrConfig)) {
|
||||||
);
|
config.url = urlOrConfig;
|
||||||
domain.flush = this.middleware.wrap(domain.flush);
|
} else {
|
||||||
return domain;
|
config = urlOrConfig;
|
||||||
|
}
|
||||||
|
config.method = config.method || 'get';
|
||||||
|
|
||||||
|
return this.#processRequest(mergeConfig(this.defaults, config));
|
||||||
};
|
};
|
||||||
|
|
||||||
#processRequest(
|
#processRequest(config: AxiosRequestConfig) {
|
||||||
config: AxiosRequestConfig,
|
|
||||||
requestHandlerFn: AxiosDomainRequestHandler,
|
|
||||||
) {
|
|
||||||
const requestHandler = {
|
const requestHandler = {
|
||||||
resolved: requestHandlerFn,
|
resolved: async (config: AxiosRequestConfig) => {
|
||||||
|
config.url = combineURL(config.baseURL, config.url);
|
||||||
|
const ctx: AxiosContext = {
|
||||||
|
req: config,
|
||||||
|
res: null,
|
||||||
|
};
|
||||||
|
await this.#middleware.flush(ctx);
|
||||||
|
return ctx.res as AxiosResponse;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const errorHandler = {
|
const errorHandler = {
|
||||||
rejected: config.errorHandler,
|
rejected: config.errorHandler,
|
||||||
|
@ -355,11 +481,11 @@ export default class Axios extends AxiosDomain {
|
||||||
| Partial<Interceptor<AxiosResponse>>
|
| Partial<Interceptor<AxiosResponse>>
|
||||||
)[] = [];
|
)[] = [];
|
||||||
|
|
||||||
this.interceptors.request.forEach((requestInterceptor) => {
|
this.#eacheRequestInterceptors((requestInterceptor) => {
|
||||||
chain.unshift(requestInterceptor);
|
chain.unshift(requestInterceptor);
|
||||||
});
|
});
|
||||||
chain.push(requestHandler);
|
chain.push(requestHandler);
|
||||||
this.interceptors.response.forEach((responseInterceptor) => {
|
this.#eacheResponseInterceptors((responseInterceptor) => {
|
||||||
chain.push(responseInterceptor);
|
chain.push(responseInterceptor);
|
||||||
});
|
});
|
||||||
chain.push(errorHandler);
|
chain.push(errorHandler);
|
||||||
|
@ -374,4 +500,49 @@ export default class Axios extends AxiosDomain {
|
||||||
Promise.resolve(config),
|
Promise.resolve(config),
|
||||||
) as Promise<AxiosResponse>;
|
) as Promise<AxiosResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#eacheRequestInterceptors(executor: InterceptorExecutor<AxiosRequestConfig>) {
|
||||||
|
this.interceptors.request.forEach(executor);
|
||||||
|
if (this.#parent) {
|
||||||
|
this.#parent.#eacheRequestInterceptors(executor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#eacheResponseInterceptors(executor: InterceptorExecutor<AxiosResponse>) {
|
||||||
|
this.interceptors.response.forEach(executor);
|
||||||
|
if (this.#parent) {
|
||||||
|
this.#parent.#eacheResponseInterceptors(executor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const method of PLAIN_METHODS) {
|
||||||
|
Axios.prototype[method] = function processRequestMethod(url, config = {}) {
|
||||||
|
config.method = method;
|
||||||
|
return this.request(url, config);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const method of WITH_PARAMS_METHODS) {
|
||||||
|
Axios.prototype[method] = function processRequestMethodWithParams(
|
||||||
|
url,
|
||||||
|
params = {},
|
||||||
|
config = {},
|
||||||
|
) {
|
||||||
|
config.method = method;
|
||||||
|
config.params = deepMerge(params, config.params ?? {});
|
||||||
|
return this.request(url, config);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const method of WITH_DATA_METHODS) {
|
||||||
|
Axios.prototype[method] = function processRequestMethodWithData(
|
||||||
|
url,
|
||||||
|
data,
|
||||||
|
config = {},
|
||||||
|
) {
|
||||||
|
config.method = method;
|
||||||
|
config.data = data;
|
||||||
|
return this.request(url, config);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,205 +0,0 @@
|
||||||
import {
|
|
||||||
PLAIN_METHODS,
|
|
||||||
WITH_DATA_METHODS,
|
|
||||||
WITH_PARAMS_METHODS,
|
|
||||||
} from '../constants/methods';
|
|
||||||
import { isString, isUndefined } from '../helpers/isTypes';
|
|
||||||
import { deepMerge } from '../helpers/deepMerge';
|
|
||||||
import { combineURL } from '../helpers/combineURL';
|
|
||||||
import { dispatchRequest } from '../request/dispatchRequest';
|
|
||||||
import { mergeConfig } from './mergeConfig';
|
|
||||||
import {
|
|
||||||
AxiosRequestConfig,
|
|
||||||
AxiosRequestData,
|
|
||||||
AxiosResponse,
|
|
||||||
AxiosResponseData,
|
|
||||||
} from './Axios';
|
|
||||||
import MiddlewareManager, {
|
|
||||||
MiddlewareContext,
|
|
||||||
MiddlewareFlush,
|
|
||||||
} from './MiddlewareManager';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求函数
|
|
||||||
*/
|
|
||||||
export interface AxiosDomainRequest {
|
|
||||||
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
|
|
||||||
AxiosResponse<TData>
|
|
||||||
>;
|
|
||||||
<TData extends AxiosResponseData>(
|
|
||||||
url: string,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
): Promise<AxiosResponse<TData>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 普通的请求方法
|
|
||||||
*/
|
|
||||||
export type AxiosDomainRequestMethod = <TData extends AxiosResponseData>(
|
|
||||||
url: string,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
) => Promise<AxiosResponse<TData>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 带参数的请求方法
|
|
||||||
*/
|
|
||||||
export type AxiosDomainRequestMethodWithParams = <
|
|
||||||
TData extends AxiosResponseData,
|
|
||||||
>(
|
|
||||||
url: string,
|
|
||||||
params?: AnyObject,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
) => Promise<AxiosResponse<TData>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 带数据的请求方法
|
|
||||||
*/
|
|
||||||
export type AxiosDomainRequestMethodWithData = <
|
|
||||||
TData extends AxiosResponseData,
|
|
||||||
>(
|
|
||||||
url: string,
|
|
||||||
data?: AxiosRequestData,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
) => Promise<AxiosResponse<TData>>;
|
|
||||||
|
|
||||||
export interface AxiosDomainRequestHandler {
|
|
||||||
(config: AxiosRequestConfig): Promise<AxiosResponse>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AxiosDomain {
|
|
||||||
/**
|
|
||||||
* 默认请求配置
|
|
||||||
*/
|
|
||||||
defaults: AxiosRequestConfig;
|
|
||||||
|
|
||||||
middleware = new MiddlewareManager();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送请求
|
|
||||||
*/
|
|
||||||
request!: AxiosDomainRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 options 请求
|
|
||||||
*/
|
|
||||||
options!: AxiosDomainRequestMethod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 get 请求
|
|
||||||
*/
|
|
||||||
get!: AxiosDomainRequestMethodWithParams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 head 请求
|
|
||||||
*/
|
|
||||||
head!: AxiosDomainRequestMethodWithParams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 post 请求
|
|
||||||
*/
|
|
||||||
post!: AxiosDomainRequestMethodWithData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 put 请求
|
|
||||||
*/
|
|
||||||
put!: AxiosDomainRequestMethodWithData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 patch 请求
|
|
||||||
*/
|
|
||||||
patch!: AxiosDomainRequestMethodWithData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 delete 请求
|
|
||||||
*/
|
|
||||||
delete!: AxiosDomainRequestMethodWithParams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 trace 请求
|
|
||||||
*/
|
|
||||||
trace!: AxiosDomainRequestMethod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 connect 请求
|
|
||||||
*/
|
|
||||||
connect!: AxiosDomainRequestMethod;
|
|
||||||
|
|
||||||
flush: MiddlewareFlush;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
defaults: AxiosRequestConfig,
|
|
||||||
processRequest: (
|
|
||||||
config: AxiosRequestConfig,
|
|
||||||
requestHandler: AxiosDomainRequestHandler,
|
|
||||||
) => Promise<AxiosResponse>,
|
|
||||||
) {
|
|
||||||
this.defaults = defaults;
|
|
||||||
|
|
||||||
this.request = (
|
|
||||||
urlOrConfig: string | AxiosRequestConfig,
|
|
||||||
config: AxiosRequestConfig = {},
|
|
||||||
) => {
|
|
||||||
if (isString(urlOrConfig)) {
|
|
||||||
config.url = urlOrConfig;
|
|
||||||
} else {
|
|
||||||
config = urlOrConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUndefined(config.method)) {
|
|
||||||
config.method = 'get';
|
|
||||||
}
|
|
||||||
|
|
||||||
return processRequest(
|
|
||||||
mergeConfig(this.defaults, config),
|
|
||||||
this.#requestHandler,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
this.flush = this.middleware.wrap(async (ctx) => {
|
|
||||||
ctx.res = await dispatchRequest(ctx.req);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#requestHandler: AxiosDomainRequestHandler = async (config) => {
|
|
||||||
config.url = combineURL(config.baseURL, config.url);
|
|
||||||
const ctx: MiddlewareContext = {
|
|
||||||
req: config,
|
|
||||||
res: null,
|
|
||||||
};
|
|
||||||
await this.flush(ctx);
|
|
||||||
return ctx.res as AxiosResponse;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const method of PLAIN_METHODS) {
|
|
||||||
AxiosDomain.prototype[method] = function processRequestMethod(
|
|
||||||
url,
|
|
||||||
config = {},
|
|
||||||
) {
|
|
||||||
config.method = method;
|
|
||||||
return this.request(url, config);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const method of WITH_PARAMS_METHODS) {
|
|
||||||
AxiosDomain.prototype[method] = function processRequestMethodWithParams(
|
|
||||||
url,
|
|
||||||
params = {},
|
|
||||||
config = {},
|
|
||||||
) {
|
|
||||||
config.method = method;
|
|
||||||
config.params = deepMerge(params, config.params ?? {});
|
|
||||||
return this.request(url, config);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const method of WITH_DATA_METHODS) {
|
|
||||||
AxiosDomain.prototype[method] = function processRequestMethodWithData(
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
config = {},
|
|
||||||
) {
|
|
||||||
config.method = method;
|
|
||||||
config.data = data;
|
|
||||||
return this.request(url, config);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,36 +1,44 @@
|
||||||
import { assert } from '../helpers/error';
|
import { assert } from '../helpers/error';
|
||||||
import { combineURL } from '../helpers/combineURL';
|
import { combineURL } from '../helpers/combineURL';
|
||||||
import { isFunction } from '../helpers/isTypes';
|
import { isFunction, isString } from '../helpers/isTypes';
|
||||||
import { AxiosRequestConfig, AxiosResponse } from './Axios';
|
|
||||||
|
|
||||||
export interface MiddlewareContext {
|
|
||||||
req: AxiosRequestConfig;
|
|
||||||
res: null | AxiosResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MiddlewareNext {
|
export interface MiddlewareNext {
|
||||||
(): Promise<void>;
|
(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MiddlewareCallback {
|
export interface MiddlewareCallback<Conext extends AnyObject> {
|
||||||
(ctx: MiddlewareContext, next: MiddlewareNext): Promise<void>;
|
(ctx: Conext, next: MiddlewareNext): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MiddlewareFlush {
|
export interface MiddlewareFlush<Conext extends AnyObject> {
|
||||||
(ctx: MiddlewareContext): Promise<void>;
|
(ctx: Conext): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class MiddlewareManager {
|
export default class MiddlewareManager<Conext extends AnyObject = AnyObject> {
|
||||||
#map = new Map<string, MiddlewareCallback[]>();
|
#map = new Map<string, MiddlewareCallback<Conext>[]>();
|
||||||
|
|
||||||
use(callback: MiddlewareCallback): MiddlewareManager;
|
flush: MiddlewareFlush<Conext>;
|
||||||
use(path: string, callback: MiddlewareCallback): MiddlewareManager;
|
|
||||||
use(path: string | MiddlewareCallback, callback?: MiddlewareCallback) {
|
constructor(flush: MiddlewareFlush<Conext>) {
|
||||||
|
this.flush = this.wrap(flush);
|
||||||
|
}
|
||||||
|
|
||||||
|
use(callback: MiddlewareCallback<Conext>): MiddlewareManager<Conext>;
|
||||||
|
use(
|
||||||
|
path: string,
|
||||||
|
callback: MiddlewareCallback<Conext>,
|
||||||
|
): MiddlewareManager<Conext>;
|
||||||
|
use(
|
||||||
|
path: string | MiddlewareCallback<Conext>,
|
||||||
|
callback?: MiddlewareCallback<Conext>,
|
||||||
|
) {
|
||||||
if (isFunction(path)) {
|
if (isFunction(path)) {
|
||||||
callback = path;
|
callback = path;
|
||||||
path = '/';
|
path = '/';
|
||||||
}
|
}
|
||||||
assert(!!path, 'path 不是一个非空的 string');
|
assert(isString(path), 'path 不是一个 string');
|
||||||
|
assert(!!path, 'path 不是一个长度大于零的 string');
|
||||||
|
assert(isFunction(callback), 'callback 不是一个 function');
|
||||||
|
|
||||||
const middlewares = this.#map.get(path) ?? [];
|
const middlewares = this.#map.get(path) ?? [];
|
||||||
middlewares.push(callback!);
|
middlewares.push(callback!);
|
||||||
|
@ -39,32 +47,25 @@ export default class MiddlewareManager {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap(flush: MiddlewareFlush): MiddlewareFlush {
|
wrap(flush: MiddlewareFlush<Conext>): MiddlewareFlush<Conext> {
|
||||||
return (ctx) => this.#performer(ctx, flush);
|
return (ctx) => {
|
||||||
}
|
const allMiddlewares: MiddlewareCallback<Conext>[] = [];
|
||||||
|
|
||||||
#performer(ctx: MiddlewareContext, flush: MiddlewareFlush) {
|
for (const [path, middlewares] of this.#map.entries()) {
|
||||||
const middlewares = [...this.#getAllMiddlewares(ctx), flush];
|
const url = combineURL(ctx.req.baseURL, path);
|
||||||
|
const checkRE = new RegExp(`^${url}([/?].*)?`);
|
||||||
|
|
||||||
function next(): Promise<void> {
|
if (path === '/') {
|
||||||
return middlewares.shift()!(ctx, next);
|
allMiddlewares.push(...middlewares);
|
||||||
}
|
} else if (checkRE.test(ctx.req.url!)) {
|
||||||
|
allMiddlewares.push(...middlewares);
|
||||||
return next();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#getAllMiddlewares(ctx: MiddlewareContext) {
|
|
||||||
const allMiddlewares: MiddlewareCallback[] = [];
|
|
||||||
|
|
||||||
for (const [path, middlewares] of this.#map.entries()) {
|
|
||||||
const url = combineURL(ctx.req.baseURL, path);
|
|
||||||
|
|
||||||
const checkRE = new RegExp(`^${url}([/?].*)?`);
|
|
||||||
if (checkRE.test(ctx.req.url!)) {
|
|
||||||
allMiddlewares.push(...middlewares);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return allMiddlewares;
|
const tasks = [...allMiddlewares, flush];
|
||||||
|
return (function next(): Promise<void> {
|
||||||
|
return tasks.shift()!(ctx, next);
|
||||||
|
})();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { combineURL } from '../helpers/combineURL';
|
||||||
|
import { buildURL } from '../helpers/buildURL';
|
||||||
|
import Axios, {
|
||||||
|
AxiosRequest,
|
||||||
|
AxiosRequestConfig,
|
||||||
|
AxiosRequestHeaders,
|
||||||
|
} from './Axios';
|
||||||
|
import { mergeConfig } from './mergeConfig';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* axios 实例默认配置
|
||||||
|
*/
|
||||||
|
export interface AxiosInstanceDefaults extends AxiosRequestConfig {
|
||||||
|
/**
|
||||||
|
* 请求头
|
||||||
|
*/
|
||||||
|
headers: Required<AxiosRequestHeaders>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* axios 实例
|
||||||
|
*/
|
||||||
|
export interface AxiosInstance extends AxiosRequest, Axios {
|
||||||
|
/**
|
||||||
|
* 默认请求配置
|
||||||
|
*/
|
||||||
|
defaults: AxiosInstanceDefaults;
|
||||||
|
/**
|
||||||
|
* 获取 URI
|
||||||
|
*
|
||||||
|
* @param config 默认配置
|
||||||
|
*/
|
||||||
|
getUri(config: AxiosRequestConfig): string;
|
||||||
|
/**
|
||||||
|
* 派生领域
|
||||||
|
*
|
||||||
|
* @param config 默认配置
|
||||||
|
*/
|
||||||
|
fork(config: AxiosRequestConfig): AxiosInstance;
|
||||||
|
/**
|
||||||
|
* 扩展实例
|
||||||
|
*
|
||||||
|
* @param config 默认配置
|
||||||
|
*/
|
||||||
|
extend(config: AxiosRequestConfig): AxiosInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createInstance(config: AxiosRequestConfig, parent?: Axios) {
|
||||||
|
const context = new Axios(config, parent);
|
||||||
|
const instance = context.request as AxiosInstance;
|
||||||
|
|
||||||
|
instance.getUri = function getUri(config: AxiosRequestConfig) {
|
||||||
|
const { url, params, paramsSerializer } = mergeConfig(
|
||||||
|
instance.defaults,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
return buildURL(url, params, paramsSerializer).replace(/^\?/, '');
|
||||||
|
};
|
||||||
|
instance.extend = function extend(config: AxiosRequestConfig = {}) {
|
||||||
|
config.url = combineURL(instance.defaults.baseURL, config.url);
|
||||||
|
return createInstance(mergeConfig(instance.defaults, config), context);
|
||||||
|
};
|
||||||
|
instance.fork = instance.extend;
|
||||||
|
|
||||||
|
Object.assign(instance, context);
|
||||||
|
Object.setPrototypeOf(instance, Axios.prototype);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { getDefaultAdapter } from './adpater/getDefaultAdapter';
|
import { getDefaultAdapter } from './adpater/getDefaultAdapter';
|
||||||
import { AxiosInstanceDefaults } from './axios';
|
import { AxiosInstanceDefaults } from './core/createInstance';
|
||||||
|
|
||||||
const defaults: AxiosInstanceDefaults = {
|
const defaults: AxiosInstanceDefaults = {
|
||||||
// 适配器,在支持的平台中有值。
|
// 适配器,在支持的平台中有值。
|
||||||
|
|
11
src/index.ts
11
src/index.ts
|
@ -15,10 +15,13 @@ export type {
|
||||||
AxiosUploadProgressCallback,
|
AxiosUploadProgressCallback,
|
||||||
} from './core/Axios';
|
} from './core/Axios';
|
||||||
export type {
|
export type {
|
||||||
MiddlewareContext,
|
|
||||||
MiddlewareCallback,
|
MiddlewareCallback,
|
||||||
MiddlewareNext,
|
MiddlewareNext,
|
||||||
} from './core/MiddlewareManager';
|
} from './core/MiddlewareManager';
|
||||||
|
export type {
|
||||||
|
AxiosInstanceDefaults,
|
||||||
|
AxiosInstance,
|
||||||
|
} from './core/createInstance';
|
||||||
export type {
|
export type {
|
||||||
AxiosAdapter,
|
AxiosAdapter,
|
||||||
AxiosAdapterRequestConfig,
|
AxiosAdapterRequestConfig,
|
||||||
|
@ -35,11 +38,7 @@ export type {
|
||||||
AxiosAdapterPlatform,
|
AxiosAdapterPlatform,
|
||||||
AxiosAdapterPlatformTask,
|
AxiosAdapterPlatformTask,
|
||||||
} from './adpater/createAdapter';
|
} from './adpater/createAdapter';
|
||||||
export type {
|
export type { AxiosStatic } from './axios';
|
||||||
AxiosInstanceDefaults,
|
|
||||||
AxiosInstance,
|
|
||||||
AxiosStatic,
|
|
||||||
} from './axios';
|
|
||||||
|
|
||||||
export { CancelToken, isCancel } from './request/cancel';
|
export { CancelToken, isCancel } from './request/cancel';
|
||||||
export { isAxiosError } from './request/createError';
|
export { isAxiosError } from './request/createError';
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { describe, test, expect, vi, afterEach } from 'vitest';
|
import { describe, test, expect, vi } from 'vitest';
|
||||||
import { mockAdapter, testEachMethods } from 'scripts/test.utils';
|
import { mockAdapter, testEachMethods } from 'scripts/test.utils';
|
||||||
import {
|
import {
|
||||||
PLAIN_METHODS,
|
PLAIN_METHODS,
|
||||||
WITH_DATA_METHODS,
|
WITH_DATA_METHODS,
|
||||||
WITH_PARAMS_METHODS,
|
WITH_PARAMS_METHODS,
|
||||||
} from '@/constants/methods';
|
} from '@/constants/methods';
|
||||||
import AxiosDomain from '@/core/AxiosDomain';
|
|
||||||
import defaults from '@/defaults';
|
import defaults from '@/defaults';
|
||||||
import axios from '@/axios';
|
import axios from '@/axios';
|
||||||
|
|
||||||
|
@ -163,8 +162,4 @@ describe('src/axios.ts', () => {
|
||||||
'test?id=1',
|
'test?id=1',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('派生的领域应该为 AxiosDomain 的实例', () => {
|
|
||||||
expect(axios.fork() instanceof AxiosDomain).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
WITH_DATA_METHODS,
|
WITH_DATA_METHODS,
|
||||||
WITH_PARAMS_METHODS,
|
WITH_PARAMS_METHODS,
|
||||||
} from '@/constants/methods';
|
} from '@/constants/methods';
|
||||||
import AxiosDomain from '@/core/AxiosDomain';
|
|
||||||
import Axios from '@/core/Axios';
|
import Axios from '@/core/Axios';
|
||||||
import axios from '@/axios';
|
import axios from '@/axios';
|
||||||
|
|
||||||
|
@ -22,10 +21,6 @@ describe('src/core/Axios.ts', () => {
|
||||||
baseURL: 'http://api.com',
|
baseURL: 'http://api.com',
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该继承自 AxiosDomain', () => {
|
|
||||||
expect(new Axios() instanceof AxiosDomain).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该有这些实例属性及方法', () => {
|
test('应该有这些实例属性及方法', () => {
|
||||||
const c = {
|
const c = {
|
||||||
baseURL: 'http://api.com',
|
baseURL: 'http://api.com',
|
||||||
|
@ -34,8 +29,6 @@ describe('src/core/Axios.ts', () => {
|
||||||
expect(axiosObj.defaults).toEqual(c);
|
expect(axiosObj.defaults).toEqual(c);
|
||||||
expect(axiosObj.interceptors).toBeTypeOf('object');
|
expect(axiosObj.interceptors).toBeTypeOf('object');
|
||||||
expect(axiosObj.request).toBeTypeOf('function');
|
expect(axiosObj.request).toBeTypeOf('function');
|
||||||
expect(axiosObj.getUri).toBeTypeOf('function');
|
|
||||||
expect(axiosObj.fork).toBeTypeOf('function');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testEachMethods('%s 应该是一个函数', (k) => {
|
testEachMethods('%s 应该是一个函数', (k) => {
|
||||||
|
@ -354,45 +347,4 @@ describe('src/core/Axios.ts', () => {
|
||||||
expect(res2).not.toBeCalled();
|
expect(res2).not.toBeCalled();
|
||||||
expect(rej2).toBeCalled();
|
expect(rej2).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以获取 URI', () => {
|
|
||||||
expect(axiosObj.getUri({ url: 'test' })).toBe('test');
|
|
||||||
expect(axiosObj.getUri({ url: 'test', params: { id: 1 } })).toBe(
|
|
||||||
'test?id=1',
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
axiosObj.getUri({ url: 'test', paramsSerializer: () => 'id=1' }),
|
|
||||||
).toBe('test?id=1');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('派生的领域应该为 AxiosDomain 的实例', () => {
|
|
||||||
expect(axiosObj.fork() instanceof AxiosDomain).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该支持 绝对路径/相对路径 派生领域', () => {
|
|
||||||
const a1 = axiosObj.fork({ baseURL: 'test' });
|
|
||||||
const a2 = new Axios().fork({ baseURL: 'test' });
|
|
||||||
const a3 = axiosObj.fork({ baseURL: 'https://api.com' });
|
|
||||||
const a4 = axiosObj.fork();
|
|
||||||
|
|
||||||
expect(a1.defaults.baseURL).toBe('http://api.com/test');
|
|
||||||
expect(a2.defaults.baseURL).toBe('/test');
|
|
||||||
expect(a3.defaults.baseURL).toBe('https://api.com');
|
|
||||||
expect(a4.defaults.baseURL).toBe('http://api.com');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('派生自当前实例的领域应该可以复用当前实例的拦截器', async () => {
|
|
||||||
const axiosObj = new Axios();
|
|
||||||
const req = vi.fn((v) => v);
|
|
||||||
const res = vi.fn((v) => v);
|
|
||||||
|
|
||||||
axiosObj.interceptors.request.use(req);
|
|
||||||
axiosObj.interceptors.response.use(res);
|
|
||||||
|
|
||||||
const a = axiosObj.fork({ baseURL: 'test' });
|
|
||||||
await a.request('test', { adapter: mockAdapter() });
|
|
||||||
|
|
||||||
expect(req).toBeCalled();
|
|
||||||
expect(res).toBeCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
import { describe, test, expect, vi } from 'vitest';
|
|
||||||
import { ignore } from '@/helpers/ignore';
|
|
||||||
import {
|
|
||||||
PLAIN_METHODS,
|
|
||||||
WITH_DATA_METHODS,
|
|
||||||
WITH_PARAMS_METHODS,
|
|
||||||
} from '@/constants/methods';
|
|
||||||
import AxiosDomain from '@/core/AxiosDomain';
|
|
||||||
import { AxiosResponse } from '@/core/Axios';
|
|
||||||
import { eachMethods } from 'scripts/test.utils';
|
|
||||||
|
|
||||||
describe('src/core/AxiosDomain.ts', () => {
|
|
||||||
test('应该有这些实例属性', () => {
|
|
||||||
const c = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const a = new AxiosDomain(c, vi.fn());
|
|
||||||
|
|
||||||
expect(a.defaults).toEqual(c);
|
|
||||||
expect(a.request).toBeTypeOf('function');
|
|
||||||
|
|
||||||
eachMethods((k) => {
|
|
||||||
expect(a[k]).toBeTypeOf('function');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('发送请求时 processRequest 应该被调用', () => {
|
|
||||||
const p = vi.fn();
|
|
||||||
const d = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const c = {
|
|
||||||
url: 'test',
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
new AxiosDomain(d, p).request(c);
|
|
||||||
|
|
||||||
expect(p).toBeCalled();
|
|
||||||
expect(p.mock.calls[0][0]).toEqual({
|
|
||||||
...d,
|
|
||||||
...c,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('请求方法应该支持空参数', () => {
|
|
||||||
const cb = vi.fn();
|
|
||||||
const a = new AxiosDomain({}, cb);
|
|
||||||
|
|
||||||
a.request('test');
|
|
||||||
|
|
||||||
PLAIN_METHODS.forEach((k) => a[k]('test'));
|
|
||||||
WITH_PARAMS_METHODS.forEach((k) => a[k]('test'));
|
|
||||||
WITH_DATA_METHODS.forEach((k) => a[k]('test'));
|
|
||||||
|
|
||||||
const l =
|
|
||||||
PLAIN_METHODS.length +
|
|
||||||
WITH_PARAMS_METHODS.length +
|
|
||||||
WITH_DATA_METHODS.length +
|
|
||||||
1;
|
|
||||||
expect(cb.mock.calls.length).toBe(l);
|
|
||||||
cb.mock.calls.forEach(([config]) => expect(config.url).toBe('test'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该可以调用请求方法', () => {
|
|
||||||
const cb = vi.fn();
|
|
||||||
const d = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const u = 'test';
|
|
||||||
const c = {
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const a = new AxiosDomain(d, async (config) => {
|
|
||||||
cb();
|
|
||||||
|
|
||||||
expect(config.baseURL).toBe(d.baseURL);
|
|
||||||
expect(config.url).toBe(u);
|
|
||||||
expect(config.params).toEqual(c.params);
|
|
||||||
expect(config.data).toEqual(c.data);
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
a.request(u, c);
|
|
||||||
|
|
||||||
PLAIN_METHODS.forEach((k) => a[k](u, c));
|
|
||||||
WITH_PARAMS_METHODS.forEach((k) => a[k](u, c.params, ignore(c, 'params')));
|
|
||||||
WITH_DATA_METHODS.forEach((k) => a[k](u, c.data, ignore(c, 'data')));
|
|
||||||
|
|
||||||
const l =
|
|
||||||
PLAIN_METHODS.length +
|
|
||||||
WITH_PARAMS_METHODS.length +
|
|
||||||
WITH_DATA_METHODS.length +
|
|
||||||
1;
|
|
||||||
expect(cb.mock.calls.length).toBe(l);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该可以直接传递 config 调用请求方法', () => {
|
|
||||||
const cb = vi.fn();
|
|
||||||
const d = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const c = {
|
|
||||||
url: 'test',
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const a = new AxiosDomain(d, async (config) => {
|
|
||||||
cb();
|
|
||||||
|
|
||||||
expect(config.baseURL).toBe(d.baseURL);
|
|
||||||
expect(config.url).toBe(c.url);
|
|
||||||
expect(config.params).toEqual(c.params);
|
|
||||||
expect(config.data).toEqual(c.data);
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
a.request(c);
|
|
||||||
|
|
||||||
PLAIN_METHODS.forEach((k) => a[k](c.url, ignore(c, 'url')));
|
|
||||||
WITH_PARAMS_METHODS.forEach((k) =>
|
|
||||||
a[k](c.url, c.params, ignore(c, 'url', 'params')),
|
|
||||||
);
|
|
||||||
WITH_DATA_METHODS.forEach((k) =>
|
|
||||||
a[k](c.url, c.data, ignore(c, 'url', 'data')),
|
|
||||||
);
|
|
||||||
|
|
||||||
const l =
|
|
||||||
PLAIN_METHODS.length +
|
|
||||||
WITH_PARAMS_METHODS.length +
|
|
||||||
WITH_DATA_METHODS.length +
|
|
||||||
1;
|
|
||||||
expect(cb.mock.calls.length).toBe(l);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该支持深度合并 params', () => {
|
|
||||||
const d = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const p = {
|
|
||||||
v1: 1,
|
|
||||||
v2: {
|
|
||||||
v1: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const c = {
|
|
||||||
params: {
|
|
||||||
v2: {
|
|
||||||
v2: 2,
|
|
||||||
},
|
|
||||||
v3: 3,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const a = new AxiosDomain(d, async (config) => {
|
|
||||||
expect(config.params).toEqual({
|
|
||||||
v1: 1,
|
|
||||||
v2: {
|
|
||||||
v1: 1,
|
|
||||||
v2: 2,
|
|
||||||
},
|
|
||||||
v3: 3,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
WITH_PARAMS_METHODS.forEach((k) => a[k]('test', p, c));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该只取传入的 data', () => {
|
|
||||||
const ds = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
const d = {
|
|
||||||
v: 1,
|
|
||||||
};
|
|
||||||
const c = {
|
|
||||||
v: 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
const a = new AxiosDomain(ds, async (config) => {
|
|
||||||
expect(config.data).toEqual({
|
|
||||||
v: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
WITH_DATA_METHODS.forEach((k) => a[k]('test', d, c));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('应该支持多种类型 data', () => {
|
|
||||||
const ds = {
|
|
||||||
baseURL: 'http://api.com',
|
|
||||||
};
|
|
||||||
|
|
||||||
const str = '11';
|
|
||||||
const obj = {};
|
|
||||||
const buff = new ArrayBuffer(0);
|
|
||||||
|
|
||||||
const testStr = new AxiosDomain(ds, async (config) => {
|
|
||||||
expect(config.data).toBe(str);
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
const testObj = new AxiosDomain(ds, async (config) => {
|
|
||||||
expect(config.data).toBe(obj);
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
const testBuff = new AxiosDomain(ds, async (config) => {
|
|
||||||
expect(config.data).toBe(buff);
|
|
||||||
|
|
||||||
return {} as AxiosResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
WITH_DATA_METHODS.forEach((k) => {
|
|
||||||
testStr[k]('test', str);
|
|
||||||
testObj[k]('test', obj);
|
|
||||||
testBuff[k]('test', buff);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -3,14 +3,18 @@ import MiddlewareManager from '@/core/MiddlewareManager';
|
||||||
|
|
||||||
describe('src/core/MiddlewareManager.ts', () => {
|
describe('src/core/MiddlewareManager.ts', () => {
|
||||||
test('应该有这些实例属性', () => {
|
test('应该有这些实例属性', () => {
|
||||||
const m = new MiddlewareManager();
|
const m = new MiddlewareManager(vi.fn());
|
||||||
|
|
||||||
expect(m.use).toBeTypeOf('function');
|
expect(m.use).toBeTypeOf('function');
|
||||||
expect(m.wrap).toBeTypeOf('function');
|
expect(m.wrap).toBeTypeOf('function');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以添加中间件回调', async () => {
|
test('应该可以添加中间件回调', async () => {
|
||||||
const m = new MiddlewareManager();
|
const flush = vi.fn(async (ctx) => {
|
||||||
|
expect(ctx.req.url).toBe('test');
|
||||||
|
ctx.res = res;
|
||||||
|
});
|
||||||
|
const m = new MiddlewareManager(flush);
|
||||||
const ctx = {
|
const ctx = {
|
||||||
req: { url: 'https://api.com' },
|
req: { url: 'https://api.com' },
|
||||||
res: null,
|
res: null,
|
||||||
|
@ -24,20 +28,20 @@ describe('src/core/MiddlewareManager.ts', () => {
|
||||||
await next();
|
await next();
|
||||||
expect(ctx.res).toBe(res);
|
expect(ctx.res).toBe(res);
|
||||||
});
|
});
|
||||||
const flush = vi.fn(async (ctx) => {
|
|
||||||
expect(ctx.req.url).toBe('test');
|
|
||||||
ctx.res = res;
|
|
||||||
});
|
|
||||||
|
|
||||||
m.use(midde);
|
m.use(midde);
|
||||||
await m.wrap(flush)(ctx);
|
await m.flush(ctx);
|
||||||
|
|
||||||
expect(ctx.res).toBe(res);
|
expect(ctx.res).toBe(res);
|
||||||
expect(midde).toBeCalled();
|
expect(midde).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以给路径添加中间件回调', async () => {
|
test('应该可以给路径添加中间件回调', async () => {
|
||||||
const m = new MiddlewareManager();
|
const flush = vi.fn(async (ctx) => {
|
||||||
|
ctx.res = res;
|
||||||
|
});
|
||||||
|
|
||||||
|
const m = new MiddlewareManager(flush);
|
||||||
const ctx1 = {
|
const ctx1 = {
|
||||||
req: {
|
req: {
|
||||||
baseURL: 'https://api.com',
|
baseURL: 'https://api.com',
|
||||||
|
@ -60,18 +64,15 @@ describe('src/core/MiddlewareManager.ts', () => {
|
||||||
await next();
|
await next();
|
||||||
expect(ctx.res).toBe(res);
|
expect(ctx.res).toBe(res);
|
||||||
});
|
});
|
||||||
const flush = vi.fn(async (ctx) => {
|
|
||||||
ctx.res = res;
|
|
||||||
});
|
|
||||||
|
|
||||||
m.use('/test', midde);
|
m.use('/test', midde);
|
||||||
await m.wrap(flush)(ctx1);
|
await m.flush(ctx1);
|
||||||
|
|
||||||
expect(ctx1.res).toBe(res);
|
expect(ctx1.res).toBe(res);
|
||||||
expect(midde).not.toBeCalled();
|
expect(midde).not.toBeCalled();
|
||||||
|
|
||||||
m.use('/test', midde);
|
m.use('/test', midde);
|
||||||
await m.wrap(flush)(ctx2);
|
await m.flush(ctx2);
|
||||||
|
|
||||||
expect(midde).toBeCalled();
|
expect(midde).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue