Merge branch 'master' of https://github.com/metersphere/metersphere
Conflicts: frontend/src/business/components/xpack
This commit is contained in:
commit
6500e0cf4a
|
@ -0,0 +1,150 @@
|
|||
package io.metersphere.api.dto.automation.parse;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.parse.har.HarUtils;
|
||||
import io.metersphere.api.dto.definition.parse.har.model.*;
|
||||
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.jmeter.RequestResult;
|
||||
import io.metersphere.api.jmeter.ResponseResult;
|
||||
import io.metersphere.api.parse.HarScenarioAbstractParser;
|
||||
import io.metersphere.api.service.ApiScenarioModuleService;
|
||||
import io.metersphere.base.domain.ApiScenarioModule;
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class HarScenarioParser extends HarScenarioAbstractParser<ScenarioImport> {
|
||||
|
||||
@Override
|
||||
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
|
||||
Har har = null;
|
||||
try {
|
||||
String sourceStr = getApiTestStr(source);
|
||||
har = HarUtils.read(sourceStr);
|
||||
} catch (Exception e) {
|
||||
MSException.throwException(e.getMessage());
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(har)) {
|
||||
MSException.throwException("解析失败,请确认选择的是 Har 格式!");
|
||||
}
|
||||
|
||||
ScenarioImport scenarioImport = new ScenarioImport();
|
||||
|
||||
String harName = request.getFileName();
|
||||
// 场景步骤
|
||||
LinkedList<MsTestElement> apiScenarioWithBLOBs = new LinkedList<>();
|
||||
// ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
|
||||
// scenario.setName(harName);
|
||||
|
||||
MsScenario msScenario = new MsScenario();
|
||||
msScenario.setName(harName);
|
||||
this.projectId = request.getProjectId();
|
||||
if (!ObjectUtils.isEmpty(har.log)&&!ObjectUtils.isEmpty(har.log.entries)) {
|
||||
parseItem(har.log.entries, msScenario, apiScenarioWithBLOBs);
|
||||
}
|
||||
|
||||
// 生成场景对象
|
||||
List<ApiScenarioWithBLOBs> scenarioWithBLOBs = new LinkedList<>();
|
||||
parseScenarioWithBLOBs(scenarioWithBLOBs, msScenario, request);
|
||||
scenarioImport.setData(scenarioWithBLOBs);
|
||||
return scenarioImport;
|
||||
}
|
||||
|
||||
private void parseScenarioWithBLOBs(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
|
||||
ApiScenarioModule module = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
|
||||
if (module == null) {
|
||||
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
|
||||
module = apiModuleService.getNewModule(msScenario.getName(), projectId, 1);
|
||||
}
|
||||
|
||||
ApiScenarioWithBLOBs scenarioWithBLOBs = parseScenario(msScenario);
|
||||
if (module != null) {
|
||||
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
|
||||
scenarioWithBLOBs.setModulePath("/" + module.getName());
|
||||
}
|
||||
scenarioWithBLOBsList.add(scenarioWithBLOBs);
|
||||
}
|
||||
|
||||
private void parseItem(List<HarEntry> items, MsScenario scenario, LinkedList<MsTestElement> results) {
|
||||
for (HarEntry item : items) {
|
||||
MsHTTPSamplerProxy request = parseHar(item);
|
||||
if (request != null) {
|
||||
results.add(request);
|
||||
}
|
||||
request.setRequestResult(getRequestResult(request,item));
|
||||
}
|
||||
scenario.setHashTree(results);
|
||||
}
|
||||
|
||||
// private List<ScenarioVariable> parseScenarioVariable(List<PostmanKeyValue> postmanKeyValues) {
|
||||
// if (postmanKeyValues == null) {
|
||||
// return null;
|
||||
// }
|
||||
// List<ScenarioVariable> keyValues = new ArrayList<>();
|
||||
// postmanKeyValues.forEach(item -> keyValues.add(new ScenarioVariable(item.getKey(), item.getValue(), item.getDescription(), VariableTypeConstants.CONSTANT.name())));
|
||||
// return keyValues;
|
||||
// }
|
||||
private RequestResult getRequestResult(MsHTTPSamplerProxy samplerProxy,HarEntry harEntry) {
|
||||
HarRequest request = harEntry.request;
|
||||
HarResponse response = harEntry.response;
|
||||
|
||||
RequestResult requestResult = new RequestResult();
|
||||
requestResult.setName("Response");
|
||||
requestResult.setUrl(request.url);
|
||||
requestResult.setMethod(request.method);
|
||||
if(samplerProxy.getBody()!= null){
|
||||
List<KeyValue> keyValueList = new ArrayList<>();
|
||||
if(!ObjectUtils.isEmpty(request.queryString)){
|
||||
for (HarQueryParm model : request.queryString) {
|
||||
KeyValue keyValue = new KeyValue(model.name,model.value);
|
||||
keyValueList.add(keyValue);
|
||||
}
|
||||
}
|
||||
if(!ObjectUtils.isEmpty(request.postData)&&!ObjectUtils.isEmpty(request.postData.params)){
|
||||
for (HarPostParam model : request.postData.params) {
|
||||
KeyValue keyValue = new KeyValue(model.name,model.value);
|
||||
keyValueList.add(keyValue);
|
||||
}
|
||||
}
|
||||
|
||||
requestResult.setBody(JSONArray.toJSONString(keyValueList));
|
||||
}
|
||||
|
||||
requestResult.setHeaders(JSONArray.toJSONString(request.headers));
|
||||
requestResult.setRequestSize(request.bodySize);
|
||||
// requestResult.setStartTime(result.getStartTime());
|
||||
// requestResult.setEndTime(result.getEndTime());
|
||||
// requestResult.setTotalAssertions(result.getAssertionResults().length);
|
||||
// requestResult.setSuccess(result.isSuccessful());
|
||||
// requestResult.setError(result.getErrorCount());
|
||||
if(!ObjectUtils.isEmpty(request.cookies)){
|
||||
requestResult.setCookies(JSONArray.toJSONString(request.cookies));
|
||||
}
|
||||
|
||||
ResponseResult responseResult = requestResult.getResponseResult();
|
||||
responseResult.setHeaders(JSONArray.toJSONString(response.headers));
|
||||
// responseResult.setLatency(result.getLatency());
|
||||
responseResult.setResponseCode(String.valueOf(response.status));
|
||||
responseResult.setResponseSize(response.bodySize);
|
||||
// responseResult.setResponseTime(result.getTime());
|
||||
if(response.content != null && response.content.text != null){
|
||||
responseResult.setBody(response.content.text);
|
||||
responseResult.setResponseMessage(response.content.text);
|
||||
}
|
||||
|
||||
return requestResult;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ public class ScenarioImportParserFactory {
|
|||
return new PostmanScenarioParser();
|
||||
} else if (StringUtils.equals(ApiImportPlatform.Jmeter.name(), platform)) {
|
||||
return new MsJmeterParser();
|
||||
} else if (StringUtils.equals(ApiImportPlatform.Har.name(), platform)) {
|
||||
return new HarScenarioParser();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ public class ApiDefinitionImportParserFactory {
|
|||
return new PostmanDefinitionParser();
|
||||
} else if (StringUtils.equals(ApiImportPlatform.Swagger2.name(), platform)) {
|
||||
return new Swagger2Parser();
|
||||
}else if (StringUtils.equals(ApiImportPlatform.Har.name(), platform)) {
|
||||
return new HarParser();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package io.metersphere.api.dto.definition.parse;
|
||||
|
||||
|
||||
import io.metersphere.api.parse.ApiImportAbstractParser;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/10 11:15 上午
|
||||
* @Description
|
||||
*/
|
||||
public abstract class HarAbstractParser extends ApiImportAbstractParser<ApiDefinitionImport> {
|
||||
|
||||
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
|
||||
if (tags != null) {
|
||||
tags.forEach(tag -> {
|
||||
ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId);
|
||||
apiDefinition.setModuleId(module.getId());
|
||||
});
|
||||
}else {
|
||||
apiDefinition.setModuleId(parentModule.getId());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package io.metersphere.api.dto.definition.parse;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.parse.har.HarUtils;
|
||||
import io.metersphere.api.dto.definition.parse.har.model.*;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.definition.response.HttpResponse;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.XMLUtils;
|
||||
import io.swagger.models.Model;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/10 11:14 上午
|
||||
* @Description
|
||||
*/
|
||||
public class HarParser extends HarAbstractParser {
|
||||
|
||||
private Map<String, Model> definitions = null;
|
||||
|
||||
@Override
|
||||
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
|
||||
Har har = null;
|
||||
try {
|
||||
String sourceStr = getApiTestStr(source);
|
||||
har = HarUtils.read(sourceStr);
|
||||
} catch (Exception e) {
|
||||
MSException.throwException(e.getMessage());
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(har)) {
|
||||
MSException.throwException("解析失败,请确认选择的是 Har 格式!");
|
||||
}
|
||||
|
||||
ApiDefinitionImport definitionImport = new ApiDefinitionImport();
|
||||
this.projectId = request.getProjectId();
|
||||
definitionImport.setData(parseRequests(har, request));
|
||||
return definitionImport;
|
||||
}
|
||||
|
||||
|
||||
private List<ApiDefinitionWithBLOBs> parseRequests(Har har, ApiTestImportRequest importRequest) {
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
|
||||
ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
|
||||
|
||||
List<HarEntry> harEntryList = new ArrayList<>();
|
||||
if (har.log != null && har.log.entries != null) {
|
||||
harEntryList = har.log.entries;
|
||||
}
|
||||
|
||||
for (HarEntry entry : harEntryList) {
|
||||
HarRequest harRequest = entry.request;
|
||||
|
||||
//默认取路径的最后一块
|
||||
String reqName = "";
|
||||
if (harRequest.url != null) {
|
||||
String[] nameArr = harRequest.url.split("/");
|
||||
reqName = nameArr[nameArr.length - 1];
|
||||
}
|
||||
|
||||
if (harRequest != null) {
|
||||
MsHTTPSamplerProxy request = super.buildRequest(reqName, harRequest.url, harRequest.method);
|
||||
ApiDefinitionWithBLOBs apiDefinition = super.buildApiDefinition(request.getId(), reqName, harRequest.url, harRequest.method, importRequest);
|
||||
parseParameters(harRequest, request);
|
||||
parseRequestBody(harRequest, request.getBody());
|
||||
addBodyHeader(request);
|
||||
apiDefinition.setRequest(JSON.toJSONString(request));
|
||||
apiDefinition.setResponse(JSON.toJSONString(parseResponse(entry.response)));
|
||||
buildModule(parentNode, apiDefinition, null);
|
||||
results.add(apiDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private void parseParameters(HarRequest harRequest, MsHTTPSamplerProxy request) {
|
||||
List<HarQueryParm> queryStringList = harRequest.queryString;
|
||||
queryStringList.forEach(harQueryParm -> {
|
||||
parseQueryParameters(harQueryParm, request.getArguments());
|
||||
});
|
||||
List<HarHeader> harHeaderList = harRequest.headers;
|
||||
harHeaderList.forEach(harHeader -> {
|
||||
parseHeaderParameters(harHeader, request.getHeaders());
|
||||
});
|
||||
List<HarCookie> harCookieList = harRequest.cookies;
|
||||
harCookieList.forEach(harCookie -> {
|
||||
parseCookieParameters(harCookie, request.getHeaders());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private String getDefaultStringValue(String val) {
|
||||
return StringUtils.isBlank(val) ? "" : val;
|
||||
}
|
||||
|
||||
private void parseCookieParameters(HarCookie harCookie, List<KeyValue> headers) {
|
||||
addCookie(headers, harCookie.name, harCookie.value, harCookie.comment, false);
|
||||
}
|
||||
|
||||
private void parseHeaderParameters(HarHeader harHeader, List<KeyValue> headers) {
|
||||
addHeader(headers, harHeader.name, harHeader.value,harHeader.comment, "", false);
|
||||
}
|
||||
|
||||
private HttpResponse parseResponse(HarResponse response) {
|
||||
HttpResponse msResponse = new HttpResponse();
|
||||
msResponse.setBody(new Body());
|
||||
msResponse.setHeaders(new ArrayList<>());
|
||||
msResponse.setType(RequestType.HTTP);
|
||||
// todo 状态码要调整?
|
||||
msResponse.setStatusCode(new ArrayList<>());
|
||||
if (response != null) {
|
||||
String responseCode = String.valueOf(response.status);
|
||||
msResponse.getStatusCode().add(new KeyValue(responseCode, responseCode));
|
||||
parseResponseHeader(response, msResponse.getHeaders());
|
||||
parseResponseBody(response, msResponse.getBody());
|
||||
}
|
||||
return msResponse;
|
||||
}
|
||||
|
||||
private void parseResponseHeader(HarResponse response, List<KeyValue> msHeaders) {
|
||||
List<HarHeader> harHeaders = response.headers;
|
||||
if (harHeaders != null) {
|
||||
for (HarHeader header : harHeaders) {
|
||||
msHeaders.add(new KeyValue(header.name, header.value, header.comment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseResponseBody(HarResponse response, Body body) {
|
||||
parseResponseBody(response.content, body);
|
||||
}
|
||||
|
||||
private void parseRequestBody(HarRequest requestBody, Body body) {
|
||||
if (requestBody == null) {
|
||||
return;
|
||||
}
|
||||
HarPostData content = requestBody.postData;
|
||||
if (!StringUtils.equalsIgnoreCase("GET", requestBody.method) || requestBody.postData == null) {
|
||||
return;
|
||||
}
|
||||
String contentType = content.mimeType;
|
||||
if (StringUtils.isEmpty(contentType)) {
|
||||
body.setRaw(content.text);
|
||||
} else {
|
||||
Map<String, Schema> infoMap = new HashMap();
|
||||
|
||||
if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_JSON_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
body.setRaw(content.text);
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_XML_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_XML_VALUE;
|
||||
body.setRaw(parseXmlBody(content.text));
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else {
|
||||
body.setRaw(content.text);
|
||||
}
|
||||
}
|
||||
body.setType(getBodyType(contentType));
|
||||
}
|
||||
|
||||
private void parseResponseBody(HarContent content, Body body) {
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
String contentType = content.mimeType;
|
||||
body.setType(getBodyType(contentType));
|
||||
body.setRaw(content.text);
|
||||
}
|
||||
|
||||
private String parseXmlBody(String xmlString) {
|
||||
JSONObject object = JSONObject.parseObject(getDefaultStringValue(xmlString));
|
||||
return XMLUtils.jsonToXmlStr(object);
|
||||
}
|
||||
|
||||
private void parseQueryParameters(HarQueryParm harQueryParm, List<KeyValue> arguments) {
|
||||
arguments.add(new KeyValue(harQueryParm.name, harQueryParm.value, harQueryParm.comment, false));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import io.metersphere.api.dto.definition.parse.har.model.Har;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Utility class for working with HAR files.
|
||||
*
|
||||
* @author sangupta
|
||||
*
|
||||
*/
|
||||
public class HarUtils {
|
||||
|
||||
public static Har read(File file) throws JsonSyntaxException, IOException {
|
||||
Har har = JSONObject.parseObject(FileUtils.readFileToString(file), Har.class);
|
||||
return har;
|
||||
}
|
||||
|
||||
|
||||
public static Har read(String harJson) throws JsonSyntaxException, IOException {
|
||||
if(StringUtils.isEmpty(harJson)) {
|
||||
throw new IllegalArgumentException("HAR Json cannot be null/empty");
|
||||
}
|
||||
Har har = JSONObject.parseObject(harJson, Har.class);
|
||||
return har;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
///**
|
||||
// *
|
||||
// * har - HAR file reader, writer and viewer
|
||||
// * Copyright (c) 2014, Sandeep Gupta
|
||||
// *
|
||||
// * http://sangupta.com/projects/har
|
||||
// *
|
||||
// * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// * you may not use this file except in compliance with the License.
|
||||
// * You may obtain a copy of the License at
|
||||
// *
|
||||
// * http://www.apache.org/licenses/LICENSE-2.0
|
||||
// *
|
||||
// * Unless required by applicable law or agreed to in writing, software
|
||||
// * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// * See the License for the specific language governing permissions and
|
||||
// * limitations under the License.
|
||||
// *
|
||||
// */
|
||||
//
|
||||
//package io.metersphere.api.dto.definition.parse.har.command;
|
||||
//
|
||||
//import java.io.File;
|
||||
//
|
||||
//import com.sangupta.har.HarUtils;
|
||||
//import com.sangupta.har.model.Har;
|
||||
//import com.sangupta.har.model.HarEntry;
|
||||
//import com.sangupta.har.model.HarPage;
|
||||
//import com.sangupta.jerry.util.AssertUtils;
|
||||
//
|
||||
//import io.airlift.command.Arguments;
|
||||
//import io.airlift.command.Command;
|
||||
//
|
||||
//@Command(name = "view", description = "View HAR file")
|
||||
//public class ViewHar implements Runnable {
|
||||
//
|
||||
// @Arguments
|
||||
// private String file;
|
||||
//
|
||||
// @Override
|
||||
// public void run() {
|
||||
// Har har = null;
|
||||
//
|
||||
// try {
|
||||
// har = HarUtils.read(new File(this.file));
|
||||
// } catch(Exception e) {
|
||||
// System.out.println("Error reading HAR file: " + e.getMessage());
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(har.log == null || AssertUtils.isEmpty(har.log.pages)) {
|
||||
// System.out.println("HAR file has no pages!");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // connect references
|
||||
// HarUtils.connectReferences(har);
|
||||
//
|
||||
// // start displaying
|
||||
// System.out.println("Number of pages viewed: " + har.log.pages.size());
|
||||
// System.out.println();
|
||||
//
|
||||
// for(HarPage page : har.log.pages) {
|
||||
// System.out.println(page);
|
||||
//
|
||||
// // output the calls for this page
|
||||
// for(HarEntry entry : page.entries) {
|
||||
// System.out.println("\t" + entry);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class Har {
|
||||
|
||||
public HarLog log;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Har [log=" + log + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarCache {
|
||||
|
||||
public HarCacheDetails beforeRequest;
|
||||
|
||||
public HarCacheDetails afterRequest;
|
||||
|
||||
public String comment;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarCacheDetails {
|
||||
|
||||
public String expires;
|
||||
|
||||
public String lastAccess;
|
||||
|
||||
public String etag;
|
||||
|
||||
public String hitCount;
|
||||
|
||||
public String comment;
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarContent {
|
||||
|
||||
public long size;
|
||||
|
||||
public String mimeType;
|
||||
|
||||
public long compression;
|
||||
|
||||
public String text;
|
||||
|
||||
public String comment;
|
||||
|
||||
public String encoding;
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarCookie {
|
||||
|
||||
public String name;
|
||||
|
||||
public String value;
|
||||
|
||||
public String path;
|
||||
|
||||
public String expires;
|
||||
|
||||
public boolean httpOnly;
|
||||
|
||||
public boolean secure;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Cookie: " + this.name + "=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.name == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof HarCookie)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.name == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HarCookie harCookie = (HarCookie) obj;
|
||||
return this.name.equals(harCookie.name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarCreator {
|
||||
|
||||
public String name;
|
||||
|
||||
public String version;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarCreator [name=" + name + ", version=" + version + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarEntry implements Comparable<HarEntry> {
|
||||
|
||||
public String pageref;
|
||||
|
||||
public String startedDateTime;
|
||||
|
||||
public double time;
|
||||
|
||||
public HarRequest request;
|
||||
|
||||
public HarResponse response;
|
||||
|
||||
public HarCache cache;
|
||||
|
||||
public HarTiming timings;
|
||||
|
||||
public String serverIPAddress;
|
||||
|
||||
public String connection;
|
||||
|
||||
public String comment;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarEntry [pageref=" + pageref + ", startedDateTime=" + startedDateTime + ", time=" + time + ", request="
|
||||
+ request + ", response=" + response + ", cache=" + cache + ", timings=" + timings
|
||||
+ ", serverIPAddress=" + serverIPAddress + ", connection=" + connection + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(HarEntry o) {
|
||||
if(o == null) {
|
||||
return -1;
|
||||
}
|
||||
// parse the time and then return
|
||||
return this.startedDateTime.compareTo(o.startedDateTime);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarHeader {
|
||||
|
||||
public String name;
|
||||
|
||||
public String value;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Header: " + this.name + "=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.name == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof HarHeader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.name == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HarHeader harHeader = (HarHeader) obj;
|
||||
return this.name.equals(harHeader.name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HarLog {
|
||||
|
||||
public static final String DEFAULT_HAR_VERSION = "1.2";
|
||||
|
||||
public String version = DEFAULT_HAR_VERSION;
|
||||
|
||||
public HarCreator creator;
|
||||
|
||||
public HarCreator browser;
|
||||
|
||||
public List<HarPage> pages;
|
||||
|
||||
public List<HarEntry> entries;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarLog [version=" + version + ", creator=" + creator + ", browser=" + browser + ", pages=" + pages
|
||||
+ ", entries=" + entries + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HarPage {
|
||||
|
||||
public String startedDateTime;
|
||||
|
||||
public String id;
|
||||
|
||||
public String title;
|
||||
|
||||
public HarPageTiming pageTimings;
|
||||
|
||||
public String comment;
|
||||
|
||||
public transient List<HarEntry> entries;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarPage [startedDateTime=" + startedDateTime + ", id=" + id + ", title=" + title + ", pageTimings="
|
||||
+ pageTimings + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.id == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof HarPage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.id == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HarPage harPage = (HarPage) obj;
|
||||
return this.id.equals(harPage.id);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarPageTiming {
|
||||
|
||||
public double onContentLoad;
|
||||
|
||||
public double onLoad;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarPageTiming [onContentLoad=" + onContentLoad + ", onLoad=" + onLoad + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HarPostData {
|
||||
|
||||
public String mimeType;
|
||||
|
||||
public List<HarPostParam> params;
|
||||
|
||||
public String text;
|
||||
|
||||
public String comment;
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarPostParam {
|
||||
|
||||
public String name;
|
||||
|
||||
public String value;
|
||||
|
||||
public String fileName;
|
||||
|
||||
public String contentType;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Post Param: " + this.name + "=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.name == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof HarPostParam)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.name == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HarPostParam harPostParam = (HarPostParam) obj;
|
||||
return this.name.equals(harPostParam.name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarQueryParm {
|
||||
|
||||
public String name;
|
||||
|
||||
public String value;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Query Param: " + this.name + "=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.name == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof HarQueryParm)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.name == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HarQueryParm harQueryParm = (HarQueryParm) obj;
|
||||
return this.name.equals(harQueryParm.name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HarRequest {
|
||||
|
||||
public String method;
|
||||
|
||||
public String url;
|
||||
|
||||
public String httpVersion;
|
||||
|
||||
public List<HarCookie> cookies;
|
||||
|
||||
public List<HarHeader> headers;
|
||||
|
||||
public List<HarQueryParm> queryString;
|
||||
|
||||
public HarPostData postData;
|
||||
|
||||
public long headersSize;
|
||||
|
||||
public long bodySize;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.method + " " + this.url + " " + this.httpVersion;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HarResponse {
|
||||
|
||||
public int status;
|
||||
|
||||
public String statusText;
|
||||
|
||||
public String httpVersion;
|
||||
|
||||
public List<HarHeader> headers;
|
||||
|
||||
public List<HarCookie> cookies;
|
||||
|
||||
public HarContent content;
|
||||
|
||||
public String redirectURL;
|
||||
|
||||
public long headersSize;
|
||||
|
||||
public long bodySize;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HTTP " + this.status + " (" + this.statusText + ")";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
*
|
||||
* har - HAR file reader, writer and viewer
|
||||
* Copyright (c) 2014, Sandeep Gupta
|
||||
*
|
||||
* http://sangupta.com/projects/har
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.metersphere.api.dto.definition.parse.har.model;
|
||||
|
||||
public class HarTiming {
|
||||
|
||||
public double blocked;
|
||||
|
||||
public double dns;
|
||||
|
||||
public double connect;
|
||||
|
||||
public double send;
|
||||
|
||||
public double wait;
|
||||
|
||||
public double receive;
|
||||
|
||||
public double ssl;
|
||||
|
||||
public String comment;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HarTiming [blocked=" + blocked + ", dns=" + dns + ", connect=" + connect + ", send=" + send + ", wait="
|
||||
+ wait + ", receive=" + receive + ", ssl=" + ssl + ", comment=" + comment + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -40,6 +40,8 @@ public class MsJSR223Processor extends MsTestElement {
|
|||
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
||||
processor.setName(this.getName() + "<->" + name);
|
||||
}
|
||||
processor.setProperty("MS-ID", this.getId());
|
||||
|
||||
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||
processor.setProperty("cacheKey", "true");
|
||||
|
|
|
@ -82,6 +82,7 @@ public class MsDubboSampler extends MsTestElement {
|
|||
}
|
||||
sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName());
|
||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DubboSampleGui"));
|
||||
sampler.setProperty("MS-ID", this.getId());
|
||||
|
||||
sampler.addTestElement(configCenter(this.getConfigCenter()));
|
||||
sampler.addTestElement(registryCenter(this.getRegistryCenter()));
|
||||
|
|
|
@ -85,8 +85,8 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
|||
@JSONField(ordinal = 34)
|
||||
private List<KeyValue> arguments;
|
||||
|
||||
// @JSONField(ordinal = 35)
|
||||
// private Object requestResult;
|
||||
@JSONField(ordinal = 35)
|
||||
private Object requestResult;
|
||||
|
||||
@JSONField(ordinal = 36)
|
||||
private MsAuthManager authManager;
|
||||
|
@ -106,6 +106,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
|||
}
|
||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
||||
sampler.setProperty("MS-ID", this.getId());
|
||||
sampler.setMethod(this.getMethod());
|
||||
sampler.setContentEncoding("UTF-8");
|
||||
sampler.setConnectTimeout(this.getConnectTimeout() == null ? "6000" : this.getConnectTimeout());
|
||||
|
|
|
@ -119,6 +119,8 @@ public class MsJDBCSampler extends MsTestElement {
|
|||
}
|
||||
sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName());
|
||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||
sampler.setProperty("MS-ID", this.getId());
|
||||
|
||||
// request.getDataSource() 是ID,需要转换为Name
|
||||
sampler.setProperty("dataSource", this.dataSource.getName());
|
||||
sampler.setProperty("query", this.getQuery());
|
||||
|
|
|
@ -117,6 +117,7 @@ public class MsTCPSampler extends MsTestElement {
|
|||
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
||||
tcpSampler.setName(this.getName() + "<->" + name);
|
||||
}
|
||||
tcpSampler.setProperty("MS-ID", this.getId());
|
||||
|
||||
tcpSampler.setProperty(TestElement.TEST_CLASS, TCPSampler.class.getName());
|
||||
tcpSampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TCPSamplerGui"));
|
||||
|
|
|
@ -239,7 +239,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
sendTask(report, reportUrl, testResult);
|
||||
sendTask(report, reportUrl, testResult);
|
||||
}
|
||||
|
||||
private static void sendTask(ApiTestReport report, String reportUrl, TestResult testResult) {
|
||||
|
@ -303,6 +303,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
|
||||
private RequestResult getRequestResult(SampleResult result) {
|
||||
RequestResult requestResult = new RequestResult();
|
||||
requestResult.setId(result.getSamplerId());
|
||||
requestResult.setName(result.getSampleLabel());
|
||||
requestResult.setUrl(result.getUrlAsString());
|
||||
requestResult.setMethod(getMethod(result));
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.List;
|
|||
|
||||
@Data
|
||||
public class RequestResult {
|
||||
// 请求ID
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
package io.metersphere.api.parse;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.definition.parse.har.model.*;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.parse.postman.PostmanEvent;
|
||||
import io.metersphere.api.dto.parse.postman.PostmanKeyValue;
|
||||
import io.metersphere.api.dto.parse.postman.PostmanRequest;
|
||||
import io.metersphere.api.dto.parse.postman.PostmanScript;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.commons.constants.MsRequestBodyType;
|
||||
import io.metersphere.commons.constants.PostmanRequestBodyMode;
|
||||
import io.metersphere.commons.utils.XMLUtils;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class HarScenarioAbstractParser<T> extends ApiImportAbstractParser<T> {
|
||||
|
||||
protected MsHTTPSamplerProxy parseHar(HarEntry harEntry) {
|
||||
HarRequest harRequest = harEntry.request;
|
||||
if (harRequest == null) {
|
||||
return null;
|
||||
}
|
||||
MsHTTPSamplerProxy request = buildRequest(harRequest.url, harRequest.url,harRequest.method);
|
||||
if (StringUtils.isNotBlank(request.getPath())) {
|
||||
String path = request.getPath().split("\\?")[0];
|
||||
path = path.replace("{{", "${");
|
||||
path = path.replace("}}", "}");
|
||||
request.setPath(path);
|
||||
} else {
|
||||
request.setPath("/");
|
||||
}
|
||||
parseParameters(harRequest, request);
|
||||
parseRequestBody(harRequest, request.getBody());
|
||||
addBodyHeader(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
private void parseParameters(HarRequest harRequest, MsHTTPSamplerProxy request) {
|
||||
List<HarQueryParm> queryStringList = harRequest.queryString;
|
||||
queryStringList.forEach(harQueryParm -> {
|
||||
parseQueryParameters(harQueryParm, request.getArguments());
|
||||
});
|
||||
List<HarHeader> harHeaderList = harRequest.headers;
|
||||
harHeaderList.forEach(harHeader -> {
|
||||
parseHeaderParameters(harHeader, request.getHeaders());
|
||||
});
|
||||
List<HarCookie> harCookieList = harRequest.cookies;
|
||||
harCookieList.forEach(harCookie -> {
|
||||
parseCookieParameters(harCookie, request.getHeaders());
|
||||
});
|
||||
}
|
||||
private void parseRequestBody(HarRequest requestBody, Body body) {
|
||||
if (requestBody == null) {
|
||||
return;
|
||||
}
|
||||
HarPostData content = requestBody.postData;
|
||||
if (!StringUtils.equalsIgnoreCase("GET", requestBody.method) || requestBody.postData == null) {
|
||||
return;
|
||||
}
|
||||
String contentType = content.mimeType;
|
||||
if (StringUtils.isEmpty(contentType)) {
|
||||
body.setRaw(content.text);
|
||||
} else {
|
||||
Map<String, Schema> infoMap = new HashMap();
|
||||
|
||||
if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_JSON_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
body.setRaw(content.text);
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_XML_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_XML_VALUE;
|
||||
body.setRaw(parseXmlBody(content.text));
|
||||
} else if (contentType.startsWith(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE)) {
|
||||
contentType = org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
List<HarPostParam> postParams = content.params;
|
||||
for (HarPostParam postParam : postParams) {
|
||||
KeyValue kv = new KeyValue(postParam.name,postParam.value);
|
||||
body.getKvs().add(kv);
|
||||
}
|
||||
} else {
|
||||
body.setRaw(content.text);
|
||||
}
|
||||
}
|
||||
body.setType(getBodyType(contentType));
|
||||
}
|
||||
|
||||
|
||||
private void parseQueryParameters(HarQueryParm harQueryParm, List<KeyValue> arguments) {
|
||||
arguments.add(new KeyValue(harQueryParm.name, harQueryParm.value, harQueryParm.comment, false));
|
||||
}
|
||||
private void parseCookieParameters(HarCookie harCookie, List<KeyValue> headers) {
|
||||
addCookie(headers, harCookie.name, harCookie.value, harCookie.comment, false);
|
||||
}
|
||||
|
||||
private void parseHeaderParameters(HarHeader harHeader, List<KeyValue> headers) {
|
||||
addHeader(headers, harHeader.name, harHeader.value,harHeader.comment, "", false);
|
||||
}
|
||||
|
||||
private void addPreScript(MsHTTPSamplerProxy request, List<PostmanEvent> event) {
|
||||
if (request != null && CollectionUtils.isNotEmpty(event)) {
|
||||
StringBuilder scriptStr = new StringBuilder();
|
||||
event = event.stream()
|
||||
.filter(item -> item.getScript() != null)
|
||||
.collect(Collectors.toList());
|
||||
event.forEach(item -> {
|
||||
PostmanScript script = item.getScript();
|
||||
if (script != null && item.getListen().contains("prerequest")) {
|
||||
List<String> exec = script.getExec();
|
||||
if (CollectionUtils.isNotEmpty(exec)) {
|
||||
exec.forEach(col -> {
|
||||
if (StringUtils.isNotEmpty(col)) {
|
||||
scriptStr.append(col + "\n");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (StringUtils.isNotBlank(scriptStr)) {
|
||||
MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor();
|
||||
jsr223PreProcessor.setName("JSR223PreProcessor");
|
||||
jsr223PreProcessor.setScriptLanguage("javascript");
|
||||
jsr223PreProcessor.setScript(scriptStr.toString());
|
||||
LinkedList<MsTestElement> hashTree = new LinkedList<>();
|
||||
hashTree.add(jsr223PreProcessor);
|
||||
request.setHashTree(hashTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<KeyValue> parseKeyValue(List<PostmanKeyValue> postmanKeyValues) {
|
||||
if (postmanKeyValues == null) {
|
||||
return null;
|
||||
}
|
||||
List<KeyValue> keyValues = new ArrayList<>();
|
||||
postmanKeyValues.forEach(item -> keyValues.add(new KeyValue(item.getKey(), item.getValue(), item.getDescription(), item.getContentType())));
|
||||
return keyValues;
|
||||
}
|
||||
|
||||
private void parseBody(Body body, PostmanRequest requestDesc) {
|
||||
JSONObject postmanBody = requestDesc.getBody();
|
||||
if (postmanBody == null) {
|
||||
return;
|
||||
}
|
||||
String bodyMode = postmanBody.getString("mode");
|
||||
if (StringUtils.isBlank(bodyMode)) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
|
||||
parseRawBody(body, postmanBody, bodyMode);
|
||||
} else if (StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {
|
||||
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.getString(bodyMode), PostmanKeyValue.class);
|
||||
body.setKvs(parseKeyValue(postmanKeyValues));
|
||||
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value())) {
|
||||
body.setType(Body.FORM_DATA);
|
||||
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.URLENCODED.value())) {
|
||||
body.setType(Body.WWW_FROM);
|
||||
}
|
||||
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FILE.value())) {
|
||||
body.setType(Body.BINARY);
|
||||
body.setKvs(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
private String parseXmlBody(String xmlString) {
|
||||
JSONObject object = JSONObject.parseObject(getDefaultStringValue(xmlString));
|
||||
return XMLUtils.jsonToXmlStr(object);
|
||||
}
|
||||
|
||||
private void parseRawBody(Body body, JSONObject postmanBody, String bodyMode) {
|
||||
body.setRaw(postmanBody.getString(bodyMode));
|
||||
body.setType(MsRequestBodyType.RAW.value());
|
||||
JSONObject options = postmanBody.getJSONObject("options");
|
||||
if (options != null) {
|
||||
JSONObject raw = options.getJSONObject(PostmanRequestBodyMode.RAW.value());
|
||||
if (raw != null) {
|
||||
String bodyType = "";
|
||||
switch (raw.getString("language")) {
|
||||
case "json":
|
||||
bodyType = Body.JSON;
|
||||
break;
|
||||
case "xml":
|
||||
bodyType = Body.XML;
|
||||
break;
|
||||
default:
|
||||
bodyType = Body.RAW;
|
||||
}
|
||||
body.setType(bodyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getDefaultStringValue(String val) {
|
||||
return StringUtils.isBlank(val) ? "" : val;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiDefinition implements Serializable {
|
||||
|
@ -38,5 +37,7 @@ public class ApiDefinition implements Serializable {
|
|||
|
||||
private String tags;
|
||||
|
||||
private String originalState;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1193,6 +1193,76 @@ public class ApiDefinitionExample {
|
|||
addCriterion("tags not between", value1, value2, "tags");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIsNull() {
|
||||
addCriterion("original_state is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIsNotNull() {
|
||||
addCriterion("original_state is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateEqualTo(String value) {
|
||||
addCriterion("original_state =", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotEqualTo(String value) {
|
||||
addCriterion("original_state <>", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateGreaterThan(String value) {
|
||||
addCriterion("original_state >", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("original_state >=", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLessThan(String value) {
|
||||
addCriterion("original_state <", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLessThanOrEqualTo(String value) {
|
||||
addCriterion("original_state <=", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLike(String value) {
|
||||
addCriterion("original_state like", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotLike(String value) {
|
||||
addCriterion("original_state not like", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIn(List<String> values) {
|
||||
addCriterion("original_state in", values, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotIn(List<String> values) {
|
||||
addCriterion("original_state not in", values, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateBetween(String value1, String value2) {
|
||||
addCriterion("original_state between", value1, value2, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotBetween(String value1, String value2) {
|
||||
addCriterion("original_state not between", value1, value2, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -43,5 +43,7 @@ public class ApiScenario implements Serializable {
|
|||
|
||||
private Integer num;
|
||||
|
||||
private String originalState;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1393,6 +1393,76 @@ public class ApiScenarioExample {
|
|||
addCriterion("num not between", value1, value2, "num");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIsNull() {
|
||||
addCriterion("original_state is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIsNotNull() {
|
||||
addCriterion("original_state is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateEqualTo(String value) {
|
||||
addCriterion("original_state =", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotEqualTo(String value) {
|
||||
addCriterion("original_state <>", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateGreaterThan(String value) {
|
||||
addCriterion("original_state >", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("original_state >=", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLessThan(String value) {
|
||||
addCriterion("original_state <", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLessThanOrEqualTo(String value) {
|
||||
addCriterion("original_state <=", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateLike(String value) {
|
||||
addCriterion("original_state like", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotLike(String value) {
|
||||
addCriterion("original_state not like", value, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateIn(List<String> values) {
|
||||
addCriterion("original_state in", values, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotIn(List<String> values) {
|
||||
addCriterion("original_state not in", values, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateBetween(String value1, String value2) {
|
||||
addCriterion("original_state between", value1, value2, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andOriginalStateNotBetween(String value1, String value2) {
|
||||
addCriterion("original_state not between", value1, value2, "originalState");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<result column="path" jdbcType="VARCHAR" property="path" />
|
||||
<result column="num" jdbcType="INTEGER" property="num" />
|
||||
<result column="tags" jdbcType="VARCHAR" property="tags" />
|
||||
<result column="original_state" jdbcType="VARCHAR" property="originalState" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
||||
<result column="description" jdbcType="LONGVARCHAR" property="description" />
|
||||
|
@ -84,7 +85,7 @@
|
|||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, project_id, `name`, `method`, module_path, environment_id, schedule, `status`,
|
||||
module_id, user_id, create_time, update_time, protocol, `path`, num, tags
|
||||
module_id, user_id, create_time, update_time, protocol, `path`, num, tags, original_state
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
description, request, response
|
||||
|
@ -143,15 +144,15 @@
|
|||
schedule, `status`, module_id,
|
||||
user_id, create_time, update_time,
|
||||
protocol, `path`, num,
|
||||
tags, description, request,
|
||||
response)
|
||||
tags, original_state, description,
|
||||
request, response)
|
||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{method,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR},
|
||||
#{schedule,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
|
||||
#{userId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{protocol,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
|
||||
#{tags,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR},
|
||||
#{response,jdbcType=LONGVARCHAR})
|
||||
#{tags,jdbcType=VARCHAR}, #{originalState,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR},
|
||||
#{request,jdbcType=LONGVARCHAR}, #{response,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
||||
insert into api_definition
|
||||
|
@ -204,6 +205,9 @@
|
|||
<if test="tags != null">
|
||||
tags,
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
original_state,
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description,
|
||||
</if>
|
||||
|
@ -263,6 +267,9 @@
|
|||
<if test="tags != null">
|
||||
#{tags,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
#{originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
#{description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -331,6 +338,9 @@
|
|||
<if test="record.tags != null">
|
||||
tags = #{record.tags,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.originalState != null">
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.description != null">
|
||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -363,6 +373,7 @@
|
|||
`path` = #{record.path,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
tags = #{record.tags,jdbcType=VARCHAR},
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||
request = #{record.request,jdbcType=LONGVARCHAR},
|
||||
response = #{record.response,jdbcType=LONGVARCHAR}
|
||||
|
@ -387,7 +398,8 @@
|
|||
protocol = #{record.protocol,jdbcType=VARCHAR},
|
||||
`path` = #{record.path,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
tags = #{record.tags,jdbcType=VARCHAR}
|
||||
tags = #{record.tags,jdbcType=VARCHAR},
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -440,6 +452,9 @@
|
|||
<if test="tags != null">
|
||||
tags = #{tags,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
original_state = #{originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description = #{description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -469,6 +484,7 @@
|
|||
`path` = #{path,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
tags = #{tags,jdbcType=VARCHAR},
|
||||
original_state = #{originalState,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=LONGVARCHAR},
|
||||
request = #{request,jdbcType=LONGVARCHAR},
|
||||
response = #{response,jdbcType=LONGVARCHAR}
|
||||
|
@ -490,7 +506,8 @@
|
|||
protocol = #{protocol,jdbcType=VARCHAR},
|
||||
`path` = #{path,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
tags = #{tags,jdbcType=VARCHAR}
|
||||
tags = #{tags,jdbcType=VARCHAR},
|
||||
original_state = #{originalState,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -21,6 +21,7 @@
|
|||
<result column="last_result" jdbcType="VARCHAR" property="lastResult" />
|
||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||
<result column="num" jdbcType="INTEGER" property="num" />
|
||||
<result column="original_state" jdbcType="VARCHAR" property="originalState" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
||||
<result column="scenario_definition" jdbcType="LONGVARCHAR" property="scenarioDefinition" />
|
||||
|
@ -87,7 +88,7 @@
|
|||
<sql id="Base_Column_List">
|
||||
id, project_id, tags, user_id, api_scenario_module_id, module_path, `name`, `level`,
|
||||
`status`, principal, step_total, follow_people, schedule, create_time, update_time,
|
||||
pass_rate, last_result, report_id, num
|
||||
pass_rate, last_result, report_id, num, original_state
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
scenario_definition, description
|
||||
|
@ -147,16 +148,16 @@
|
|||
principal, step_total, follow_people,
|
||||
schedule, create_time, update_time,
|
||||
pass_rate, last_result, report_id,
|
||||
num, scenario_definition, description
|
||||
)
|
||||
num, original_state, scenario_definition,
|
||||
description)
|
||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR},
|
||||
#{userId,jdbcType=VARCHAR}, #{apiScenarioModuleId,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR},
|
||||
#{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||
#{principal,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{followPeople,jdbcType=VARCHAR},
|
||||
#{schedule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
|
||||
#{num,jdbcType=INTEGER}, #{scenarioDefinition,jdbcType=LONGVARCHAR}, #{description,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
#{num,jdbcType=INTEGER}, #{originalState,jdbcType=VARCHAR}, #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
#{description,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
||||
insert into api_scenario
|
||||
|
@ -218,6 +219,9 @@
|
|||
<if test="num != null">
|
||||
num,
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
original_state,
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition,
|
||||
</if>
|
||||
|
@ -283,6 +287,9 @@
|
|||
<if test="num != null">
|
||||
#{num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
#{originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
#{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -357,6 +364,9 @@
|
|||
<if test="record.num != null">
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.originalState != null">
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.scenarioDefinition != null">
|
||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -389,6 +399,7 @@
|
|||
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
description = #{record.description,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
|
@ -415,7 +426,8 @@
|
|||
pass_rate = #{record.passRate,jdbcType=VARCHAR},
|
||||
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER}
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
original_state = #{record.originalState,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -477,6 +489,9 @@
|
|||
<if test="num != null">
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="originalState != null">
|
||||
original_state = #{originalState,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -506,6 +521,7 @@
|
|||
last_result = #{lastResult,jdbcType=VARCHAR},
|
||||
report_id = #{reportId,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
original_state = #{originalState,jdbcType=VARCHAR},
|
||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
description = #{description,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
|
@ -529,7 +545,8 @@
|
|||
pass_rate = #{passRate,jdbcType=VARCHAR},
|
||||
last_result = #{lastResult,jdbcType=VARCHAR},
|
||||
report_id = #{reportId,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER}
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
original_state = #{originalState,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -235,7 +235,7 @@
|
|||
|
||||
<update id="removeToGc">
|
||||
update api_definition
|
||||
set
|
||||
set original_state=status,
|
||||
status = 'Trash'
|
||||
where id in
|
||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||
|
@ -245,7 +245,7 @@
|
|||
|
||||
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample">
|
||||
update api_definition
|
||||
set
|
||||
set original_state=status,
|
||||
status = 'Trash', module_path = null, module_id = null
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
|
@ -255,7 +255,7 @@
|
|||
<update id="reduction">
|
||||
update api_definition
|
||||
set
|
||||
status = 'Underway'
|
||||
status = original_state
|
||||
where id in
|
||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
|
|
|
@ -275,7 +275,7 @@
|
|||
|
||||
<update id="removeToGc">
|
||||
update api_scenario
|
||||
set
|
||||
set original_state=status,
|
||||
status = 'Trash'
|
||||
where id in
|
||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||
|
@ -285,7 +285,7 @@
|
|||
|
||||
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiScenarioExample">
|
||||
update api_scenario
|
||||
set
|
||||
set original_state=status,
|
||||
status = 'Trash', module_path = null, api_scenario_module_id = null
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
|
@ -295,7 +295,7 @@
|
|||
<update id="reduction">
|
||||
update api_scenario
|
||||
set
|
||||
status = 'Underway'
|
||||
status = original_state
|
||||
where id in
|
||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum ApiImportPlatform {
|
||||
Metersphere, Postman, Swagger2, Plugin, Jmeter
|
||||
Metersphere, Postman, Swagger2, Plugin, Jmeter, Har
|
||||
}
|
||||
|
|
|
@ -44,6 +44,10 @@ public class ShiroUtils {
|
|||
// filterChainDefinitionMap.put("/document/**", "anon");
|
||||
}
|
||||
|
||||
public static void ignoreCsrfFilter(Map<String, String> filterChainDefinitionMap) {
|
||||
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
|
||||
}
|
||||
|
||||
public static Cookie getSessionIdCookie(){
|
||||
SimpleCookie sessionIdCookie = new SimpleCookie();
|
||||
sessionIdCookie.setPath("/");
|
||||
|
|
|
@ -47,9 +47,11 @@ public class ShiroConfig implements EnvironmentAware {
|
|||
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
|
||||
shiroFilterFactoryBean.getFilters().put("csrf", new CsrfFilter());
|
||||
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
|
||||
|
||||
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
|
||||
|
||||
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
|
||||
ShiroUtils.ignoreCsrfFilter(filterChainDefinitionMap);
|
||||
|
||||
filterChainDefinitionMap.put("/**", "apikey, csrf, authc");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,7 @@ public class EngineContext {
|
|||
private String reportId;
|
||||
private Integer resourceIndex;
|
||||
private Map<String, Object> properties = new HashMap<>();
|
||||
private Map<String, String> testData = new HashMap<>();
|
||||
private Map<String, byte[]> testJars = new HashMap<>();
|
||||
private Map<String, byte[]> testResourceFiles = new HashMap<>();
|
||||
|
||||
public String getTestId() {
|
||||
return testId;
|
||||
|
@ -69,14 +68,6 @@ public class EngineContext {
|
|||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
public Map<String, String> getTestData() {
|
||||
return testData;
|
||||
}
|
||||
|
||||
public void setTestData(Map<String, String> testData) {
|
||||
this.testData = testData;
|
||||
}
|
||||
|
||||
public String getResourcePoolId() {
|
||||
return resourcePoolId;
|
||||
}
|
||||
|
@ -111,11 +102,11 @@ public class EngineContext {
|
|||
}
|
||||
|
||||
|
||||
public Map<String, byte[]> getTestJars() {
|
||||
return testJars;
|
||||
public Map<String, byte[]> getTestResourceFiles() {
|
||||
return testResourceFiles;
|
||||
}
|
||||
|
||||
public void setTestJars(Map<String, byte[]> testJars) {
|
||||
this.testJars = testJars;
|
||||
public void setTestResourceFiles(Map<String, byte[]> testResourceFiles) {
|
||||
this.testResourceFiles = testResourceFiles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import io.metersphere.service.FileService;
|
|||
import io.metersphere.service.KubernetesTestEngine;
|
||||
import io.metersphere.service.TestResourcePoolService;
|
||||
import org.apache.commons.beanutils.ConstructorUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.reflections8.Reflections;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -92,8 +93,7 @@ public class EngineFactory {
|
|||
}
|
||||
|
||||
List<FileMetadata> jmxFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.JMX.name())).collect(Collectors.toList());
|
||||
List<FileMetadata> csvFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.CSV.name())).collect(Collectors.toList());
|
||||
List<FileMetadata> jarFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.JAR.name())).collect(Collectors.toList());
|
||||
List<FileMetadata> resourceFiles = ListUtils.subtract(fileMetadataList, jmxFiles);
|
||||
// 合并上传的jmx
|
||||
byte[] jmxBytes = mergeJmx(jmxFiles);
|
||||
final EngineContext engineContext = new EngineContext();
|
||||
|
@ -156,22 +156,13 @@ public class EngineFactory {
|
|||
MSException.throwException(e);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(csvFiles)) {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
csvFiles.forEach(cf -> {
|
||||
FileContent csvContent = fileService.getFileContent(cf.getId());
|
||||
data.put(cf.getName(), new String(csvContent.getFile()));
|
||||
});
|
||||
engineContext.setTestData(data);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(jarFiles)) {
|
||||
if (CollectionUtils.isNotEmpty(resourceFiles)) {
|
||||
Map<String, byte[]> data = new HashMap<>();
|
||||
jarFiles.forEach(jf -> {
|
||||
FileContent content = fileService.getFileContent(jf.getId());
|
||||
data.put(jf.getName(), content.getFile());
|
||||
resourceFiles.forEach(cf -> {
|
||||
FileContent csvContent = fileService.getFileContent(cf.getId());
|
||||
data.put(cf.getName(), csvContent.getFile());
|
||||
});
|
||||
engineContext.setTestJars(data);
|
||||
engineContext.setTestResourceFiles(data);
|
||||
}
|
||||
|
||||
return engineContext;
|
||||
|
|
|
@ -51,17 +51,9 @@ public class JmeterFileService {
|
|||
|
||||
// 每个测试生成一个文件夹
|
||||
files.put(fileName, context.getContent().getBytes(StandardCharsets.UTF_8));
|
||||
// 保存测试数据文件
|
||||
Map<String, String> testData = context.getTestData();
|
||||
if (!CollectionUtils.isEmpty(testData)) {
|
||||
for (String k : testData.keySet()) {
|
||||
String v = testData.get(k);
|
||||
files.put(k, v.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
// 保存 byte[] jar
|
||||
Map<String, byte[]> jarFiles = context.getTestJars();
|
||||
// 保存 byte[]
|
||||
Map<String, byte[]> jarFiles = context.getTestResourceFiles();
|
||||
if (!CollectionUtils.isEmpty(jarFiles)) {
|
||||
for (String k : jarFiles.keySet()) {
|
||||
byte[] v = jarFiles.get(k);
|
||||
|
|
|
@ -32,6 +32,12 @@ public class CsrfFilter extends AnonymousFilter {
|
|||
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
|
||||
return true;
|
||||
}
|
||||
// websocket 不需要csrf
|
||||
String websocketKey = httpServletRequest.getHeader("Sec-WebSocket-Key");
|
||||
if (StringUtils.isNotBlank(websocketKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 请求头取出的token value
|
||||
String csrfToken = httpServletRequest.getHeader(TOKEN_NAME);
|
||||
// 校验 token
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,4 +44,10 @@ ALTER TABLE test_case_review ADD tags VARCHAR(2000) NULL;
|
|||
alter table test_plan_api_scenario change environment_id environment longtext null comment 'Relevance environment';
|
||||
|
||||
-- file add sort column
|
||||
alter table file_metadata add sort int default 0;
|
||||
alter table file_metadata add sort int default 0;
|
||||
|
||||
-- add Original state
|
||||
alter table api_definition add original_state varchar(64);
|
||||
alter table api_scenario add original_state varchar(64);
|
||||
update api_definition set original_state='Underway';
|
||||
update api_scenario set original_state='Underway';
|
|
@ -17,7 +17,6 @@
|
|||
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||
"axios": "^0.21.1",
|
||||
"core-js": "^3.4.3",
|
||||
"default-passive-events": "^2.0.0",
|
||||
"diffable-html": "^4.0.0",
|
||||
"echarts": "^4.6.0",
|
||||
"el-table-infinite-scroll": "^1.0.10",
|
||||
|
|
|
@ -100,6 +100,19 @@
|
|||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
},
|
||||
formatResult(res) {
|
||||
let resMap = new Map;
|
||||
if (res && res.scenarios) {
|
||||
res.scenarios.forEach(item => {
|
||||
if (item && item.requestResults) {
|
||||
item.requestResults.forEach(req => {
|
||||
resMap.set(req.id, req);
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
this.$emit('refresh', resMap);
|
||||
},
|
||||
getReport() {
|
||||
this.init();
|
||||
if (this.reportId) {
|
||||
|
@ -113,7 +126,7 @@
|
|||
if (!this.content) {
|
||||
this.content = {scenarios: []};
|
||||
}
|
||||
this.$emit('refresh');
|
||||
this.formatResult(this.content);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -276,7 +276,9 @@
|
|||
},
|
||||
{
|
||||
name: this.$t('test_track.case.batch_move_case'), handleClick: this.handleBatchMove
|
||||
}
|
||||
},
|
||||
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
|
||||
|
||||
],
|
||||
isSelectAllDate: false,
|
||||
selectRows: new Set(),
|
||||
|
@ -596,6 +598,29 @@
|
|||
this.search();
|
||||
})
|
||||
},
|
||||
handleDeleteBatch(row) {
|
||||
if (this.trashEnable) {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/api/automation/deleteBatch/', ids, () => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.$alert(this.$t('api_test.definition.request.delete_confirm') + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/api/automation/removeToGc/', ids, () => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
execute(row) {
|
||||
this.infoDb = false;
|
||||
let url = "/api/automation/run";
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
<!-- 调试结果 -->
|
||||
<el-drawer v-if="type!=='detail'" :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr"
|
||||
:withHeader="true" :modal="false" size="90%">
|
||||
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/>
|
||||
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId" @refresh="detailRefresh"/>
|
||||
</el-drawer>
|
||||
|
||||
<!--场景公共参数-->
|
||||
|
@ -291,7 +291,8 @@
|
|||
response: {},
|
||||
projectIds: new Set,
|
||||
projectEnvMap: new Map,
|
||||
projectList: []
|
||||
projectList: [],
|
||||
debugResult: new Map,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -548,21 +549,32 @@
|
|||
if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
|
||||
this.recursiveSorting(arr[i].hashTree);
|
||||
}
|
||||
// 添加debug结果
|
||||
if (this.debugResult && this.debugResult.get(arr[i].id)) {
|
||||
arr[i].requestResult = this.debugResult.get(arr[i].id);
|
||||
}
|
||||
}
|
||||
},
|
||||
sort() {
|
||||
for (let i in this.scenarioDefinition) {
|
||||
// 排序
|
||||
this.scenarioDefinition[i].index = Number(i) + 1;
|
||||
// 设置循环控制
|
||||
if (this.scenarioDefinition[i].type === ELEMENT_TYPE.LoopController && this.scenarioDefinition[i].hashTree
|
||||
&& this.scenarioDefinition[i].hashTree.length > 1) {
|
||||
this.scenarioDefinition[i].countController.proceed = true;
|
||||
}
|
||||
// 设置项目ID
|
||||
if (!this.scenarioDefinition[i].projectId) {
|
||||
this.scenarioDefinition[i].projectId = getCurrentProjectID();
|
||||
}
|
||||
if (this.scenarioDefinition[i].hashTree != undefined && this.scenarioDefinition[i].hashTree.length > 0) {
|
||||
this.recursiveSorting(this.scenarioDefinition[i].hashTree);
|
||||
}
|
||||
// 添加debug结果
|
||||
if (this.debugResult && this.debugResult.get(this.scenarioDefinition[i].id)) {
|
||||
this.scenarioDefinition[i].requestResult = this.debugResult.get(this.scenarioDefinition[i].id);
|
||||
}
|
||||
}
|
||||
},
|
||||
addCustomizeApi(request) {
|
||||
|
@ -1026,6 +1038,11 @@
|
|||
arr.forEach(a => this.projectIds.add(a));
|
||||
})
|
||||
})
|
||||
},
|
||||
detailRefresh(result) {
|
||||
// 把执行结果分发给各个请求
|
||||
this.debugResult = result;
|
||||
this.sort()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.import_mode')">
|
||||
<el-form-item v-if="!isHar" :label="$t('commons.import_mode')">
|
||||
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
|
||||
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
|
@ -118,6 +118,13 @@
|
|||
tip: this.$t('api_test.api_import.jmeter_tip'),
|
||||
exportTip: this.$t('api_test.api_import.jmeter_export_tip'),
|
||||
suffixes: new Set(['jmx'])
|
||||
},
|
||||
{
|
||||
name: 'Har',
|
||||
value: 'Har',
|
||||
tip: this.$t('api_test.api_import.har_tip'),
|
||||
exportTip: this.$t('api_test.api_import.har_export_tip'),
|
||||
suffixes: new Set(['har'])
|
||||
}
|
||||
],
|
||||
selectedPlatform: {},
|
||||
|
@ -150,6 +157,11 @@
|
|||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isHar() {
|
||||
return this.selectedPlatformValue === 'Har';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
scheduleEdit() {
|
||||
if (!this.formData.swaggerUrl) {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="!isScenarioModel" :label="$t('commons.import_mode')">
|
||||
<el-form-item v-if="!isScenarioModel&&!isHar" :label="$t('commons.import_mode')">
|
||||
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
|
||||
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
|
@ -146,7 +146,14 @@ export default {
|
|||
tip: this.$t('api_test.api_import.swagger_tip'),
|
||||
exportTip: this.$t('api_test.api_import.swagger_export_tip'),
|
||||
suffixes: new Set(['json'])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Har',
|
||||
value: 'Har',
|
||||
tip: this.$t('api_test.api_import.har_tip'),
|
||||
exportTip: this.$t('api_test.api_import.har_export_tip'),
|
||||
suffixes: new Set(['har'])
|
||||
},
|
||||
],
|
||||
selectedPlatform: {},
|
||||
selectedPlatformValue: 'Metersphere',
|
||||
|
@ -182,6 +189,9 @@ export default {
|
|||
isSwagger2() {
|
||||
return this.selectedPlatformValue === 'Swagger2';
|
||||
},
|
||||
isHar() {
|
||||
return this.selectedPlatformValue === 'Har';
|
||||
},
|
||||
isScenarioModel() {
|
||||
return this.model === 'scenario';
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@
|
|||
}
|
||||
this.reqMessages = this.$t('api_test.request.address') + ":\n" + this.response.url + "\n" +
|
||||
this.$t('api_test.scenario.headers') + ":\n" + this.response.headers + "\n" + "Cookies :\n" +
|
||||
this.response.cookies + "\n" + "Bpdy:" + "\n" + this.response.body;
|
||||
this.response.cookies + "\n" + "Body:" + "\n" + this.response.body;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -117,6 +117,36 @@
|
|||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<div>
|
||||
{{ $t('load_test.granularity') }}
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="400"
|
||||
trigger="hover">
|
||||
<el-table :data="granularityData">
|
||||
<el-table-column property="start" :label="$t('load_test.duration')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.start }} - {{ scope.row.end }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column property="granularity" :label="$t('load_test.granularity')"/>
|
||||
</el-table>
|
||||
<i slot="reference" class="el-icon-info pointer"/>
|
||||
</el-popover>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="granularity" :placeholder="$t('commons.please_select')" size="mini" clearable>
|
||||
<el-option v-for="op in granularityData" :key="op.granularity" :label="op.granularity" :value="op.granularity"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -134,6 +164,18 @@ export default {
|
|||
domains: [],
|
||||
params: [],
|
||||
statusCodeStr: '',
|
||||
granularity: undefined,
|
||||
granularityData: [
|
||||
{start: 0, end: 100, granularity: 1},
|
||||
{start: 101, end: 500, granularity: 5},
|
||||
{start: 501, end: 1000, granularity: 10},
|
||||
{start: 1001, end: 3000, granularity: 30},
|
||||
{start: 3001, end: 6000, granularity: 60},
|
||||
{start: 6001, end: 30000, granularity: 300},
|
||||
{start: 30001, end: 60000, granularity: 600},
|
||||
{start: 60001, end: 180000, granularity: 1800},
|
||||
{start: 180001, end: 360000, granularity: 3600},
|
||||
]
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -166,6 +208,7 @@ export default {
|
|||
this.statusCodeStr = this.statusCode.join(',');
|
||||
this.domains = data.domains || [];
|
||||
this.params = data.params || [];
|
||||
this.granularity = data.granularity;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -252,6 +295,7 @@ export default {
|
|||
statusCode: statusCode,
|
||||
params: this.params,
|
||||
domains: this.domains,
|
||||
granularity: this.granularity,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
@ -287,4 +331,8 @@ export default {
|
|||
align: center;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<el-row type="flex" justify="start" align="middle">
|
||||
<el-upload
|
||||
style="padding-right: 10px;"
|
||||
accept=".jar,.csv"
|
||||
accept=".jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx"
|
||||
action=""
|
||||
:limit="fileNumLimit"
|
||||
multiple
|
||||
|
@ -170,7 +170,7 @@ export default {
|
|||
fileList: [],
|
||||
tableData: [],
|
||||
uploadList: [],
|
||||
metadataIdList:[],
|
||||
metadataIdList: [],
|
||||
fileNumLimit: 10,
|
||||
threadGroups: [],
|
||||
loadFileVisible: false,
|
||||
|
@ -276,7 +276,10 @@ export default {
|
|||
let self = this;
|
||||
let file = uploadResources.file;
|
||||
self.uploadList.push(file);
|
||||
|
||||
let type = file.name.substring(file.name.lastIndexOf(".") + 1);
|
||||
if (type.toLowerCase() !== 'jmx') {
|
||||
return;
|
||||
}
|
||||
let jmxReader = new FileReader();
|
||||
jmxReader.onload = (event) => {
|
||||
self.threadGroups = self.threadGroups.concat(findThreadGroup(event.target.result, file.name));
|
||||
|
|
|
@ -22,7 +22,6 @@ import {left2RightDrag, bottom2TopDrag, right2LeftDrag} from "../common/js/direc
|
|||
import JsonSchemaEditor from './components/common/json-schema/schema/index';
|
||||
import JSONPathPicker from 'vue-jsonpath-picker';
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import 'default-passive-events'
|
||||
Vue.use(JsonSchemaEditor);
|
||||
import VuePapaParse from 'vue-papa-parse'
|
||||
Vue.use(VuePapaParse)
|
||||
|
|
|
@ -478,7 +478,8 @@ export default {
|
|||
delete_file: "The file already exists, please delete the file with the same name first!",
|
||||
thread_num: 'Concurrent users:',
|
||||
input_thread_num: 'Please enter the number of threads',
|
||||
duration: 'Duration time (seconds):',
|
||||
duration: 'Duration time (seconds)',
|
||||
granularity: 'Aggregation time (seconds)',
|
||||
input_duration: 'Please enter a duration',
|
||||
rps_limit: 'RPS Limit:',
|
||||
input_rps_limit: 'Please enter a limit',
|
||||
|
@ -913,7 +914,9 @@ export default {
|
|||
export_tip: "Export Tip",
|
||||
ms_tip: "Support for MeterSphere JSON format",
|
||||
ms_export_tip: "Export jSON-formatted files via MeterSphere website or browser plug-ins",
|
||||
har_export_tip: "Export Har files by browser dev-tool",
|
||||
swagger_tip: "Swagger 2.0 and 3.0 json files are supported",
|
||||
har_tip: "Only Har files are supported",
|
||||
postman_tip: "Only Postman Collection V2.1 json files are supported",
|
||||
postman_export_tip: "Export the test collection by Postman",
|
||||
swagger_export_tip: "Export jSON-formatted files via Swagger website",
|
||||
|
|
|
@ -475,7 +475,8 @@ export default {
|
|||
delete_file: "文件已存在,请先删除同名文件!",
|
||||
thread_num: '并发用户数:',
|
||||
input_thread_num: '请输入线程数',
|
||||
duration: '压测时长(秒):',
|
||||
duration: '压测时长(秒)',
|
||||
granularity: '聚合时间(秒)',
|
||||
input_duration: '请输入时长',
|
||||
rps_limit: 'RPS上限:',
|
||||
input_rps_limit: '请输入限制',
|
||||
|
@ -916,8 +917,10 @@ export default {
|
|||
export_tip: "导出方法",
|
||||
ms_tip: "支持 Metersphere json 格式",
|
||||
ms_export_tip: "通过 Metersphere 接口测试页面或者浏览器插件导出 json 格式文件",
|
||||
har_export_tip: "通过 浏览器的开发者工具 导出 Har 格式文件",
|
||||
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
|
||||
swagger_tip: "支持 Swagger 2.0 与 3.0 版本的 json 文件",
|
||||
har_tip: "只支持 Har 文件",
|
||||
post_export_tip: "通过 Postman 导出测试集合",
|
||||
swagger_export_tip: "通过 Swagger 页面导出",
|
||||
jmeter_export_tip: "通过 Jmeter 生成JMX文件",
|
||||
|
|
|
@ -475,7 +475,8 @@ export default {
|
|||
delete_file: "文件已存在,請先刪除同名文件!",
|
||||
thread_num: '並發用戶數:',
|
||||
input_thread_num: '請輸入線程數',
|
||||
duration: '壓測時長(秒):',
|
||||
duration: '壓測時長(秒)',
|
||||
granularity: '聚合時間(秒)',
|
||||
input_duration: '請輸入時長',
|
||||
rps_limit: 'RPS上限:',
|
||||
input_rps_limit: '請輸入限制',
|
||||
|
@ -915,8 +916,10 @@ export default {
|
|||
export_tip: "導出方法",
|
||||
ms_tip: "支持 Metersphere json 格式",
|
||||
ms_export_tip: "通過 Metersphere 接口測試頁面或者瀏覽器插件導出 json 格式文件",
|
||||
har_export_tip: "通过 瀏覽器到開發者工具 导出 Har 格式文件",
|
||||
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
|
||||
swagger_tip: "支持 Swagger 2.0 與 3.0 版本的 json 文件",
|
||||
har_tip: "只支持 Har 文件",
|
||||
post_export_tip: "通過 Postman 導出測試集合",
|
||||
swagger_export_tip: "通過 Swagger 頁面導出",
|
||||
jmeter_export_tip: "通過 Jmeter 生成JMX文件",
|
||||
|
|
Loading…
Reference in New Issue