feat(接口测试): 响应内容根据响应头中的content-type设置来进行对应的xml或json解析

响应内容根据响应头中的content-type设置来进行对应的xml或json解析
This commit is contained in:
song-tianyang 2022-10-18 14:15:51 +08:00 committed by wxg0103
parent e71ae9a0e7
commit 97725c4495
10 changed files with 106 additions and 129 deletions

View File

@ -21,15 +21,11 @@ import io.metersphere.api.dto.MsgDTO;
import io.metersphere.api.dto.RequestResultExpandDTO;
import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.commons.utils.FixedCapacityUtil;
import io.metersphere.commons.utils.ResponseUtil;
import io.metersphere.commons.utils.ResultParseUtil;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.WebSocketUtil;
import io.metersphere.commons.utils.*;
import io.metersphere.dto.RequestResult;
import io.metersphere.jmeter.JMeterBase;
import io.metersphere.utils.*;
import io.metersphere.utils.JMeterVars;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.engine.util.NoThreadClone;
@ -159,14 +155,14 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
if (StringUtils.isNotEmpty(requestResult.getName()) && requestResult.getName().startsWith("Transaction=")) {
requestResult.getSubRequestResults().forEach(transactionResult -> {
transactionResult.getResponseResult().setConsole(console);
//解析误报内容
//对响应内容进行进一步解析和处理
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(transactionResult);
dto.setContent("result_" + JSON.toJSONString(expandDTO));
WebSocketUtil.sendMessageSingle(dto);
});
} else {
requestResult.getResponseResult().setConsole(console);
//解析误报内容
//对响应内容进行进一步解析和处理
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(requestResult);
dto.setContent("result_" + JSON.toJSONString(expandDTO));
WebSocketUtil.sendMessageSingle(dto);

View File

@ -2,14 +2,12 @@ package io.metersphere.api.parse.scenario;
import io.metersphere.api.dto.automation.EsbDataStruct;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.XMLUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
@ -27,9 +25,6 @@ public class EsbDataParser {
if (esbDataList == null || esbDataList.isEmpty()) {
return xmlString;
}
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
XMLUtil.setExpandEntityReferencesFalse(factory);
Document document = DocumentHelper.createDocument();
EsbDataStruct dataStruct = selectEsbDataStructByNameStruct(esbDataList, paramArr, 0);
if (dataStruct != null) {

View File

@ -5,11 +5,9 @@ import io.metersphere.api.dto.mock.MockConfigRequestParams;
import io.metersphere.commons.constants.PropertyConstant;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.i18n.Translator;
import io.metersphere.commons.utils.XMLUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import io.metersphere.commons.utils.mock.MockApiUtils;
import io.metersphere.i18n.Translator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
@ -17,8 +15,9 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
@ -41,11 +40,7 @@ public class TcpTreeTableDataParser {
if (treeDataList == null || treeDataList.isEmpty()) {
return xmlString;
}
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
XMLUtil.setExpandEntityReferencesFalse(factory);
Document document = DocumentHelper.createDocument();
TcpTreeTableDataStruct dataStruct = null;
if (treeDataList.size() > 1) {
dataStruct = new TcpTreeTableDataStruct();

View File

@ -0,0 +1,8 @@
package io.metersphere.commons.enums;
/**
* 请求体格式化类型
*/
public enum ResponseFormatType {
XML, JSON, RAW
}

View File

@ -1,9 +1,14 @@
package io.metersphere.commons.utils;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
import io.metersphere.api.dto.RequestResultExpandDTO;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.enums.ResponseFormatType;
import io.metersphere.dto.RequestResult;
import io.metersphere.dto.ResponseResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -16,6 +21,10 @@ import java.util.Map;
public class ResponseUtil {
public static RequestResultExpandDTO parseByRequestResult(RequestResult baseResult) {
//根据responseheader的信息来处理返回数据
baseResult = ResponseUtil.parseResponseBodyByHeader(baseResult);
//解析是否含有误报库信息
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(baseResult);
RequestResult requestResult = errorCodeDTO.getResult();
@ -35,4 +44,54 @@ public class ResponseUtil {
}
return expandDTO;
}
public static RequestResult parseResponseBodyByHeader(RequestResult requestResult) {
if (requestResult != null && requestResult.getResponseResult() != null && StringUtils.isNoneBlank(requestResult.getResponseResult().getHeaders())) {
String[] headerArr = StringUtils.split(requestResult.getResponseResult().getHeaders(), StringUtils.LF);
String formatType = ResponseFormatType.RAW.toString();
for (String header : headerArr) {
String[] headerKeyValue = StringUtils.split(header, ":");
if (headerKeyValue.length == 2) {
if (StringUtils.equalsIgnoreCase(headerKeyValue[0], "Content-Type")) {
if (StringUtils.containsIgnoreCase(headerKeyValue[1], ResponseFormatType.XML.name())) {
formatType = ResponseFormatType.XML.name();
} else if (StringUtils.containsIgnoreCase(headerKeyValue[1], ResponseFormatType.JSON.name())) {
formatType = ResponseFormatType.JSON.name();
}
break;
}
}
}
requestResult.setResponseResult(formatResponseBody(requestResult.getResponseResult(), formatType));
}
return requestResult;
}
private static ResponseResult formatResponseBody(ResponseResult responseResult, String formatType) {
if (responseResult != null) {
String rspBody = responseResult.getBody();
if (StringUtils.equalsIgnoreCase(formatType, ResponseFormatType.XML.name())) {
try {
rspBody = XMLUtil.formatXmlString(responseResult.getBody());
} catch (Exception e) {
LogUtil.error("格式化xml返回值失败请检查返回参数是否为xml格式!", e);
}
} else if (StringUtils.equalsIgnoreCase(formatType, ResponseFormatType.JSON.name())) {
try {
ObjectMapper mapper = new ObjectMapper();
// 配置四个空格的缩进
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(StringUtils.SPACE + StringUtils.SPACE, DefaultIndenter.SYS_LF);
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter); // Indent JSON arrays
rspBody = mapper.writer(printer).writeValueAsString(JSON.parseObject(rspBody));
} catch (Exception e) {
LogUtil.error("格式化json返回值失败请检查返回参数是否为json格式!", e);
}
}
responseResult.setBody(rspBody);
}
return responseResult;
}
}

View File

@ -4,17 +4,35 @@ import io.metersphere.api.exec.engine.EngineSourceParserFactory;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XMLUtil {
public static String formatXmlString(String xmlString) throws Exception {
xmlString = StringUtils.replace(xmlString, StringUtils.LF, StringUtils.EMPTY);
Document document = getDom4jDocumentByXmlString(xmlString);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding(document.getXMLEncoding());
StringWriter stringWriter = new StringWriter();
XMLWriter writer = new XMLWriter(stringWriter, format);
writer.write(document);
writer.close();
return stringWriter.toString();
}
public static Document getDom4jDocumentByXmlString(String xmlString) throws Exception {
return EngineSourceParserFactory.getDocument(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8.name())));
}
public static void setExpandEntityReferencesFalse(DocumentBuilderFactory documentBuilderFactory) {
try {
@ -83,7 +101,6 @@ public class XMLUtil {
result = (JSONObject) XmlTagToJsonObject(list);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
// MSException.throwException(Translator.get("illegal_xml_format"));
}
return result;
}

View File

@ -325,7 +325,7 @@ public class MockApiUtils {
if (bodyObj.has("xmlHeader")) {
String xmlHeader = bodyObj.optString("xmlHeader");
if (!StringUtils.startsWith(xmlHeader, "<?") && !StringUtils.endsWith(xmlHeader, "?>")) {
returnStr = "<?" + xmlHeader + "?>\r\n";
returnStr = "<?xml " + xmlHeader + "?>\r\n";
} else {
returnStr = xmlHeader;
}
@ -355,6 +355,7 @@ public class MockApiUtils {
if (!((JSONObject) paramJson).keySet().isEmpty()) {
JSONArray bodyParams = returnParams.getBodyParams();
if (bodyParams == null) {
bodyParams = new JSONArray();
bodyParams.put(paramJson);
} else {
bodyParams.put(((JSONObject) paramJson));
@ -390,7 +391,7 @@ public class MockApiUtils {
requestMockParams.setRestParamsObj(urlParamsObject);
requestMockParams.setQueryParamsObj(queryParamsObject);
if (isPostRequest) {
if (isPostRequest && !queryParamsObject.keySet().isEmpty()) {
JSONArray jsonArray = new JSONArray();
jsonArray.put(queryParamsObject);
requestMockParams.setBodyParams(jsonArray);

View File

@ -283,7 +283,7 @@ public class ApiDefinitionExecResultService {
for (RequestResult item : dto.getRequestResults()) {
LoggerUtil.info("执行结果【 " + item.getName() + " 】入库存储");
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
//对响应内容进行进一步解析如果有附加信息比如误报库信息则根据附加信息内的数据进行其他判读
//对响应内容进行进一步解析和处理如果有附加信息比如误报库信息则根据附加信息内的数据进行其他判读
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(item);
ApiDefinitionExecResult reportResult = this.editResult(item, dto.getReportId(), dto.getConsole(), dto.getRunMode(), dto.getTestId(), null);

View File

@ -1,41 +1,18 @@
package io.metersphere.service.scenario;
import io.metersphere.api.dto.ApiScenarioReportBaseInfoDTO;
import io.metersphere.api.dto.ApiScenarioReportDTO;
import io.metersphere.api.dto.RequestResultExpandDTO;
import io.metersphere.api.dto.StepTreeDTO;
import io.metersphere.api.dto.*;
import io.metersphere.api.exec.scenario.ApiScenarioEnvService;
import io.metersphere.api.dto.ApiDefinitionExecResultDTO;
import io.metersphere.base.domain.ApiDefinitionExecResultExample;
import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs;
import io.metersphere.base.domain.ApiScenarioReport;
import io.metersphere.base.domain.ApiScenarioReportResult;
import io.metersphere.base.domain.ApiScenarioReportResultExample;
import io.metersphere.base.domain.ApiScenarioReportResultWithBLOBs;
import io.metersphere.base.domain.ApiScenarioReportStructureExample;
import io.metersphere.base.domain.ApiScenarioReportStructureWithBLOBs;
import io.metersphere.base.domain.ApiScenarioReportWithBLOBs;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.UiScenarioWithBLOBs;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.ApiScenarioReportResultMapper;
import io.metersphere.base.mapper.ApiScenarioReportStructureMapper;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportResultMapper;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.constants.PropertyConstant;
import io.metersphere.commons.constants.ReportTypeConstants;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.*;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.RequestResult;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.commons.utils.ResultParseUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
@ -48,15 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@ -293,6 +262,8 @@ public class ApiScenarioReportStructureService {
RequestResult result = new RequestResultExpandDTO(reportResult);
if (reportResult.getContent() != null) {
result = JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class);
//针对响应头对响应内容做处理
result = ResponseUtil.parseResponseBodyByHeader(result);
}
step.setValue(result);
step.setTotalStatus(reportResult.getStatus());
@ -701,6 +672,8 @@ public class ApiScenarioReportStructureService {
RequestResult result = new RequestResult();
try {
result = selectReportContent(stepId, RequestResult.class);
//针对响应头对响应内容做处理
result = ResponseUtil.parseResponseBodyByHeader(result);
} catch (Exception ignore) {
}
return result;

View File

@ -1,7 +1,6 @@
package io.metersphere.environment.utils;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.environment.dto.MockConfigRequestParams;
import io.metersphere.environment.dto.MockParamConditionEnum;
import io.metersphere.environment.dto.TcpTreeTableDataStruct;
@ -9,18 +8,10 @@ import io.metersphere.i18n.Translator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
@ -36,64 +27,6 @@ public class TcpTreeTableDataParser {
public static final String DATA_TYPE_STRING = "string";
public static final String DATA_TYPE_OBJECT = "object";
public static String treeTableData2Xml(List<TcpTreeTableDataStruct> treeDataList) {
String xmlString = "";
try {
if (treeDataList == null || treeDataList.isEmpty()) {
return xmlString;
}
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
XMLUtils.setExpandEntityReferencesFalse(factory);
DocumentBuilder db = factory.newDocumentBuilder();
Document document = DocumentHelper.createDocument();
TcpTreeTableDataStruct dataStruct = null;
if (treeDataList.size() > 1) {
dataStruct = new TcpTreeTableDataStruct();
dataStruct.setName("ROOT");
dataStruct.setChildren(treeDataList);
} else {
dataStruct = treeDataList.get(0);
}
dataStruct.genXmlElementByDocument(document);
xmlString = document.getRootElement().asXML();
// 设置XML文档格式
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
// 设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1
outputFormat.setEncoding(StandardCharsets.UTF_8.name());
//outputFormat.setSuppressDeclaration(true); //是否生产xml头
outputFormat.setIndent(true); //设置是否缩进
outputFormat.setNewlines(true); //设置是否换行
try {
// stringWriter字符串是用来保存XML文档的
StringWriter stringWriter = new StringWriter();
// xmlWriter是用来把XML文档写入字符串的(工具)
XMLWriter xmlWriter = new XMLWriter(stringWriter, outputFormat);
// 把创建好的XML文档写入字符串
xmlWriter.write(document);
// 打印字符串,即是XML文档
xmlString = stringWriter.toString();
xmlWriter.close();
} catch (IOException e) {
LogUtil.error(e);
}
} catch (Exception e) {
LogUtil.error(e);
}
if (StringUtils.isEmpty(xmlString)) {
xmlString = "";
} else {
xmlString = xmlString.replaceAll(" ", "");
}
return xmlString;
}
public static List<TcpTreeTableDataStruct> xml2TreeTableData(String xmlString) {
List<TcpTreeTableDataStruct> returnList = new ArrayList<>();
Document document = XMLUtils.stringToDocument(xmlString);