feat: TCP请求的相关交互和展示优化

接口定义TCP请求的交互和展示优化,TCP设置增加编码设置,TCP表头的请求类型改为协议方法,ESB报文增加Mock参数
This commit is contained in:
song-tianyang 2021-06-04 10:41:22 +08:00 committed by 刘瑞斌
parent 3d0edb2e35
commit 214a6385fe
12 changed files with 119 additions and 27 deletions

View File

@ -20,6 +20,7 @@ import io.metersphere.commons.constants.DelimiterConstants;
import io.metersphere.commons.constants.MsTestElementConstants; import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ScriptEngineUtils;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -35,10 +36,13 @@ import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree; import org.apache.jorphan.collections.ListedHashTree;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -82,6 +86,9 @@ public class MsTCPSampler extends MsTestElement {
private String protocol = "TCP"; private String protocol = "TCP";
@JSONField(ordinal = 39) @JSONField(ordinal = 39)
private String projectId; private String projectId;
@JSONField(ordinal = 40)
private String connectEncoding;
/** /**
* 新加两个参数场景保存/修改时需要的参数不会传递JMeter只是用于最后的保留 * 新加两个参数场景保存/修改时需要的参数不会传递JMeter只是用于最后的保留
@ -195,7 +202,21 @@ public class MsTCPSampler extends MsTestElement {
tcpSampler.setCloseConnection(String.valueOf(this.isCloseConnection())); tcpSampler.setCloseConnection(String.valueOf(this.isCloseConnection()));
tcpSampler.setSoLinger(this.getSoLinger()); tcpSampler.setSoLinger(this.getSoLinger());
tcpSampler.setEolByte(this.getEolByte()); tcpSampler.setEolByte(this.getEolByte());
tcpSampler.setRequestData(this.getRequest());
String value = this.getRequest();
if(StringUtils.isNotEmpty(this.getConnectEncoding())){
if(StringUtils.equalsIgnoreCase("utf-8",this.getConnectEncoding())){
value = new String(value.getBytes(),StandardCharsets.UTF_8);
}else if(StringUtils.equalsIgnoreCase("gbk",this.getConnectEncoding())){
try {
value = new String(value.getBytes(),"GBK");
}catch (Exception e){
}
}
}
tcpSampler.setRequestData(value);
tcpSampler.setProperty(ConfigTestElement.USERNAME, this.getUsername()); tcpSampler.setProperty(ConfigTestElement.USERNAME, this.getUsername());
tcpSampler.setProperty(ConfigTestElement.PASSWORD, this.getPassword()); tcpSampler.setProperty(ConfigTestElement.PASSWORD, this.getPassword());
return tcpSampler; return tcpSampler;
@ -213,7 +234,19 @@ public class MsTCPSampler extends MsTestElement {
if (CollectionUtils.isNotEmpty(this.parameters)) { if (CollectionUtils.isNotEmpty(this.parameters)) {
this.parameters.forEach(item -> { this.parameters.forEach(item -> {
names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName())); names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName()));
threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getValue())); String value = item.getValue();
value = this.formatMockValue(value);
if(StringUtils.isNotEmpty(this.getConnectEncoding())){
if(StringUtils.equalsIgnoreCase("utf-8",this.getConnectEncoding())){
value = new String(value.getBytes(),StandardCharsets.UTF_8);
}else if(StringUtils.equalsIgnoreCase("gbk",this.getConnectEncoding())){
try {
value = new String(value.getBytes(),"GBK");
}catch (Exception e){
}
}
}
threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), value));
}); });
} }
userParameters.setNames(new CollectionProperty(UserParameters.NAMES, names)); userParameters.setNames(new CollectionProperty(UserParameters.NAMES, names));
@ -222,7 +255,29 @@ public class MsTCPSampler extends MsTestElement {
userParameters.setThreadLists(new CollectionProperty(UserParameters.THREAD_VALUES, collectionPropertyList)); userParameters.setThreadLists(new CollectionProperty(UserParameters.THREAD_VALUES, collectionPropertyList));
tree.add(userParameters); tree.add(userParameters);
} }
private String formatMockValue(String value) {
String patten = ">@[^>@]+</?";
Pattern r = Pattern.compile(patten);
try{
Matcher m = r.matcher(value);
while (m.find()){
String findStr = m.group();
if(findStr.length() > 3){
findStr = findStr.substring(1,findStr.length()-2);
String replaceStr = ScriptEngineUtils.calculate(findStr);
if(StringUtils.equals(findStr,replaceStr)){
replaceStr = "";
}
value = value.replace(">"+findStr+"</",">"+replaceStr+"</");
m = r.matcher(value);
}
}
}catch (Exception e){
}
return value;
}
private ConfigTestElement tcpConfig() { private ConfigTestElement tcpConfig() {
ConfigTestElement configTestElement = new ConfigTestElement(); ConfigTestElement configTestElement = new ConfigTestElement();
configTestElement.setEnabled(true); configTestElement.setEnabled(true);

View File

@ -39,11 +39,9 @@ public class EsbApiParamService {
public EsbApiParamsWithBLOBs createEsbApiParam(String resourceId, String esbDataStruct, String backedEsbDataStrcut, String backedScript) { public EsbApiParamsWithBLOBs createEsbApiParam(String resourceId, String esbDataStruct, String backedEsbDataStrcut, String backedScript) {
EsbApiParamsWithBLOBs model = null; EsbApiParamsWithBLOBs model = null;
EsbApiParamsExample example = new EsbApiParamsExample(); EsbApiParamsExample example = new EsbApiParamsExample();
example.createCriteria().andResourceIdEqualTo(resourceId); example.createCriteria().andResourceIdEqualTo(resourceId);
List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example); List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example);
if (list.isEmpty()) { if (list.isEmpty()) {
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
model = new EsbApiParamsWithBLOBs(); model = new EsbApiParamsWithBLOBs();

View File

@ -41,7 +41,7 @@
sortable="custom" sortable="custom"
column-key="method" column-key="method"
:filters="methodFilters" :filters="methodFilters"
:label="$t('api_test.definition.api_type')" :label="getApiRequestTypeName"
width="120px"> width="120px">
<template v-slot:default="scope"> <template v-slot:default="scope">
<el-tag size="mini" <el-tag size="mini"
@ -228,6 +228,13 @@
} else { } else {
return new Set(); return new Set();
} }
},
getApiRequestTypeName(){
if(this.currentProtocol === 'TCP'){
return this.$t('api_test.definition.api_agreement');
}else{
return this.$t('api_test.definition.api_type');
}
} }
}, },
methods: { methods: {

View File

@ -69,7 +69,12 @@ export default {
return { return {
validated: false, validated: false,
apiProtocol: "TCP", apiProtocol: "TCP",
methodTypes:["TCP"], methodTypes:[
{
'key':"TCP",
'value':this.$t('api_test.request.tcp.general_format'),
}
],
showXpackCompnent:false, showXpackCompnent:false,
} }
}, },
@ -85,7 +90,10 @@ export default {
this.showXpackCompnent = true; this.showXpackCompnent = true;
if(hasLicense()){ if(hasLicense()){
if(this.methodTypes.length == 1){ if(this.methodTypes.length == 1){
this.methodTypes.push("ESB"); let esbMethodType = {};
esbMethodType.key = "ESB";
esbMethodType.value="ESB";
this.methodTypes.push(esbMethodType);
} }
} }

View File

@ -8,7 +8,7 @@
<!-- <el-input class="ms-http-input" size="small" v-model="basicForm.name"/>--> <!-- <el-input class="ms-http-input" size="small" v-model="basicForm.name"/>-->
<el-input v-model="basicForm.name" class="ms-http-input" size="small"> <el-input v-model="basicForm.name" class="ms-http-input" size="small">
<el-select v-model="basicForm.method" slot="prepend" style="width: 100px" size="small" @change="methodChange"> <el-select v-model="basicForm.method" slot="prepend" style="width: 100px" size="small" @change="methodChange">
<el-option v-for="item in methodTypes" :key="item" :label="item" :value="item"/> <el-option v-for="item in methodTypes" :key="item.key" :label="item.value" :value="item.key"/>
</el-select> </el-select>
</el-input> </el-input>
@ -16,20 +16,6 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('test_track.module.module')" prop="moduleId"> <el-form-item :label="$t('test_track.module.module')" prop="moduleId">
<!--<el-select class="ms-http-input" size="small" v-model="basicForm.moduleId" style="width: 100%" @change="reload">-->
<!--<div v-if="moduleOptions.length>0">-->
<!--<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>-->
<!--</div>-->
<!--<div v-else>-->
<!--<el-option :key="0" :value="''">-->
<!--<div style="margin-left: 40px">-->
<!--<span style="font-size: 14px;color: #606266;font-weight: 48.93">{{ $t('api_test.definition.select_comp.no_data') }},-->
<!--</span>-->
<!--<el-link type="primary" @click="createModules">{{ $t('api_test.definition.select_comp.add_data') }}</el-link>-->
<!--</div>-->
<!--</el-option>-->
<!--</div>-->
<!--</el-select>-->
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="basicForm.moduleId" @getValue="setModule" :obj="moduleObj" clearable checkStrictly/> <ms-select-tree size="small" :data="moduleOptions" :defaultKey="basicForm.moduleId" @getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
</el-form-item> </el-form-item>

View File

@ -70,7 +70,7 @@
:filters="methodFilters" :filters="methodFilters"
:fields-width="fieldsWidth" :fields-width="fieldsWidth"
min-width="120px" min-width="120px"
:label="$t('api_test.definition.api_type')"> :label="getApiRequestTypeName">
<template v-slot:default="scope" class="request-method"> <template v-slot:default="scope" class="request-method">
<el-tag size="mini" <el-tag size="mini"
:style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}" :style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}"
@ -398,6 +398,13 @@ export default {
selectRows() { selectRows() {
return this.$refs.apiDefinitionTable.getSelectRows(); return this.$refs.apiDefinitionTable.getSelectRows();
}, },
getApiRequestTypeName(){
if(this.currentProtocol === 'TCP'){
return this.$t('api_test.definition.api_agreement');
}else{
return this.$t('api_test.definition.api_type');
}
}
}, },
created: function () { created: function () {
if (this.trashEnable) { if (this.trashEnable) {
@ -444,6 +451,12 @@ export default {
if (this.$refs.apiDefinitionTable) { if (this.$refs.apiDefinitionTable) {
this.$refs.apiDefinitionTable.clearSelectRows(); this.$refs.apiDefinitionTable.clearSelectRows();
} }
//
if(this.$refs.caseList){
this.$refs.caseList.handleClose();
}
initCondition(this.condition, this.condition.selectAll); initCondition(this.condition, this.condition.selectAll);
this.selectDataCounts = 0; this.selectDataCounts = 0;
this.condition.moduleIds = this.selectNodeIds; this.condition.moduleIds = this.selectNodeIds;

View File

@ -17,7 +17,6 @@
<el-row> <el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link> <el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link>
</el-row> </el-row>
<ms-api-key-value :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/> <ms-api-key-value :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/>
</el-tab-pane> </el-tab-pane>

View File

@ -73,12 +73,12 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="10" style="margin-left: 30px"> <el-row :gutter="10" style="margin-left: 30px">
<el-col :span="9"> <el-col :span="6">
<el-form-item :label="$t('api_test.request.tcp.re_use_connection')"> <el-form-item :label="$t('api_test.request.tcp.re_use_connection')">
<el-checkbox v-model="request.reUseConnection"/> <el-checkbox v-model="request.reUseConnection"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="9"> <el-col :span="6">
<el-form-item :label="$t('api_test.request.tcp.close_connection')"> <el-form-item :label="$t('api_test.request.tcp.close_connection')">
<el-checkbox v-model="request.closeConnection"/> <el-checkbox v-model="request.closeConnection"/>
</el-form-item> </el-form-item>
@ -88,6 +88,13 @@
<el-checkbox v-model="request.nodelay"/> <el-checkbox v-model="request.nodelay"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="Connect encoding">
<el-select v-model="request.connectEncoding" style="width: 100px" size="small">
<el-option v-for="item in connectEncodingArr" :key="item.key" :label="item.value" :value="item.key"/>
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -158,6 +165,16 @@
isReloadData: false, isReloadData: false,
options: API_STATUS, options: API_STATUS,
currentProjectId: "", currentProjectId: "",
connectEncodingArr:[
{
'key':'UTF-8',
'value':'UTF-8',
},
{
'key':'GBK',
'value':'GBK',
},
],
rules: { rules: {
classname: [{required: true, message: "请选择TCPClient", trigger: 'change'}], classname: [{required: true, message: "请选择TCPClient", trigger: 'change'}],
server: [{required: true, message: this.$t('api_test.request.tcp.server_cannot_be_empty'), trigger: 'blur'}], server: [{required: true, message: this.$t('api_test.request.tcp.server_cannot_be_empty'), trigger: 'blur'}],
@ -174,6 +191,9 @@
if (!this.request.tcpPreProcessor) { if (!this.request.tcpPreProcessor) {
this.$set(this.request, 'tcpPreProcessor', new JSR223PreProcessor()) this.$set(this.request, 'tcpPreProcessor', new JSR223PreProcessor())
} }
if(!this.request.connectEncoding){
this.request.connectEncoding = "UTF-8";
}
this.getEnvironments(); this.getEnvironments();
}, },
methods: { methods: {

@ -1 +1 @@
Subproject commit 1ac463ed7ef667d3f75c3ba64fab8331ecaa02c2 Subproject commit 34379f3a7e7d52b4a9c0194325b3ea02db5cc8eb

View File

@ -682,6 +682,7 @@ export default {
api_name: "Api name", api_name: "Api name",
api_status: "Api status", api_status: "Api status",
api_type: "Api type", api_type: "Api type",
api_agreement: "Method",
api_path: "Api path", api_path: "Api path",
api_principal: "Api principal", api_principal: "Api principal",
api_last_time: "Last update time", api_last_time: "Last update time",
@ -1050,6 +1051,7 @@ export default {
variable_names: "Variable names", variable_names: "Variable names",
}, },
tcp: { tcp: {
general_format: "General",
server: "Server Name or IP", server: "Server Name or IP",
port: "Port Number", port: "Port Number",
connect: "Connect(ms)", connect: "Connect(ms)",

View File

@ -682,6 +682,7 @@ export default {
api_name: "接口名称", api_name: "接口名称",
api_status: "接口状态", api_status: "接口状态",
api_type: "请求类型", api_type: "请求类型",
api_agreement: "协议/方法",
api_path: "路径", api_path: "路径",
api_principal: "负责人", api_principal: "负责人",
api_last_time: "最后更新时间", api_last_time: "最后更新时间",
@ -1052,6 +1053,7 @@ export default {
variable_names: "按列存储", variable_names: "按列存储",
}, },
tcp: { tcp: {
general_format: "通用格式",
server: "服务器名或IP", server: "服务器名或IP",
port: "端口", port: "端口",
connect: "连接(ms)", connect: "连接(ms)",

View File

@ -682,6 +682,7 @@ export default {
api_name: "接口名稱", api_name: "接口名稱",
api_status: "接口狀態", api_status: "接口狀態",
api_type: "請求類型", api_type: "請求類型",
api_agreement: "協議/方法",
api_path: "路徑", api_path: "路徑",
api_principal: "負責人", api_principal: "負責人",
api_last_time: "最後更新時間", api_last_time: "最後更新時間",
@ -1052,6 +1053,7 @@ export default {
variable_names: "按列存儲", variable_names: "按列存儲",
}, },
tcp: { tcp: {
general_format: "通用格式",
server: "服務器名或IP", server: "服務器名或IP",
port: "端口", port: "端口",
connect: "連接(ms)", connect: "連接(ms)",