feat(接口调试): 本地执行

This commit is contained in:
baiqi 2024-02-27 16:52:17 +08:00 committed by Craftsman
parent 558dbcfff6
commit a74f9cc9e6
10 changed files with 69 additions and 26 deletions

View File

@ -9,6 +9,7 @@ import {
GetApiDebugDetailUrl,
GetDebugModuleCountUrl,
GetDebugModulesUrl,
LocalExecuteApiDebugUrl,
MoveDebugModuleUrl,
TestMockUrl,
UpdateApiDebugUrl,
@ -66,6 +67,11 @@ export function executeDebug(data: ExecuteRequestParams) {
return MSR.post<ExecuteRequestParams>({ url: ExecuteApiDebugUrl, data });
}
// 本地执行调试
export function localExecuteApiDebug(host: string, data: ExecuteRequestParams) {
return MSR.post<ExecuteRequestParams>({ url: `${host}${LocalExecuteApiDebugUrl}`, data });
}
// 新增调试
export function addDebug(data: SaveDebugParams) {
return MSR.post({ url: AddApiDebugUrl, data });

View File

@ -74,15 +74,15 @@ export function testCommonScript(data: TestScriptType) {
return MSR.post({ url: TestScriptUrl, data });
}
// apiSocket 建立连接
export const apiSocket = (url: string) => {
export const apiSocket = (url: string, host?: string) => {
let protocol = 'ws://';
if (window.location.protocol === 'https:') {
if (window.location.protocol === 'https:' || host?.startsWith('https')) {
protocol = 'wss://';
}
const uri = protocol + window.location.host + url;
const uri = protocol + (host?.split('://')[1] || window.location.host) + url;
return new WebSocket(uri);
};
export function getSocket(reportId: string) {
return apiSocket(`${ConnectionWebsocketUrl}/${reportId}`);
export function getSocket(reportId: string, socketUrl?: string, host?: string) {
return apiSocket(`${socketUrl || ConnectionWebsocketUrl}/${reportId}`, host);
}

View File

@ -85,8 +85,8 @@ export function addLocalConfig(data: AddLocalConfigParams) {
}
// 个人设置-验证本地执行配置
export function validLocalConfig(id: string) {
return MSR.get<boolean>({ url: ValidLocalConfigUrl, params: id });
export function validLocalConfig(host: string) {
return MSR.get({ url: `${host}${ValidLocalConfigUrl}` });
}
// 个人设置-获取本地执行配置

View File

@ -1,4 +1,5 @@
export const ExecuteApiDebugUrl = '/api/debug/debug'; // 执行调试
export const LocalExecuteApiDebugUrl = '/api/debug'; // 本地执行调试
export const AddApiDebugUrl = '/api/debug/add'; // 新增调试
export const UpdateApiDebugUrl = '/api/debug/update'; // 更新调试
export const GetApiDebugDetailUrl = '/api/debug/get'; // 获取接口调试详情

View File

@ -7,7 +7,7 @@ export const GetMenuListUrl = '/api/user/menu';
export const GetPublicKeyUrl = '/get-key';
export const UpdateLocalConfigUrl = '/user/local/config/update'; // 个人设置-更新本地执行配置
export const AddLocalConfigUrl = '/user/local/config/add'; // 个人设置-添加本地执行
export const ValidLocalConfigUrl = '/user/local/config/validate'; // 个人设置-验证本地执行
export const ValidLocalConfigUrl = '/status'; // 个人设置-验证本地执行
export const GetLocalConfigUrl = '/user/local/config/get'; // 个人设置-获取本地执行配置
export const EnableLocalConfigUrl = '/user/local/config/enable'; // 个人设置-启用本地执行配置
export const DisableLocalConfigUrl = '/user/local/config/disable'; // 个人设置-禁用本地执行配置

View File

@ -49,7 +49,8 @@
</div>
</div>
</div>
<div v-xpack class="config-card">
<!-- TODO:UI 测试暂无 -->
<!-- <div v-xpack class="config-card">
<div class="config-card-title">
<div class="config-card-title-text">{{ t('ms.personal.uiLocalExecution') }}</div>
<MsTag
@ -93,7 +94,7 @@
/>
</div>
</div>
</div>
</div> -->
</div>
</a-spin>
</template>
@ -155,10 +156,13 @@
});
async function testApi() {
if (apiConfig.value.userUrl.trim() === '') {
return;
}
try {
testApiLoading.value = true;
const res = await validLocalConfig(apiConfig.value.id);
apiConfig.value.status = res ? 1 : 2;
const res = await validLocalConfig(apiConfig.value.userUrl.trim());
apiConfig.value.status = res === 'OK' ? 1 : 2;
if (res) {
//
if (apiConfig.value.id) {
@ -212,6 +216,9 @@
});
async function testUi() {
if (uiConfig.value.userUrl.trim() === '') {
return;
}
try {
testUiLoading.value = true;
if (uiConfig.value.id) {
@ -227,8 +234,8 @@
});
uiConfig.value.id = result.id;
}
const res = await validLocalConfig(uiConfig.value.id);
uiConfig.value.status = res ? 1 : 2;
const res = await validLocalConfig(uiConfig.value.userUrl.trim());
uiConfig.value.status = res === 'OK' ? 1 : 2;
if (res) {
Message.success(t('ms.personal.testPass'));
} else {

View File

@ -317,6 +317,7 @@ export interface ExecuteRequestParams {
linkFileIds: string[];
request: ExecuteHTTPRequestFullParams | ExecutePluginRequestParams;
projectId: string;
frontendDebug?: boolean; // 是否本地调试,该模式下接口会返回执行参数,用来调用本地执行服务
}
// 保存接口调试入参
export interface SaveDebugParams {

View File

@ -54,7 +54,7 @@
v-if="!requestVModel.executeLoading"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
class="exec-btn"
@click="execute"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
@select="execute"
>
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
@ -62,7 +62,7 @@
<icon-down />
</template>
<template v-if="hasLocalExec" #content>
<a-doption :value="isPriorityLocalExec ? 'localExec' : 'serverExec'">
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
</template>
@ -325,6 +325,7 @@
isDefinition?: boolean; //
hideResponseLayoutSwitch?: boolean; //
executeApi: (...args) => Promise<any>; //
localExecuteApi: (...args) => Promise<any>; //
createApi: (...args) => Promise<any>; //
updateApi: (...args) => Promise<any>; //
uploadTempFileApi?: (...args) => Promise<any>; //
@ -468,6 +469,7 @@
const hasLocalExec = ref(false); // api
const isPriorityLocalExec = ref(false); //
const localExecuteUrl = ref('');
async function initLocalConfig() {
try {
const res = await getLocalConfig();
@ -475,6 +477,7 @@
if (apiLocalExec) {
hasLocalExec.value = true;
isPriorityLocalExec.value = apiLocalExec.enable || false;
localExecuteUrl.value = apiLocalExec.userUrl || '';
}
} catch (error) {
// eslint-disable-next-line no-console
@ -656,8 +659,12 @@
const reportId = ref('');
const websocket = ref<WebSocket>();
function debugSocket() {
websocket.value = getSocket(reportId.value);
function debugSocket(executeType?: 'localExec' | 'serverExec') {
websocket.value = getSocket(
reportId.value,
executeType === 'localExec' ? '/ws/debug' : '',
executeType === 'localExec' ? localExecuteUrl.value : ''
);
websocket.value.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.msgType === 'EXEC_RESULT') {
@ -700,7 +707,7 @@
}
);
function makeRequestParams() {
function makeRequestParams(executeType?: 'localExec' | 'serverExec') {
const { formDataBody, wwwFormBody } = requestVModel.value.body;
const polymorphicName = protocolOptions.value.find(
(e) => e.value === requestVModel.value.protocol
@ -743,7 +750,7 @@
}
reportId.value = getGenerateId();
requestVModel.value.reportId = reportId.value; // ID
debugSocket(); // websocket
debugSocket(executeType); // websocket
return {
id: requestVModel.value.id.toString(),
reportId: reportId.value,
@ -768,6 +775,7 @@
},
...parseRequestBodyResult,
projectId: appStore.currentProjectId,
frontendDebug: executeType === 'localExec',
};
}
@ -775,12 +783,14 @@
* 执行调试
* @param val 执行类型
*/
async function execute(execuetType?: 'localExec' | 'serverExec') {
// TODO:&
async function execute(executeType?: 'localExec' | 'serverExec') {
if (isHttpProtocol.value) {
try {
requestVModel.value.executeLoading = true;
await props.executeApi(makeRequestParams());
const res = await props.executeApi(makeRequestParams(executeType));
if (executeType === 'localExec') {
await props.localExecuteApi(localExecuteUrl.value, res);
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
@ -792,7 +802,10 @@
if (valid === true) {
try {
requestVModel.value.executeLoading = true;
await props.executeApi(makeRequestParams());
const res = await props.executeApi(makeRequestParams(executeType));
if (executeType === 'localExec') {
await props.localExecuteApi(localExecuteUrl.value, res);
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);

View File

@ -38,6 +38,7 @@
:create-api="addDebug"
:update-api="updateDebug"
:execute-api="executeDebug"
:local-execute-api="localExecuteApiDebug"
:upload-temp-file-api="uploadTempFile"
@add-done="handleDebugAddDone"
/>
@ -93,7 +94,14 @@
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
import debug, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import { addDebug, executeDebug, getDebugDetail, updateDebug, uploadTempFile } from '@/api/modules/api-test/debug';
import {
addDebug,
executeDebug,
getDebugDetail,
localExecuteApiDebug,
updateDebug,
uploadTempFile,
} from '@/api/modules/api-test/debug';
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { parseCurlScript } from '@/utils';

View File

@ -24,6 +24,7 @@
:create-api="addDebug"
:update-api="updateDebug"
:execute-api="executeDebug"
:local-execute-api="localExecuteApiDebug"
is-definiton
@add-done="emit('addDone')"
/>
@ -84,7 +85,13 @@
import apiTable from './apiTable.vue';
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
import { addDebug, executeDebug, getDebugDetail, updateDebug } from '@/api/modules/api-test/debug';
import {
addDebug,
executeDebug,
getDebugDetail,
localExecuteApiDebug,
updateDebug,
} from '@/api/modules/api-test/debug';
import { useI18n } from '@/hooks/useI18n';
import { ExecuteBody } from '@/models/apiTest/debug';