refactor(GOV-010): 统一封装前端 Axios 请求
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ApiRequestError, createApiClient } from './client';
|
||||
|
||||
describe('OpenAPI 请求客户端', () => {
|
||||
it('使用调用方提供的 API 根地址请求公开路径', async () => {
|
||||
let requestedUrl = '';
|
||||
const client = createApiClient('http://127.0.0.1:3000', async (request) => {
|
||||
requestedUrl = request.url;
|
||||
return Response.json({
|
||||
status: 'healthy',
|
||||
process: 'api',
|
||||
checkedAt: '2026-08-13T09:30:00.000Z',
|
||||
dependencies: {
|
||||
mysql: { status: 'healthy', detail: 'ready' },
|
||||
redis: { status: 'healthy', detail: 'ready' },
|
||||
rocketMq: { status: 'disabled', detail: 'disabled' },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
await client.GET('/api/v1/health');
|
||||
|
||||
expect(requestedUrl).toBe('http://127.0.0.1:3000/api/v1/health');
|
||||
});
|
||||
|
||||
it('把网络错误归一化为不泄漏底层连接信息的错误', async () => {
|
||||
const client = createApiClient('http://127.0.0.1:3000', async () => {
|
||||
throw new Error('connect ECONNREFUSED mysql://root:secret@internal');
|
||||
});
|
||||
|
||||
await expect(client.GET('/api/v1/health')).rejects.toEqual(
|
||||
expect.objectContaining({
|
||||
name: 'ApiRequestError',
|
||||
message: 'API 请求失败,请稍后重试',
|
||||
}),
|
||||
);
|
||||
await expect(client.GET('/api/v1/health')).rejects.toBeInstanceOf(ApiRequestError);
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import createClient, { type Client } from 'openapi-fetch';
|
||||
import type { paths } from './generated/schema';
|
||||
|
||||
/** 统一的安全请求错误,不把浏览器或代理底层异常直接展示给用户。 */
|
||||
export class ApiRequestError extends Error {
|
||||
constructor() {
|
||||
super('API 请求失败,请稍后重试');
|
||||
this.name = 'ApiRequestError';
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建受 OpenAPI paths 约束的客户端,并在边界统一清洗网络异常。 */
|
||||
export function createApiClient(
|
||||
baseUrl: string,
|
||||
fetchImplementation: (request: Request) => Promise<Response> = globalThis.fetch,
|
||||
): Client<paths> {
|
||||
const client = createClient<paths>({
|
||||
baseUrl: baseUrl.replace(/\/$/, ''),
|
||||
fetch: fetchImplementation,
|
||||
});
|
||||
|
||||
client.use({
|
||||
onError() {
|
||||
// 浏览器错误可能带出内网主机、代理或底层连接细节,统一转换为安全的用户提示。
|
||||
return new ApiRequestError();
|
||||
},
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
Reference in New Issue
Block a user