You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by li...@apache.org on 2023/01/12 15:07:56 UTC
[shenyu-dashboard] branch master updated: [type: feature] Add support for ApiMockRequest Insert Update Delete. (#262)
This is an automated email from the ASF dual-hosted git repository.
likeguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new 19725cf8 [type: feature] Add support for ApiMockRequest Insert Update Delete. (#262)
19725cf8 is described below
commit 19725cf8fa32d87e9d10b52785796730c1b8132f
Author: Shawn Jim <32...@users.noreply.github.com>
AuthorDate: Thu Jan 12 23:07:50 2023 +0800
[type: feature] Add support for ApiMockRequest Insert Update Delete. (#262)
* Add support for ApiMockRequest Insert Update Delete.
* Remove unnecessary code.
---
src/locales/en-US.json | 14 +-
src/locales/zh-CN.json | 14 +-
src/routes/Document/ApiDoc.js | 13 +-
src/routes/Document/components/ApiContext.js | 3 +-
src/routes/Document/components/ApiDebug.js | 382 +++++++++++++-----------
src/routes/Document/components/HeadersEditor.js | 71 +++--
src/services/api.js | 24 ++
7 files changed, 315 insertions(+), 206 deletions(-)
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index b4a5d581..75b52a2b 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -328,5 +328,17 @@
"SHENYU.COMMON.MAX.LENGTH": "Max Length",
"SHENYU.COMMON.MAX.EXAMPLE": "Example",
"SHENYU.COMMON.MAX.ENVIRONMENT": "Environment",
- "SHENYU.COMMON.HTTP.METHOD": "HttpMethod"
+ "SHENYU.COMMON.HTTP.METHOD": "HttpMethod",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.HOST": "Host",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.PORT": "Port",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.URL": "Request Path",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.PATH_VARIABLE": "Path Variable",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.QUERY": "Query",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.HEADER": "Header",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.BODY": "Body",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.SAVE": "Save",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.RESET": "Reset",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.HEADER": "Add header",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.QUERY": "Add Query",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADDRESS.VALIDATE": "Request Address format error."
}
diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json
index 2c5c31c4..a26509a4 100644
--- a/src/locales/zh-CN.json
+++ b/src/locales/zh-CN.json
@@ -316,5 +316,17 @@
"SHENYU.COMMON.MAX.LENGTH": "最大长度",
"SHENYU.COMMON.MAX.EXAMPLE": "示例值",
"SHENYU.COMMON.MAX.ENVIRONMENT": "环境类型",
- "SHENYU.COMMON.HTTP.METHOD": "请求方法"
+ "SHENYU.COMMON.HTTP.METHOD": "请求方法",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.HOST": "请求域名或IP",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.PORT": "端口",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.URL": "路由地址",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.PATH_VARIABLE": "路由参数",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.QUERY": "请求参数",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.HEADER": "请求头",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.BODY": "请求体",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.SAVE": "保存",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.RESET": "重置",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.HEADER": "添加请求头参数",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.QUERY": "添加查询参数",
+ "SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADDRESS.VALIDATE": "请求地址格式错误."
}
diff --git a/src/routes/Document/ApiDoc.js b/src/routes/Document/ApiDoc.js
index bf2aac5c..b06b6486 100644
--- a/src/routes/Document/ApiDoc.js
+++ b/src/routes/Document/ApiDoc.js
@@ -20,12 +20,13 @@ import React, { useEffect, useState } from "react";
import SearchApi from "./components/SearchApi";
import AddAndUpdateApiDoc from "./components/AddAndUpdateApiDoc";
import ApiInfo from "./components/ApiInfo";
-import { getDocMenus, getApiDetail, addApi, updateApi, deleteApi } from "../../services/api";
+import { getDocMenus, getApiDetail, addApi, updateApi, deleteApi, getApiMockRequest} from "../../services/api";
import ApiContext from "./components/ApiContext";
function ApiDoc() {
const [apiDetail, setApiDetail] = useState({});
const [apiData, setApiData] = useState({});
+ const [apiMock, setApiMock] = useState({});
const [open, setOpen] = useState(false);
const [flag, setflag] = useState('add');
@@ -93,6 +94,13 @@ function ApiDoc() {
id
});
setApiDetail(data);
+
+ const { code: mockCode, message: mockMsg, data: mockData} = await getApiMockRequest(id);
+ if (mockCode !== 200) {
+ message.error(mockMsg);
+ return;
+ }
+ setApiMock(mockData);
};
const handleAddApi = (targetId) => {
setflag('add')
@@ -133,7 +141,8 @@ function ApiDoc() {
<ApiContext.Provider
value={{
apiDetail,
- apiData
+ apiData,
+ apiMock
}}
>
<Card style={{ margin: 24 }}>
diff --git a/src/routes/Document/components/ApiContext.js b/src/routes/Document/components/ApiContext.js
index cebaf595..58d7d19f 100644
--- a/src/routes/Document/components/ApiContext.js
+++ b/src/routes/Document/components/ApiContext.js
@@ -19,5 +19,6 @@ import { createContext } from "react";
export default createContext({
apiDetail: {},
- apiData: {}
+ apiData: {},
+ apiMock: {}
});
diff --git a/src/routes/Document/components/ApiDebug.js b/src/routes/Document/components/ApiDebug.js
index ebdc2860..bec3b219 100644
--- a/src/routes/Document/components/ApiDebug.js
+++ b/src/routes/Document/components/ApiDebug.js
@@ -15,36 +15,23 @@
* limitations under the License.
*/
-import {
- Typography,
- Form,
- Input,
- Button,
- Radio,
- Row,
- Col,
- Tree,
- Empty,
- Tabs
-} from "antd";
-import React, {
- useEffect,
- useState,
- forwardRef,
- useImperativeHandle,
- createRef,
- useContext
-} from "react";
+import {Button, Col, Empty, Form, Icon, Input, message, Row, Tabs, Typography} from "antd";
+import React, {createRef, forwardRef, useContext, useEffect, useImperativeHandle, useState} from "react";
import ReactJson from "react-json-view";
import fetch from "dva/fetch";
-import { sandboxProxyGateway } from "../../../services/api";
+import {
+ createOrUpdateMockRequest,
+ deleteMockRequest,
+ getApiMockRequest,
+ sandboxProxyGateway
+} from "../../../services/api";
import ApiContext from "./ApiContext";
import HeadersEditor from "./HeadersEditor";
-import { getIntlContent } from "../../../utils/IntlUtils";
+import {getIntlContent} from "../../../utils/IntlUtils";
import AuthButton from "../../../utils/AuthButton";
+import {Method} from "./globalData";
const { Title, Text, Paragraph } = Typography;
-const { TreeNode } = Tree;
const { TabPane } = Tabs;
const FormItem = Form.Item;
@@ -54,10 +41,62 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
}));
const {
- apiDetail: { apiPath, httpMethodList, requestHeaders, requestParameters },
- apiData: { appKey, gatewayUrl, cookie }
+ apiDetail,
+ apiMock
} = useContext(ApiContext);
- const [questJson, setRequestJson] = useState({});
+ const [questJson, setRequestJson] = useState(JSON.parse(apiMock.body || '{}'));
+ const [initialValue, setInitialValue] = useState({
+ id: apiMock.id,
+ apiId: apiDetail.id,
+ host: apiMock.host,
+ port: apiMock.port,
+ url: apiMock.url,
+ pathVariable: apiMock.pathVariable,
+ query: apiMock.query,
+ header: apiMock.header,
+ body: apiMock.body
+ });
+ const [activeKey, setActiveKey] = useState("1");
+
+ useEffect(
+ () => {
+ setInitialValue({
+ id: apiMock.id,
+ apiId: apiDetail.id,
+ host: apiMock.host,
+ port: apiMock.port,
+ url: apiMock.url,
+ pathVariable: apiMock.pathVariable,
+ query: apiMock.query,
+ header: apiMock.header,
+ body: apiMock.body
+ });
+ form.resetFields("requestUrl");
+ setRequestJson(JSON.parse(apiMock.body || '{}'));
+ },
+ [apiMock.id]
+ );
+
+ useEffect(
+ () => {
+ form.setFieldsValue({httpMethod: Method?.[apiDetail.httpMethod]})
+ },
+ [apiDetail.httpMethod]
+ );
+
+ useEffect(
+ () => {
+ form.setFieldsValue({headers: initialValue.header || "{}"})
+ },
+ [initialValue.header]
+ );
+
+ useEffect(
+ () => {
+ form.setFieldsValue({querys: initialValue.query || "{}"})
+ },
+ [initialValue.query]
+ );
const handleSubmit = e => {
e.preventDefault();
@@ -69,78 +108,79 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
});
}
});
- };
-
- const createRequestJson = (params = []) => {
- const exampleJSON = {};
- const key = [];
- const loopExample = (data, obj) => {
- data.forEach(item => {
- const { name, refs, example, type } = item;
- key.push(name);
- switch (type) {
- case "array":
- if (Array.isArray(refs)) {
- obj[name] = [{}];
- key.push(0);
- loopExample(refs, obj[name][0]);
- key.pop();
- } else {
- obj[name] = [];
- }
- break;
- case "object":
- obj[name] = {};
- if (Array.isArray(refs)) {
- loopExample(refs, obj[name]);
- }
- break;
- default:
- obj[name] = example;
- break;
- }
- key.pop();
- });
- };
+ }
- loopExample(params, exampleJSON);
- setRequestJson(exampleJSON);
+ const updateJson = obj => {
+ setRequestJson(obj.updated_src);
};
- const renderTreeNode = (data, indexArr = []) => {
- return data.map((item, index) => {
- const { name, type, required, description } = item;
- const TreeTitle = (
- <>
- <Text strong>{name}</Text>
- <Text code>{type}</Text>
-
- {required ? (
- <Text type="danger">required</Text>
- ) : (
- <Text type="warning">optional</Text>
- )}
- <Text type="secondary">{description}</Text>
- </>
- );
- return (
- <TreeNode key={[...indexArr, index].join("-")} title={TreeTitle}>
- {item.refs && renderTreeNode(item.refs, [...indexArr, index])}
- </TreeNode>
- );
+ const handlerSaveOrUpdate = async () => {
+ ref.current.form.validateFieldsAndScroll( async (errors) => {
+ if (!errors) {
+ const fields = form.getFieldsValue();
+ let requestUrl = fields.requestUrl;
+ const url = new URL(requestUrl);
+ const params = {
+ ...initialValue,
+ apiId: apiDetail.id,
+ host: url.hostname,
+ port: url.port,
+ url: requestUrl,
+ header: fields.headers,
+ query: fields.querys,
+ body: JSON.stringify(questJson),
+ pathVariable: url.search || ''
+ }
+ let rs = await createOrUpdateMockRequest(params);
+ if (rs.code !== 200) {
+ message.error(rs.msg);
+ } else {
+ const { code, message: msg, data } = await getApiMockRequest(apiDetail.id);
+ if (code !== 200) {
+ message.error(msg);
+ return;
+ }
+ message.success(rs.message);
+ setInitialValue({...initialValue, id: data.id});
+ }
+ }
});
};
- const updateJson = obj => {
- setRequestJson(obj.updated_src);
+ const handlerDelete = async () => {
+ if (initialValue.id) {
+ let rs = await deleteMockRequest(initialValue.id);
+ if (rs.code !== 200) {
+ message.error(rs.msg);
+ } else {
+ message.success(rs.message);
+ }
+ }
+ resetContext()
};
- useEffect(
- () => {
- createRequestJson(requestParameters);
- },
- [requestParameters]
- );
+ const resetContext = () => {
+ setInitialValue({
+ id: null,
+ apiId: apiDetail.id,
+ host: undefined,
+ port: null,
+ url: null,
+ pathVariable: null,
+ query: null,
+ header: null,
+ body: null
+ });
+ setRequestJson({});
+ form.resetFields("requestUrl");
+ }
+
+ const changeParamTab = (key) => {
+ setActiveKey(key);
+ let header = form.getFieldsValue().headers;
+ let headerJson = {...JSON.parse(header), "Content-type": key === '1' ? "application/json" : "application/x-www-form-urlencoded"};
+ setInitialValue({...initialValue, header: JSON.stringify(headerJson)})
+ }
return (
<Form onSubmit={handleSubmit}>
@@ -149,60 +189,33 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
</Title>
<FormItem label={getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.ADDRESS")}>
{form.getFieldDecorator("requestUrl", {
- initialValue: gatewayUrl + apiPath,
- rules: [{ type: "string", required: true }]
+ initialValue: initialValue.url || '',
+ rules: [
+ {
+ type: "string",
+ required: true,
+ pattern: /^https?:\/\/([^:]+):(\d+)(\/.+)$/
+ }
+ ]
})(<Input allowClear />)}
</FormItem>
- <FormItem label="AppKey">
- {form.getFieldDecorator("appKey", {
- initialValue: appKey,
- rules: [{ type: "string" }]
- })(
- <Input
- allowClear
- placeholder=" If the current API requires signature authentication, this parameter is required"
- />
- )}
- </FormItem>
- <FormItem label="Cookie">
- {form.getFieldDecorator("cookie", {
- initialValue: cookie,
- rules: [{ type: "string" }]
- })(
- <Input
- allowClear
- placeholder="Fill in the real cookie value.(signature authentication and login free API ignore this item)"
- />
- )}
- </FormItem>
<FormItem label="Headers">
{form.getFieldDecorator("headers", {
- initialValue: requestHeaders || [],
- rules: [
- {
- validator: (rule, value, callback) => {
- const errorRow = value.find(
- item => item.required && item.example === ""
- );
- if (errorRow) {
- callback(`${errorRow.name} is required`);
- } else {
- callback();
- }
- }
- }
- ]
- })(<HeadersEditor />)}
+ initialValue: initialValue.header,
+ rules: []
+ })(<HeadersEditor buttonText={getIntlContent("SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.HEADER")} mockId={apiMock.id} />)}
</FormItem>
<FormItem label={getIntlContent("SHENYU.COMMON.HTTP.METHOD")}>
{form.getFieldDecorator("httpMethod", {
- initialValue: httpMethodList?.[0]?.toLocaleUpperCase(),
+ initialValue: Method?.[apiDetail.httpMethod],
rules: [{ type: "string", required: true }]
- })(
- <Radio.Group
- options={httpMethodList?.map(v => v.toLocaleUpperCase())}
+ })
+ (
+ <Input
+ allowClear
+ readOnly={true}
/>
)}
</FormItem>
@@ -210,41 +223,69 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
label={getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.REQUEST.PARAMETERS")}
required
/>
- <Row gutter={16}>
- <Col span={14}>
- <ReactJson
- src={questJson}
- theme="monokai"
- displayDataTypes={false}
- name={false}
- onAdd={updateJson}
- onEdit={updateJson}
- onDelete={updateJson}
- style={{ borderRadius: 4, padding: 16 }}
- />
- </Col>
- <Col span={10}>
- <div
- style={{
- borderRadius: 4,
- border: "1px solid #e8e8e8",
- overflow: "auto",
- padding: 8
- }}
- >
- {requestParameters && (
- <Tree showLine defaultExpandAll>
- {renderTreeNode(requestParameters)}
- </Tree>
- )}
- </div>
- </Col>
- </Row>
+
+ <Tabs
+ activeKey={activeKey}
+ onChange={key => changeParamTab(key)}
+ >
+ <Tabs.TabPane
+ tab={
+ <>
+ <Icon type="file-text" />
+ BODY
+ </>
+ }
+ key="1"
+ >
+ <Row gutter={16}>
+ <Col span={14}>
+ <ReactJson
+ src={questJson}
+ theme="monokai"
+ displayDataTypes={false}
+ name={false}
+ onAdd={updateJson}
+ onEdit={updateJson}
+ onDelete={updateJson}
+ style={{ borderRadius: 4, padding: 16 }}
+ />
+ </Col>
+ </Row>
+ </Tabs.TabPane>
+
+ <Tabs.TabPane
+ tab={
+ <>
+ <Icon type="file-text" />
+ QUERY
+ </>
+ }
+ key="2"
+ >
+
+ <FormItem>
+ {form.getFieldDecorator("querys", {
+ initialValue: initialValue.query || "{}",
+ rules: []
+ })(<HeadersEditor buttonText={getIntlContent("SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.ADD.QUERY")} mockId={apiMock.id} />)}
+ </FormItem>
+ </Tabs.TabPane>
+ </Tabs>
+
+
<AuthButton perms="document:apirun:send">
<FormItem label=" " colon={false}>
<Button htmlType="submit" type="primary">
{getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.SEND.REQUEST")}
</Button>
+
+ <Button onClick={handlerSaveOrUpdate}>
+ {getIntlContent("SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.SAVE")}
+ </Button>
+
+ <Button onClick={handlerDelete}>
+ {getIntlContent("SHENYU.DOCUMENT.APIDOC.DEBUG.MOCK.RESET")}
+ </Button>
</FormItem>
</AuthButton>
</Form>
@@ -259,16 +300,12 @@ function ApiDebug() {
} = useContext(ApiContext);
const [responseInfo, setResponseInfo] = useState({});
const [activeKey, setActiveKey] = useState("2");
-
const formRef = createRef();
const handleSubmit = async values => {
- const { headers, ...params } = values;
- const headersObj = {};
- headers.forEach(item => {
- headersObj[item.name] = item.example;
- });
- params.headers = headersObj;
+ const { headers, requestUrl, ...params } = values;
+ params.headers = JSON.parse(headers);
+ params.requestUrl = requestUrl;
fetch(sandboxProxyGateway(), {
method: "POST",
headers: {
@@ -290,13 +327,12 @@ function ApiDebug() {
useEffect(
() => {
setResponseInfo({});
- // eslint-disable-next-line no-unused-expressions
- formRef.current?.form.resetFields(["method", "headers"]);
setActiveKey("2");
},
[id]
);
+
return (
<>
<EnhancedFCForm wrappedComponentRef={formRef} onSubmit={handleSubmit} />
diff --git a/src/routes/Document/components/HeadersEditor.js b/src/routes/Document/components/HeadersEditor.js
index 34a93ae7..c2bd9485 100644
--- a/src/routes/Document/components/HeadersEditor.js
+++ b/src/routes/Document/components/HeadersEditor.js
@@ -16,56 +16,71 @@
*/
import { Col, Input, Row, Button, Icon, Typography } from "antd";
-import React, { Fragment } from "react";
+import React, {Fragment, useEffect, useState} from "react";
const { Text } = Typography;
function HeadersEditor(props) {
- const { value, onChange } = props;
- const onChangeItem = (e, key, id) => {
- onChange(
- value.map(
- item => (item.id === id ? { ...item, [key]: e.target.value } : item)
- )
+ const {value: propsValue, onChange, buttonText} = props;
+ const jsonObj = JSON.parse(propsValue || '{}');
+ const [value, onChangeValue] =useState(Object.keys(jsonObj).map((key, index) => ({index, key, value: jsonObj[key]})));
+
+ useEffect(
+ () => {
+ onChangeValue(Object.keys(jsonObj).map((key, index) => ({index, key, value: jsonObj[key]})))
+ },
+ [propsValue]
+ );
+
+ const onChangeItem = (e, key, index) => {
+ let newValue = value.map(
+ item => (item.index === index ? { ...item, [key]: e } : item)
);
+ onChangeValue(newValue);
+ onChange(format(newValue));
};
- const onDeleteItem = id => {
- onChange(value.filter(item => item.id !== id));
+ const onDeleteItem = key => {
+ let newValue = value.filter(item => item.key !== key);
+ onChangeValue(newValue);
+ onChange(format(newValue));
};
const onAddItem = () => {
- onChange([
+ let newValue = [
...value,
- { id: `${Date.now()}`, name: "", example: "", required: false }
- ]);
+ {index: value.length, key: "", value: ""}
+ ];
+ onChangeValue(newValue);
+ onChange(format(newValue));
};
+ const format = (param) => {
+ const newObject = param.reduce((acc, curr) => {
+ acc[curr.key] = curr.value;
+ return acc;
+ }, {});
+ return JSON.stringify(newObject);
+ }
+
return (
<Row gutter={16}>
{value.map(item => (
- <Fragment key={item.id}>
+ <Fragment key={item.index}>
<Col span={6}>
<Input
allowClear
- value={item.name}
- readOnly={item.required}
- onChange={e => onChangeItem(e, "name", item.id)}
+ value={item.key}
+ readOnly={false}
+ onChange={e => onChangeItem(e.target.value, "key", item.index)}
/>
</Col>
<Col span={16}>
<Input
allowClear
- value={item.example}
- placeholder={item.description}
- prefix={
- item.required && (
- <Text type="danger" strong>
- *
- </Text>
- )
- }
- onChange={e => onChangeItem(e, "example", item.id)}
+ value={item.value}
+ readOnly={false}
+ onChange={e => onChangeItem(e.target.value, "value", item.index)}
/>
</Col>
<Col span={2} style={{ textAlign: "center" }}>
@@ -74,7 +89,7 @@ function HeadersEditor(props) {
<Icon
style={{ fontSize: "16px" }}
type="minus-circle-o"
- onClick={() => onDeleteItem(item.id)}
+ onClick={() => onDeleteItem(item.key)}
/>
</Text>
)}
@@ -84,7 +99,7 @@ function HeadersEditor(props) {
<Col span={24}>
<Button block type="dashed" onClick={onAddItem}>
- <Icon type="plus" /> Add header
+ <Icon type="plus" /> {buttonText}
</Button>
</Col>
</Row>
diff --git a/src/services/api.js b/src/services/api.js
index d2682234..22234ff4 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -823,6 +823,30 @@ export function getApiDetail(id) {
});
}
+/* queryMockRequest */
+export function getApiMockRequest(apiId) {
+ return request(`${baseUrl}/mock/${apiId}`, {
+ method: `GET`
+ });
+}
+
+/* createOrUpdateMockRequest */
+export function createOrUpdateMockRequest(params) {
+ return request(`${baseUrl}/mock/insertOrUpdate`, {
+ method: `POST`,
+ body: {
+ ...params
+ }
+ })
+}
+
+/* createOrUpdateMockRequest */
+export function deleteMockRequest(id) {
+ return request(`${baseUrl}/mock/${id}`, {
+ method: `DELETE`
+ })
+}
+
/** addApi */
export function addApi(params) {
return request(`${baseUrl}/api`, {