diff --git a/backend/src/main/java/io/metersphere/log/utils/ReflexObjectUtil.java b/backend/src/main/java/io/metersphere/log/utils/ReflexObjectUtil.java index 5b1f8302b1..336676b1ef 100644 --- a/backend/src/main/java/io/metersphere/log/utils/ReflexObjectUtil.java +++ b/backend/src/main/java/io/metersphere/log/utils/ReflexObjectUtil.java @@ -164,9 +164,28 @@ public class ReflexObjectUtil { } // 深度对比 else if (StringUtils.equals(module, "api_definition")) { - String newValue = newColumns.get(i).getOriginalValue().toString(); - String oldValue = column.getOriginalValue().toString(); - column.setDiffValue(ApiDefinitionDiffUtil.diff(newValue, oldValue)); + if (originalColumns.get(i).getColumnName().equals("request")) { + String newValue = newColumns.get(i).getOriginalValue().toString(); + String oldValue = column.getOriginalValue().toString(); + column.setDiffValue(ApiDefinitionDiffUtil.diff(newValue, oldValue)); + } else if (originalColumns.get(i).getColumnName().equals("response")) { + String newValue = newColumns.get(i).getOriginalValue().toString(); + String oldValue = column.getOriginalValue().toString(); + column.setDiffValue(ApiDefinitionDiffUtil.diffResponse(newValue, oldValue)); + } + } else { + try { + String newValue = column.getNewValue().toString(); + if (StringUtils.isNotEmpty(newValue)) { + column.setNewValue(newValue.replaceAll("\\n", " ")); + } + String oldValue = column.getOriginalValue().toString(); + if (StringUtils.isNotEmpty(oldValue)) { + column.setOriginalValue(oldValue.replaceAll("\\n", " ")); + } + } catch (Exception e) { + + } } comparedColumns.add(column); } diff --git a/backend/src/main/java/io/metersphere/log/utils/dff/ApiDefinitionDiffUtil.java b/backend/src/main/java/io/metersphere/log/utils/dff/ApiDefinitionDiffUtil.java index e833d0f8d9..942228419b 100644 --- a/backend/src/main/java/io/metersphere/log/utils/dff/ApiDefinitionDiffUtil.java +++ b/backend/src/main/java/io/metersphere/log/utils/dff/ApiDefinitionDiffUtil.java @@ -6,6 +6,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; +import io.metersphere.api.dto.scenario.Body; import io.metersphere.log.utils.ReflexObjectUtil; import io.metersphere.log.utils.json.diff.JacksonDiff; import io.metersphere.log.utils.json.diff.JsonDiff; @@ -23,6 +24,23 @@ public class ApiDefinitionDiffUtil { static final String JSON_START = "{\"root\":"; static final String JSON_END = "}"; + public static String diffResponse(String newValue, String oldValue) { + Map diffMap = new LinkedHashMap<>(); + JSONObject bloBsNew = JSON.parseObject(newValue); + JSONObject bloBsOld = JSON.parseObject(oldValue); + if (bloBsNew == null || StringUtils.isEmpty(bloBsNew.getString("type"))) { + return null; + } + JsonDiff jsonDiff = new JacksonDiff(); + if (bloBsNew.getString("type").equals("HTTP")) { + diffHttpResponse(bloBsNew, bloBsOld, jsonDiff, diffMap); + if (diffMap.size() > 0) { + diffMap.put("type", bloBsNew.getString("type")); + } + } + return JSON.toJSONString(diffMap); + } + public static String diff(String newValue, String oldValue) { try { JSONObject bloBsNew = JSON.parseObject(newValue); @@ -141,6 +159,11 @@ public class ApiDefinitionDiffUtil { if (CollectionUtils.isNotEmpty(authDiffColumns)) { diffMap.put("body_auth", JSON.toJSONString(authDiffColumns)); } else if (CollectionUtils.isEmpty(authDiffColumns) && CollectionUtils.isEmpty(authColumnsOld) && CollectionUtils.isNotEmpty(authColumns)) { + authColumns.forEach(item -> { + Object value = item.getOriginalValue(); + item.setNewValue(value); + item.setOriginalValue(""); + }); diffMap.put("body_auth", JSON.toJSONString(authColumns)); } } @@ -155,6 +178,67 @@ public class ApiDefinitionDiffUtil { } } + private static void diffHttpResponse(JSONObject httpNew, JSONObject httpOld, JsonDiff jsonDiff, Map diffMap) { + // 请求头对比 old/new + if (httpNew.get("headers") != null && httpOld.get("headers") != null) { + String headerNew = JSON_START + httpNew.get("headers").toString() + JSON_END; + String headerOld = JSON_START + httpOld.get("headers").toString() + JSON_END; + if (!StringUtils.equals(headerNew, headerOld)) { + String patch = jsonDiff.diff(headerOld, headerNew); + String diffPatch = jsonDiff.apply(headerNew, patch); + if (StringUtils.isNotEmpty(diffPatch)) { + diffMap.put("header", diffPatch); + } + } + } + // 对比statusCode参数 + if (httpNew.get("statusCode") != null && httpOld.get("statusCode") != null) { + String statusCodeNew = JSON_START + httpNew.get("statusCode").toString() + JSON_END; + String statusCodeOld = JSON_START + httpOld.get("statusCode").toString() + JSON_END; + if (!StringUtils.equals(statusCodeNew, statusCodeOld)) { + String patch = jsonDiff.diff(statusCodeOld, statusCodeNew); + String diff = jsonDiff.apply(statusCodeNew, patch); + if (StringUtils.isNotEmpty(diff)) { + diffMap.put("statusCode", diff); + } + } + } + // 对比BODY-JSON参数 + if (httpNew.get("body") != null && httpOld.get("body") != null) { + String bodyStrNew = httpNew.get("body").toString(); + String bodyStrOld = httpOld.get("body").toString(); + if (!StringUtils.equals(bodyStrNew, bodyStrOld)) { + String patch = jsonDiff.diff(bodyStrOld, bodyStrNew); + String diff = jsonDiff.apply(bodyStrNew, patch); + if (StringUtils.isNotEmpty(diff)) { + diffMap.put("body", diff); + } + } + // 对比BODY-FORM参数 + Body bodyNew = JSON.parseObject(bodyStrNew, Body.class); + Body bodyOld = JSON.parseObject(bodyStrOld, Body.class); + + if (CollectionUtils.isNotEmpty(bodyNew.getKvs()) && CollectionUtils.isNotEmpty(bodyOld.getKvs())) { + bodyNew.getKvs().remove(bodyNew.getKvs().size() - 1); + bodyOld.getKvs().remove(bodyOld.getKvs().size() - 1); + } + String bodyFormNew = JSON_START + JSON.toJSONString(bodyNew.getKvs()) + JSON_END; + String bodyFormOld = JSON_START + JSON.toJSONString(bodyOld.getKvs()) + JSON_END; + if (!StringUtils.equals(bodyFormNew, bodyFormOld)) { + String patch = jsonDiff.diff(bodyFormOld, bodyFormNew); + String diff = jsonDiff.apply(bodyFormNew, patch); + if (StringUtils.isNotEmpty(diff)) { + diffMap.put("body_form", diff); + } + } + // 对比BODY-XML参数 + if (!StringUtils.equals(bodyNew.getRaw(), bodyOld.getRaw())) { + diffMap.put("body_raw_1", bodyNew.getRaw()); + diffMap.put("body_raw_2", bodyOld.getRaw()); + } + } + } + private static void diffTcp(MsTCPSampler tcpNew, MsTCPSampler tcpOld, JsonDiff jsonDiff, Map diffMap) { // 对比请求参数 if (CollectionUtils.isNotEmpty(tcpNew.getParameters())) { diff --git a/frontend/src/business/components/history/ChangeHistory.vue b/frontend/src/business/components/history/ChangeHistory.vue index 3581534597..351437bdc0 100644 --- a/frontend/src/business/components/history/ChangeHistory.vue +++ b/frontend/src/business/components/history/ChangeHistory.vue @@ -93,7 +93,7 @@ export default { value.operTime = row.operTime; if (value.columnName === "tags") { this.$refs.tagsHistoryDetail.open(value); - } else if (value.columnName === "request" && + } else if ((value.columnName === "request" || value.columnName === "response")&& (row.operModule === "接口定义" || row.operModule === "接口定義" || row.operModule === "Api definition")) { this.$refs.apiHistoryDetail.open(value); } else { diff --git a/frontend/src/business/components/history/api/ApiHistoryDetail.vue b/frontend/src/business/components/history/api/ApiHistoryDetail.vue index 6da10a38b4..497fef1732 100644 --- a/frontend/src/business/components/history/api/ApiHistoryDetail.vue +++ b/frontend/src/business/components/history/api/ApiHistoryDetail.vue @@ -11,7 +11,7 @@

{{ this.$t('report.test_log_details') }}

- + @@ -65,6 +65,8 @@ export default { this.formatJdbc(diffValue); } else if (diffValue.type === 'DubboSampler') { this.formatDubbo(diffValue); + } else { + this.formatHttp(diffValue); } this.detail.type = diffValue.type; } @@ -97,6 +99,11 @@ export default { } } }, + removeBlankLines(array) { + if (array && array.length > 0 && !array[array.length - 1].name && !array[array.length - 1].value) { + array.splice(array.length - 1, 1); + } + }, formatHttp(diffValue) { this.detail.body = {}; this.detail.headerId = getUUID(); @@ -112,6 +119,7 @@ export default { } if (diffValue.body_form) { let form = (JSON.parse(diffValue.body_form)).root; + this.removeBlankLines(form); this.detail.body.form = form; this.detail.headerId = getUUID(); } @@ -122,16 +130,25 @@ export default { } if (diffValue.header) { let header = (JSON.parse(diffValue.header)).root; + this.removeBlankLines(header); this.detail.header = header; this.detail.headerId = getUUID(); } + if (diffValue.statusCode) { + let statusCode = (JSON.parse(diffValue.statusCode)).root; + this.removeBlankLines(statusCode); + this.detail.statusCode = statusCode; + this.detail.headerId = getUUID(); + } if (diffValue.query) { let query = (JSON.parse(diffValue.query)).root; + this.removeBlankLines(query); this.detail.query = query; this.detail.headerId = getUUID(); } if (diffValue.rest) { let rest = (JSON.parse(diffValue.rest)).root; + this.removeBlankLines(rest); this.detail.rest = rest; this.detail.headerId = getUUID(); } @@ -150,6 +167,7 @@ export default { } if (diffValue.query) { let parameters = (JSON.parse(diffValue.query)).root; + this.removeBlankLines(parameters); this.detail.parameters = parameters; this.detail.headerId = getUUID(); } @@ -161,6 +179,7 @@ export default { } if (diffValue.body_xml) { let parameters = (JSON.parse(diffValue.body_xml)).root; + this.removeBlankLines(parameters); this.detail.body.xml = parameters; this.detail.body.xml_1 = diffValue.body_xml_1; this.detail.body.xml_2 = diffValue.body_xml_2; @@ -189,6 +208,7 @@ export default { } if (diffValue.variables) { let parameters = (JSON.parse(diffValue.variables)).root; + this.removeBlankLines(parameters); this.detail.variables = parameters; this.detail.headerId = getUUID(); } @@ -213,11 +233,13 @@ export default { } if (diffValue.args) { let parameters = (JSON.parse(diffValue.args)).root; + this.removeBlankLines(parameters); this.detail.args = parameters; this.detail.headerId = getUUID(); } if (diffValue.attachment) { let parameters = (JSON.parse(diffValue.attachment)).root; + this.removeBlankLines(parameters); this.detail.attachment = parameters; this.detail.headerId = getUUID(); } diff --git a/frontend/src/business/components/history/api/ApiHttpRequestParams.vue b/frontend/src/business/components/history/api/ApiHttpRequestParams.vue index ac527bfa48..62782a20d2 100644 --- a/frontend/src/business/components/history/api/ApiHttpRequestParams.vue +++ b/frontend/src/business/components/history/api/ApiHttpRequestParams.vue @@ -6,7 +6,9 @@ - + + + @@ -97,7 +99,13 @@ export default { } }, created() { - if (this.request.body && (this.request.body.jsonSchema || this.request.body.form || this.request.body.raw_1 || this.request.body.raw_2)) { + if (this.request.header) { + this.activeName = "headers"; + } else if (this.request.query) { + this.activeName = "parameters"; + } else if (this.request.rest) { + this.activeName = "rest"; + } else if (this.request.body && (this.request.body.jsonSchema || this.request.body.form || this.request.body.raw_1 || this.request.body.raw_2)) { this.activeName = "body"; if (this.request.body.jsonSchema) { this.activeBody = "json"; @@ -108,24 +116,26 @@ export default { if (this.request.body.raw_1 || this.request.body.raw_2) { this.activeBody = "raw"; } - } else if (this.request.query) { - this.activeName = "parameters"; - } else if (this.request.header) { - this.activeName = "headers"; - } else if (this.request.rest) { - this.activeName = "rest"; } else if (this.request.body_config) { this.activeName = "advancedConfig"; } else if (this.request.body_auth) { this.activeName = "authConfig"; + } else if (this.request.statusCode) { + this.activeName = "statusCode"; } this.reloadCodeEdit(); }, watch: { 'request.headerId'() { - if (this.request.body && (this.request.body.jsonSchema || this.request.body.form || this.request.body.raw_1 || this.request.body.raw_2)) { + if (this.request.header) { + this.activeName = "headers"; + } else if (this.request.query) { + this.activeName = "parameters"; + } else if (this.request.rest) { + this.activeName = "rest"; + } else if (this.request.body && (this.request.body.jsonSchema || this.request.body.form || this.request.body.raw_1 || this.request.body.raw_2)) { this.activeName = "body"; - if (this.request.body.json) { + if (this.request.body.jsonSchema) { this.activeBody = "json"; } if (this.request.body.form) { @@ -134,16 +144,12 @@ export default { if (this.request.body.raw_1 || this.request.body.raw_2) { this.activeBody = "raw"; } - } else if (this.request.query) { - this.activeName = "parameters"; - } else if (this.request.header) { - this.activeName = "headers"; - } else if (this.request.rest) { - this.activeName = "rest"; } else if (this.request.body_config) { this.activeName = "advancedConfig"; } else if (this.request.body_auth) { this.activeName = "authConfig"; + } else if (this.request.statusCode) { + this.activeName = "statusCode"; } this.reloadCodeEdit(); }