Merge remote-tracking branch 'origin/master' into master

This commit is contained in:
Captain.B 2020-12-03 16:44:57 +08:00
commit 403e72393c
18 changed files with 1209 additions and 233 deletions

View File

@ -1,6 +1,5 @@
package io.metersphere.api.dto.definition.request.sampler; package io.metersphere.api.dto.definition.request.sampler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.annotation.JSONType;
@ -9,7 +8,6 @@ import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.request.BodyFile;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
@ -23,16 +21,13 @@ import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager; import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy; import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.protocol.http.util.HTTPArgument; import org.apache.jmeter.protocol.http.util.HTTPArgument;
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
import org.apache.jmeter.save.SaveService; import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -142,39 +137,11 @@ public class MsHTTPSamplerProxy extends MsTestElement {
if (CollectionUtils.isNotEmpty(this.getArguments())) { if (CollectionUtils.isNotEmpty(this.getArguments())) {
sampler.setArguments(httpArguments(this.getArguments())); sampler.setArguments(httpArguments(this.getArguments()));
} }
// 请求体 // 请求体
if (!StringUtils.equals(this.getMethod(), "GET")) { if (!StringUtils.equals(this.getMethod(), "GET")) {
List<KeyValue> body = new ArrayList<>(); List<KeyValue> bodyParams = this.body.getBodyParams(sampler, this.getId());
if (this.getBody().isKV() || this.getBody().isBinary()) { sampler.setArguments(httpArguments(bodyParams));
body = this.getBody().getKvs().stream().filter(KeyValue::isValid).collect(Collectors.toList());
HTTPFileArg[] httpFileArgs = httpFileArgs();
// 文件上传
if (httpFileArgs.length > 0) {
sampler.setHTTPFiles(httpFileArgs());
sampler.setDoMultipart(true);
}
} else if (this.getBody().isJson()) {
KeyValue keyValue = new KeyValue("", JSON.toJSONString(this.getBody().getJson()));
keyValue.setEnable(true);
keyValue.setEncode(false);
body.add(keyValue);
} else {
if (StringUtils.isNotBlank(this.getBody().getRaw())) {
sampler.setPostBodyRaw(true);
KeyValue keyValue = new KeyValue("", this.getBody().getRaw());
keyValue.setEnable(true);
keyValue.setEncode(false);
body.add(keyValue);
}
if (StringUtils.isNotBlank(this.getBody().getXml())) {
sampler.setPostBodyRaw(true);
KeyValue keyValue = new KeyValue("", this.getBody().getXml());
keyValue.setEnable(true);
keyValue.setEncode(false);
body.add(keyValue);
}
}
sampler.setArguments(httpArguments(body));
} }
final HashTree httpSamplerTree = tree.add(sampler); final HashTree httpSamplerTree = tree.add(sampler);
@ -225,29 +192,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
return arguments; return arguments;
} }
private void setFileArg(List<HTTPFileArg> list, List<BodyFile> files, KeyValue keyValue) {
final String BODY_FILE_DIR = "/opt/metersphere/data/body";
if (files != null) {
files.forEach(file -> {
String paramName = keyValue.getName() == null ? this.getId() : keyValue.getName();
String path = BODY_FILE_DIR + '/' + file.getId() + '_' + file.getName();
String mimetype = keyValue.getContentType();
list.add(new HTTPFileArg(path, paramName, mimetype));
});
}
}
private HTTPFileArg[] httpFileArgs() {
List<HTTPFileArg> list = new ArrayList<>();
this.getBody().getKvs().stream().filter(KeyValue::isFile).filter(KeyValue::isEnable).forEach(keyValue -> {
setFileArg(list, keyValue.getFiles(), keyValue);
});
this.getBody().getBinary().stream().filter(KeyValue::isFile).filter(KeyValue::isEnable).forEach(keyValue -> {
setFileArg(list, keyValue.getFiles(), keyValue);
});
return list.toArray(new HTTPFileArg[0]);
}
public void setHeader(HashTree tree) { public void setHeader(HashTree tree) {
HeaderManager headerManager = new HeaderManager(); HeaderManager headerManager = new HeaderManager();
headerManager.setEnabled(true); headerManager.setEnabled(true);

View File

@ -1,27 +1,30 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.scenario.request.BodyFile;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Data @Data
public class Body { public class Body {
private String type; private String type;
private String raw; private String raw;
private String format; private String format;
private List<KeyValue> fromUrlencoded;
private List<KeyValue> kvs; private List<KeyValue> kvs;
private List<KeyValue> binary; private List<KeyValue> binary;
private Object json;
private String xml;
private final static String KV = "KeyValue"; public final static String KV = "KeyValue";
private final static String FORM_DATA = "Form Data"; public final static String FORM_DATA = "Form Data";
private final static String RAW = "Raw"; public final static String WWW_FROM = "WWW_FORM";
private final static String BINARY = "BINARY"; public final static String RAW = "Raw";
private final static String JSON = "JSON"; public final static String BINARY = "BINARY";
private final static String XML = "XML"; public final static String JSON = "JSON";
public final static String XML = "XML";
public boolean isValid() { public boolean isValid() {
if (this.isKV()) { if (this.isKV()) {
@ -32,7 +35,55 @@ public class Body {
} }
public boolean isKV() { public boolean isKV() {
return StringUtils.equals(type, KV); if (StringUtils.equals(type, FORM_DATA) || StringUtils.equals(type, WWW_FROM)
|| StringUtils.equals(type, BINARY)) {
return true;
} else return false;
}
public List<KeyValue> getBodyParams(HTTPSamplerProxy sampler, String requestId) {
List<KeyValue> body = new ArrayList<>();
if (this.isKV() || this.isBinary()) {
body = this.getKvs().stream().filter(KeyValue::isValid).collect(Collectors.toList());
HTTPFileArg[] httpFileArgs = httpFileArgs(requestId);
// 文件上传
if (httpFileArgs.length > 0) {
sampler.setHTTPFiles(httpFileArgs(requestId));
sampler.setDoMultipart(true);
}
} else {
if (!this.isJson()) {
sampler.setPostBodyRaw(true);
}
KeyValue keyValue = new KeyValue("", this.getRaw());
keyValue.setEnable(true);
keyValue.setEncode(false);
body.add(keyValue);
}
return body;
}
private HTTPFileArg[] httpFileArgs(String requestId) {
List<HTTPFileArg> list = new ArrayList<>();
this.getKvs().stream().filter(KeyValue::isFile).filter(KeyValue::isEnable).forEach(keyValue -> {
setFileArg(list, keyValue.getFiles(), keyValue, requestId);
});
this.getBinary().stream().filter(KeyValue::isFile).filter(KeyValue::isEnable).forEach(keyValue -> {
setFileArg(list, keyValue.getFiles(), keyValue, requestId);
});
return list.toArray(new HTTPFileArg[0]);
}
private void setFileArg(List<HTTPFileArg> list, List<BodyFile> files, KeyValue keyValue, String requestId) {
final String BODY_FILE_DIR = "/opt/metersphere/data/body";
if (files != null) {
files.forEach(file -> {
String paramName = keyValue.getName() == null ? requestId : keyValue.getName();
String path = BODY_FILE_DIR + '/' + file.getId() + '_' + file.getName();
String mimetype = keyValue.getContentType();
list.add(new HTTPFileArg(path, paramName, mimetype));
});
}
} }
public boolean isBinary() { public boolean isBinary() {
@ -47,4 +98,11 @@ public class Body {
return StringUtils.equals(type, XML); return StringUtils.equals(type, XML);
} }
public boolean isWwwFROM() {
return StringUtils.equals(type, WWW_FROM);
}
public boolean isFromData() {
return StringUtils.equals(type, FORM_DATA);
}
} }

View File

@ -48,11 +48,14 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
} }
protected void addContentType(HttpRequest request, String contentType) { protected void addContentType(HttpRequest request, String contentType) {
addHeader(request, "Content-Type", contentType); // addHeader(request, "Content-Type", contentType);
} }
protected void addCookie(HttpRequest request, String key, String value) { protected void addCookie(List<KeyValue> headers, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>()); addCookie(headers, key, value, "");
}
protected void addCookie(List<KeyValue> headers, String key, String value, String description) {
boolean hasCookie = false; boolean hasCookie = false;
for (KeyValue header : headers) { for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase("Cookie", header.getName())) { if (StringUtils.equalsIgnoreCase("Cookie", header.getName())) {
@ -62,12 +65,15 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
} }
} }
if (!hasCookie) { if (!hasCookie) {
addHeader(request, "Cookie", key + "=" + value + ";"); addHeader(headers, "Cookie", key + "=" + value + ";", description);
} }
} }
protected void addHeader(HttpRequest request, String key, String value) { protected void addHeader(List<KeyValue> headers, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>()); addHeader(headers, key, value, "");
}
protected void addHeader(List<KeyValue> headers, String key, String value, String description) {
boolean hasContentType = false; boolean hasContentType = false;
for (KeyValue header : headers) { for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase(header.getName(), key)) { if (StringUtils.equalsIgnoreCase(header.getName(), key)) {
@ -75,8 +81,20 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
} }
} }
if (!hasContentType) { if (!hasContentType) {
headers.add(new KeyValue(key, value)); headers.add(new KeyValue(key, value, description));
}
request.setHeaders(headers);
} }
} }
// protected void addHeader(HttpRequest request, String key, String value) {
// List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>());
// boolean hasContentType = false;
// for (KeyValue header : headers) {
// if (StringUtils.equalsIgnoreCase(header.getName(), key)) {
// hasContentType = true;
// }
// }
// if (!hasContentType) {
// headers.add(new KeyValue(key, value));
// }
// request.setHeaders(headers);
// }
}

View File

@ -6,183 +6,212 @@ import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult; import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.parse.ApiImport; import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.api.dto.scenario.request.Request;
import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.commons.constants.MsRequestBodyType; import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.SwaggerParameterType; import io.metersphere.commons.constants.SwaggerParameterType;
import io.swagger.models.*; import io.swagger.models.*;
import io.swagger.models.parameters.*; import io.swagger.models.parameters.*;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.parser.SwaggerParser; import io.swagger.parser.SwaggerParser;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
import java.io.InputStream; import java.io.InputStream;
import java.sql.Connection;
import java.util.*; import java.util.*;
public class Swagger2Parser extends ApiImportAbstractParser { public class Swagger2Parser extends ApiImportAbstractParser {
private Map<String, Model> definitions = null;
@Override @Override
public ApiImport parse(InputStream source, ApiTestImportRequest request) { public ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request) {
Swagger swagger; Swagger swagger;
if (StringUtils.isNotBlank(request.getSwaggerUrl())) { if (StringUtils.isNotBlank(request.getSwaggerUrl())) {
swagger = new SwaggerParser().read(request.getSwaggerUrl()); swagger = new SwaggerParser().read(request.getSwaggerUrl());
} else { } else {
swagger = new SwaggerParser().readWithInfo(getApiTestStr(source)).getSwagger(); swagger = new SwaggerParser().readWithInfo(getApiTestStr(source)).getSwagger();
} }
ApiImport apiImport = new ApiImport();
apiImport.setScenarios(parseRequests(swagger));
apiImport.getScenarios().forEach(scenario -> scenario.setEnvironmentId(request.getEnvironmentId()));
return apiImport;
}
@Override
public ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request) {
ApiImport apiImport = this.parse(source, request);
ApiDefinitionImport definitionImport = new ApiDefinitionImport(); ApiDefinitionImport definitionImport = new ApiDefinitionImport();
definitionImport.setData(parseSwagger(apiImport)); definitionImport.setData(parseRequests(swagger));
return definitionImport; return definitionImport;
} }
private List<ApiDefinitionResult> parseSwagger(ApiImport apiImport) { @Override
public ApiImport parse(InputStream source, ApiTestImportRequest request) {
return null;
}
private List<ApiDefinitionResult> parseRequests(Swagger swagger) {
List<ApiDefinitionResult> results = new LinkedList<>(); List<ApiDefinitionResult> results = new LinkedList<>();
apiImport.getScenarios().forEach(item -> {
item.getRequests().forEach(childItem -> {
if (childItem instanceof HttpRequest) {
HttpRequest res = (HttpRequest) childItem;
ApiDefinitionResult request = new ApiDefinitionResult();
request.setName(res.getName());
request.setPath(res.getPath());
request.setMethod(res.getMethod());
request.setProtocol(RequestType.HTTP);
MsHTTPSamplerProxy requestElement = new MsHTTPSamplerProxy();
requestElement.setName(res.getName() + "Postman MHTTPSamplerProxy");
requestElement.setBody(res.getBody());
requestElement.setArguments(res.getParameters());
requestElement.setProtocol(RequestType.HTTP);
requestElement.setPath(res.getPath());
requestElement.setMethod(res.getMethod());
requestElement.setId(UUID.randomUUID().toString());
requestElement.setRest(new ArrayList<KeyValue>());
MsHeaderManager headerManager = new MsHeaderManager();
headerManager.setId(UUID.randomUUID().toString());
headerManager.setName(res.getName() + "Postman MsHeaderManager");
headerManager.setHeaders(res.getHeaders());
HashTree tree = new HashTree();
tree.add(headerManager);
LinkedList<MsTestElement> list = new LinkedList<>();
list.add(headerManager);
requestElement.setHashTree(list);
request.setRequest(JSON.toJSONString(requestElement));
results.add(request);
}
});
});
return results;
}
private List<Scenario> parseRequests(Swagger swagger) {
Map<String, Path> paths = swagger.getPaths(); Map<String, Path> paths = swagger.getPaths();
Set<String> pathNames = paths.keySet(); Set<String> pathNames = paths.keySet();
Map<String, Scenario> scenarioMap = new HashMap<>();
this.definitions = swagger.getDefinitions();
for (String pathName : pathNames) { for (String pathName : pathNames) {
Path path = paths.get(pathName); Path path = paths.get(pathName);
Map<HttpMethod, Operation> operationMap = path.getOperationMap(); Map<HttpMethod, Operation> operationMap = path.getOperationMap();
Set<HttpMethod> httpMethods = operationMap.keySet(); Set<HttpMethod> httpMethods = operationMap.keySet();
for (HttpMethod method : httpMethods) { for (HttpMethod method : httpMethods) {
Operation operation = operationMap.get(method); Operation operation = operationMap.get(method);
HttpRequest request = new HttpRequest();
ApiDefinitionResult apiDefinition = buildApiDefinition(operation, pathName, method.name());
MsHTTPSamplerProxy request = buildRequest(operation, pathName, method.name());
parseParameters(operation, request);
apiDefinition.setRequest(JSON.toJSONString(request));
results.add(apiDefinition);
// List<String> tags = operation.getTags();
// if (tags != null) {
// tags.forEach(tag -> {
// Scenario scenario = Optional.ofNullable(scenarioMap.get(tag)).orElse(new Scenario());
// List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
// requests.add(request);
// scenario.setRequests(requests);
// scenario.setName(tag);
// scenarioMap.put(tag, scenario);
// });
// } else {
// Scenario scenario = Optional.ofNullable(scenarioMap.get("default")).orElse(new Scenario());
// List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
// requests.add(request);
// scenario.setRequests(requests);
// scenarioMap.put("default", scenario);
// }
}
}
this.definitions = null;
return results;
}
private ApiDefinitionResult buildApiDefinition(Operation operation, String path, String method) {
ApiDefinitionResult apiDefinition = new ApiDefinitionResult();
if (StringUtils.isNotBlank(operation.getSummary())) {
apiDefinition.setName(operation.getSummary());
} else {
apiDefinition.setName(operation.getOperationId());
}
apiDefinition.setPath(path);
apiDefinition.setProtocol(RequestType.HTTP);
apiDefinition.setMethod(method);
return apiDefinition;
}
private MsHTTPSamplerProxy buildRequest(Operation operation, String path, String method) {
MsHTTPSamplerProxy request = new MsHTTPSamplerProxy();
if (StringUtils.isNotBlank(operation.getSummary())) { if (StringUtils.isNotBlank(operation.getSummary())) {
request.setName(operation.getSummary()); request.setName(operation.getSummary());
} else { } else {
request.setName(operation.getOperationId()); request.setName(operation.getOperationId());
} }
request.setPath(pathName); request.setPath(path);
request.setUseEnvironment(true); request.setMethod(method);
request.setMethod(method.name()); request.setProtocol(RequestType.HTTP);
parseParameters(operation, swagger.getDefinitions(), request); return request;
List<String> tags = operation.getTags();
if (tags != null) {
tags.forEach(tag -> {
Scenario scenario = Optional.ofNullable(scenarioMap.get(tag)).orElse(new Scenario());
List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
requests.add(request);
scenario.setRequests(requests);
scenario.setName(tag);
scenarioMap.put(tag, scenario);
});
} else {
Scenario scenario = Optional.ofNullable(scenarioMap.get("default")).orElse(new Scenario());
List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
requests.add(request);
scenario.setRequests(requests);
scenarioMap.put("default", scenario);
} }
} private void parseParameters(Operation operation, MsHTTPSamplerProxy request) {
}
return new ArrayList<>(scenarioMap.values());
}
private void parseParameters(Operation operation, Map<String, Model> definitions, HttpRequest request) {
List<Parameter> parameters = operation.getParameters(); List<Parameter> parameters = operation.getParameters();
request.setId(UUID.randomUUID().toString());
request.setHeaders(new ArrayList<>());
request.setArguments(new ArrayList<>());
request.setRest(new ArrayList<>());
request.setBody(new Body());
request.getBody().setType(getBodyType(operation));
// todo 路径变量 {xxx} 是否要转换
for (Parameter parameter : parameters) { for (Parameter parameter : parameters) {
switch (parameter.getIn()) { switch (parameter.getIn()) {
// case SwaggerParameterType.PATH: case SwaggerParameterType.PATH:
// parsePathParameters(parameter, request); parsePathParameters(parameter, request.getRest());
// break; break;
case SwaggerParameterType.QUERY: case SwaggerParameterType.QUERY:
parseQueryParameters(parameter, request); parseQueryParameters(parameter, request.getArguments());
break; break;
case SwaggerParameterType.FORM_DATA: case SwaggerParameterType.FORM_DATA:
parseFormDataParameters(parameter, request); parseFormDataParameters((FormParameter) parameter, request.getBody());
break; break;
case SwaggerParameterType.BODY: case SwaggerParameterType.BODY:
parseBodyParameters(parameter, request, definitions); parseBodyParameters(parameter, request.getBody());
break; break;
case SwaggerParameterType.HEADER: case SwaggerParameterType.HEADER:
parseHeaderParameters(parameter, request); parseHeaderParameters(parameter, request.getHeaders());
break; break;
case SwaggerParameterType.COOKIE: case SwaggerParameterType.COOKIE:
parseCookieParameters(parameter, request); parseCookieParameters(parameter, request.getHeaders());
break; break;
// case SwaggerParameterType.FILE: // case SwaggerParameterType.FILE:
// parsePathParameters(parameter, request); // parsePathParameters(parameter, request);
// break; // break;
} }
} }
// List<String> responseContentTypes = operation.getProduces();
} }
private void parseCookieParameters(Parameter parameter, HttpRequest request) { private String getBodyType(Operation operation) {
if (CollectionUtils.isEmpty(operation.getConsumes())) {
return Body.RAW;
}
String contentType = operation.getConsumes().get(0);
String bodyType = "";
switch (contentType) {
case "application/x-www-form-urlencoded":
bodyType = Body.WWW_FROM;
break;
case "multipart/form-data":
bodyType = Body.FORM_DATA;
break;
case "application/json":
bodyType = Body.JSON;
break;
case "application/xml":
bodyType = Body.XML;
break;
// case "": //todo binary 啥类型
// bodyType = Body.BINARY;
// break;
default:
bodyType = Body.RAW;
}
return bodyType;
}
private void parsePathParameters(Parameter parameter, List<KeyValue> rests) {
PathParameter pathParameter = (PathParameter) parameter;
rests.add(new KeyValue(pathParameter.getName(), "", getDefaultStringValue(parameter.getDescription())));
}
private String getDefaultStringValue(String val) {
return StringUtils.isBlank(val) ? "" : val;
}
private void parseCookieParameters(Parameter parameter, List<KeyValue> headers) {
CookieParameter cookieParameter = (CookieParameter) parameter; CookieParameter cookieParameter = (CookieParameter) parameter;
addCookie(request, cookieParameter.getName(), cookieParameter.getDescription()); addCookie(headers, cookieParameter.getName(), "", getDefaultStringValue(cookieParameter.getDescription()));
} }
private void parseHeaderParameters(Parameter parameter, HttpRequest request) { private void parseHeaderParameters(Parameter parameter, List<KeyValue> headers) {
HeaderParameter headerParameter = (HeaderParameter) parameter; HeaderParameter headerParameter = (HeaderParameter) parameter;
addHeader(request, headerParameter.getName(), headerParameter.getDescription()); addHeader(headers, headerParameter.getName(), "", getDefaultStringValue(headerParameter.getDescription()));
} }
private void parseBodyParameters(Parameter parameter, HttpRequest request, Map<String, Model> definitions) { private void parseBodyParameters(Parameter parameter, Body body) {
BodyParameter bodyParameter = (BodyParameter) parameter; BodyParameter bodyParameter = (BodyParameter) parameter;
Body body = Optional.ofNullable(request.getBody()).orElse(new Body());
body.setType(MsRequestBodyType.RAW.value());
Model schema = bodyParameter.getSchema(); Model schema = bodyParameter.getSchema();
// 引用模型
if (schema instanceof RefModel) { if (schema instanceof RefModel) {
String simpleRef = ""; String simpleRef = "";
RefModel refModel = (RefModel) bodyParameter.getSchema(); RefModel refModel = (RefModel) bodyParameter.getSchema();
@ -192,14 +221,15 @@ public class Swagger2Parser extends ApiImportAbstractParser {
} else { } else {
simpleRef = refModel.getSimpleRef(); simpleRef = refModel.getSimpleRef();
} }
Model model = definitions.get(simpleRef); Model model = this.definitions.get(simpleRef);
HashSet<String> refSet = new HashSet<>(); HashSet<String> refSet = new HashSet<>();
refSet.add(simpleRef); refSet.add(simpleRef);
if (model != null) { if (model != null) {
JSONObject bodyParameters = getBodyJSONObjectParameters(model.getProperties(), definitions, refSet); JSONObject bodyParameters = getBodyParameters(model.getProperties(), refSet);
body.setRaw(bodyParameters.toJSONString()); body.setRaw(bodyParameters.toJSONString());
} }
} else if (schema instanceof ArrayModel) { } else if (schema instanceof ArrayModel) {
//模型数组
ArrayModel arrayModel = (ArrayModel) bodyParameter.getSchema(); ArrayModel arrayModel = (ArrayModel) bodyParameter.getSchema();
Property items = arrayModel.getItems(); Property items = arrayModel.getItems();
if (items instanceof RefProperty) { if (items instanceof RefProperty) {
@ -209,21 +239,20 @@ public class Swagger2Parser extends ApiImportAbstractParser {
refSet.add(simpleRef); refSet.add(simpleRef);
Model model = definitions.get(simpleRef); Model model = definitions.get(simpleRef);
JSONArray propertyList = new JSONArray(); JSONArray propertyList = new JSONArray();
propertyList.add(getBodyJSONObjectParameters(model.getProperties(), definitions, refSet)); propertyList.add(getBodyParameters(model.getProperties(), refSet));
body.setRaw(propertyList.toString()); body.setRaw(propertyList.toString());
} }
} }
request.setBody(body);
body.setFormat("json"); body.setFormat("json");
} }
private JSONObject getBodyJSONObjectParameters(Map<String, Property> properties, Map<String, Model> definitions, HashSet<String> refSet) { private JSONObject getBodyParameters(Map<String, Property> properties, HashSet<String> refSet) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
if (properties != null) { if (properties != null) {
properties.forEach((key, value) -> { properties.forEach((key, value) -> {
if (value instanceof ObjectProperty) { if (value instanceof ObjectProperty) {
ObjectProperty objectProperty = (ObjectProperty) value; ObjectProperty objectProperty = (ObjectProperty) value;
jsonObject.put(key, getBodyJSONObjectParameters(objectProperty.getProperties(), definitions, refSet)); jsonObject.put(key, getBodyParameters(objectProperty.getProperties(), refSet));
} else if (value instanceof ArrayProperty) { } else if (value instanceof ArrayProperty) {
ArrayProperty arrayProperty = (ArrayProperty) value; ArrayProperty arrayProperty = (ArrayProperty) value;
Property items = arrayProperty.getItems(); Property items = arrayProperty.getItems();
@ -231,38 +260,50 @@ public class Swagger2Parser extends ApiImportAbstractParser {
RefProperty refProperty = (RefProperty) items; RefProperty refProperty = (RefProperty) items;
String simpleRef = refProperty.getSimpleRef(); String simpleRef = refProperty.getSimpleRef();
if (refSet.contains(simpleRef)) { if (refSet.contains(simpleRef)) {
//避免嵌套死循环
jsonObject.put(key, new JSONArray()); jsonObject.put(key, new JSONArray());
return; return;
} }
refSet.add(simpleRef); refSet.add(simpleRef);
Model model = definitions.get(simpleRef); Model model = this.definitions.get(simpleRef);
JSONArray propertyList = new JSONArray(); JSONArray propertyList = new JSONArray();
propertyList.add(getBodyJSONObjectParameters(model.getProperties(), definitions, refSet)); propertyList.add(getBodyParameters(model.getProperties(), refSet));
jsonObject.put(key, propertyList); jsonObject.put(key, propertyList);
} else { } else {
jsonObject.put(key, new ArrayList<>()); jsonObject.put(key, new ArrayList<>());
} }
} else { } else {
jsonObject.put(key, Optional.ofNullable(value.getDescription()).orElse("")); jsonObject.put(key, getDefaultValueByPropertyType(value));
} }
}); });
} }
return jsonObject; return jsonObject;
} }
private void parseFormDataParameters(Parameter parameter, HttpRequest request) { private Object getDefaultValueByPropertyType(Property value) {
Body body = Optional.ofNullable(request.getBody()).orElse(new Body()); if (value instanceof LongProperty || value instanceof IntegerProperty
body.setType(MsRequestBodyType.FORM_DATA.value()); || value instanceof BaseIntegerProperty) {
List<KeyValue> keyValues = Optional.ofNullable(body.getKvs()).orElse(new ArrayList<>()); return 0;
keyValues.add(new KeyValue(parameter.getName(), "", parameter.getDescription())); } else if (value instanceof FloatProperty || value instanceof DoubleProperty
body.setKvs(keyValues); || value instanceof DecimalProperty) {
request.setBody(body); return 0.0;
} else {// todo 其他类型?
return getDefaultStringValue(value.getDescription());
}
} }
private void parseQueryParameters(Parameter parameter, HttpRequest request) { private void parseFormDataParameters(FormParameter parameter, Body body) {
List<KeyValue> keyValues = Optional.ofNullable(body.getKvs()).orElse(new ArrayList<>());
KeyValue kv = new KeyValue(parameter.getName(), "", getDefaultStringValue(parameter.getDescription()));
if (StringUtils.equals(parameter.getType(), "file") ) {
kv.setType("file");
}
keyValues.add(kv);
body.setKvs(keyValues);
}
private void parseQueryParameters(Parameter parameter, List<KeyValue> arguments) {
QueryParameter queryParameter = (QueryParameter) parameter; QueryParameter queryParameter = (QueryParameter) parameter;
List<KeyValue> parameters = Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>()); arguments.add(new KeyValue(queryParameter.getName(), "", getDefaultStringValue(queryParameter.getDescription())));
parameters.add(new KeyValue(queryParameter.getName(), "", queryParameter.getDescription()));
request.setParameters(parameters);
} }
} }

View File

@ -0,0 +1,82 @@
package io.metersphere.api.parse.old;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public abstract class ApiImportAbstractParser implements ApiImportParser {
protected String getApiTestStr(InputStream source) {
StringBuilder testStr = null;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
testStr = new StringBuilder();
String inputStr;
while ((inputStr = bufferedReader.readLine()) != null) {
testStr.append(inputStr);
}
} catch (Exception e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
} finally {
try {
source.close();
} catch (IOException e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
}
}
return testStr.toString();
}
protected void setScenarioByRequest(Scenario scenario, ApiTestImportRequest request) {
if (request.getUseEnvironment()) {
scenario.setEnvironmentId(request.getEnvironmentId());
}
}
protected void addContentType(HttpRequest request, String contentType) {
addHeader(request, "Content-Type", contentType);
}
protected void addCookie(HttpRequest request, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>());
boolean hasCookie = false;
for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase("Cookie", header.getName())) {
hasCookie = true;
String cookies = Optional.ofNullable(header.getValue()).orElse("");
header.setValue(cookies + key + "=" + value + ";");
}
}
if (!hasCookie) {
addHeader(request, "Cookie", key + "=" + value + ";");
}
}
protected void addHeader(HttpRequest request, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>());
boolean hasContentType = false;
for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase(header.getName(), key)) {
hasContentType = true;
}
}
if (!hasContentType) {
headers.add(new KeyValue(key, value));
}
request.setHeaders(headers);
}
}

View File

@ -0,0 +1,13 @@
package io.metersphere.api.parse.old;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.parse.ApiImport;
import java.io.InputStream;
public interface ApiImportParser {
ApiImport parse(InputStream source, ApiTestImportRequest request);
ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request);
}

View File

@ -0,0 +1,17 @@
package io.metersphere.api.parse.old;
import io.metersphere.commons.constants.ApiImportPlatform;
import org.apache.commons.lang3.StringUtils;
public class ApiImportParserFactory {
public static ApiImportParser getApiImportParser(String platform) {
if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) {
return new MsParser();
} else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) {
return new PostmanParser();
} else if (StringUtils.equals(ApiImportPlatform.Swagger2.name(), platform)) {
return new Swagger2Parser();
}
return null;
}
}

View File

@ -0,0 +1,227 @@
package io.metersphere.api.parse.old;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ScriptEngineUtils;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
public class JmeterDocumentParser {
private final static String HASH_TREE_ELEMENT = "hashTree";
private final static String STRING_PROP = "stringProp";
private final static String ARGUMENTS = "Arguments";
private final static String COLLECTION_PROP = "collectionProp";
private final static String HTTP_SAMPLER_PROXY = "MsHTTPSamplerProxy";
private final static String ELEMENT_PROP = "elementProp";
public static byte[] parse(byte[] source) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try (
ByteArrayInputStream byteStream = new ByteArrayInputStream(source)
) {
InputSource inputSource = new InputSource(byteStream);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
final Document document = docBuilder.parse(inputSource);
final Element jmeterTestPlan = document.getDocumentElement();
NodeList childNodes = jmeterTestPlan.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
parseHashTree(ele);
}
}
return documentToBytes(document);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
return source;
}
}
private static byte[] documentToBytes(Document document) throws TransformerException {
DOMSource domSource = new DOMSource(document);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
return writer.toString().getBytes();
}
private static void parseHashTree(Element hashTree) {
if (invalid(hashTree)) {
return;
}
if (hashTree.getChildNodes().getLength() > 0) {
final NodeList childNodes = hashTree.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (invalid(ele)) {
continue;
}
if (nodeNameEquals(ele, HASH_TREE_ELEMENT)) {
parseHashTree(ele);
} else if (nodeNameEquals(ele, ARGUMENTS)) {
processArguments(ele);
} else if (nodeNameEquals(ele, HTTP_SAMPLER_PROXY)) {
processHttpSamplerProxy(ele);
}
}
}
}
}
private static void processHttpSamplerProxy(Element ele) {
if (invalid(ele)) {
return;
}
NodeList childNodes = ele.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if (!(item instanceof Element)) {
continue;
}
Element element = (Element) item;
if (nodeNameEquals(element, ELEMENT_PROP) && "HTTPsampler.Arguments".equals(element.getAttribute("name"))) {
processArguments(element);
} else if ("HTTPSampler.path".equals(element.getAttribute("name"))) {
processStringProp(element);
}
}
}
private static void processArguments(Element ele) {
if (invalid(ele)) {
return;
}
NodeList childNodes = ele.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if (!(item instanceof Element)) {
continue;
}
Element element = (Element) item;
if (nodeNameEquals(item, COLLECTION_PROP) && "Arguments.arguments".equals(element.getAttribute("name"))) {
NodeList elementProps = item.getChildNodes();
for (int j = 0; j < elementProps.getLength(); j++) {
Node elementProp = elementProps.item(j);
if (!(elementProp instanceof Element)) {
continue;
}
NodeList stringProps = elementProp.getChildNodes();
for (int k = 0; k < stringProps.getLength(); k++) {
Node stringProp = stringProps.item(k);
if (!(stringProp instanceof Element)) {
continue;
}
processStringProp((Element) stringProp);
}
}
}
}
}
private static void processStringProp(Element ele) {
String name = ele.getAttribute("name");
switch (name) {
case "HTTPSampler.path":
String path = ele.getTextContent();
Map<String, String> parser = parserUrl(path);
String url = parser.get("URL");
String params = parser.keySet().stream().filter(k -> !"URL".equals(k)).reduce("?", (u, k) -> {
String v = parser.get(k);
if (!StringUtils.equals("?", u)) {
u += "&";
}
u += k + "=" + ScriptEngineUtils.calculate(v);
return u;
});
ele.setTextContent(url + ((params != null && !params.equals("?")) ? params : ""));
break;
case "Argument.value":
String textContent = ele.getTextContent();
if (StringUtils.startsWith(textContent, "@")) {
ele.setTextContent(ScriptEngineUtils.calculate(textContent));
}
break;
default:
break;
}
}
private static boolean nodeNameEquals(Node node, String desiredName) {
return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName());
}
private static boolean invalid(Element ele) {
return !StringUtils.isBlank(ele.getAttribute("enabled")) && !Boolean.parseBoolean(ele.getAttribute("enabled"));
}
private static Map<String, String> parserUrl(String url) {
// 传递的URL参数
Map<String, String> strUrlParas = new HashMap<>();
String strUrl;
String strUrlParams;
// 解析访问地址
if (url.contains("?")) {
String[] strUrlPatten = url.split("\\?");
strUrl = strUrlPatten[0];
strUrlParams = strUrlPatten[1];
} else {
strUrl = url;
strUrlParams = url;
}
strUrlParas.put("URL", strUrl);
// 解析参数
String[] params = null;
if (strUrlParams.contains("&")) {
params = strUrlParams.split("&");
} else {
params = new String[]{strUrlParams};
}
// 保存参数到参数容器
for (String p : params) {
if (p.contains("=")) {
String[] param = p.split("=");
if (param.length == 1) {
strUrlParas.put(param[0], "");
} else {
String key = param[0];
String value = param[1];
strUrlParas.put(key, value);
}
}
}
return strUrlParas;
}
}

View File

@ -0,0 +1,101 @@
package io.metersphere.api.parse.old;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.commons.constants.MsRequestBodyType;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
public class MsParser extends ApiImportAbstractParser {
@Override
public ApiImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
ApiImport apiImport = JSON.parseObject(parsePluginFormat(testStr), ApiImport.class);
apiImport.getScenarios().forEach(scenario -> setScenarioByRequest(scenario, request));
return apiImport;
}
@Override
public ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
ApiDefinitionImport apiImport = JSON.parseObject(testStr, ApiDefinitionImport.class);
return apiImport;
}
private String parsePluginFormat(String testStr) {
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
if (testObject.get("scenarios") != null) {
return testStr;
} else {
//插件格式
JSONArray scenarios = new JSONArray();
testObject.keySet().forEach(scenarioName -> {
JSONObject scenario = new JSONObject();
scenario.put("name", scenarioName);
JSONArray requestsObjects = new JSONArray();
JSONObject requestsObject = testObject.getJSONObject(scenarioName);
requestsObject.keySet().forEach(requestName -> {
JSONObject requestObject = new JSONObject(true);
JSONObject requestTmpObject = requestsObject.getJSONObject(requestName);
//排序确保type在第一个否则转换失败
if (StringUtils.isBlank(requestTmpObject.getString("type"))) {
requestObject.put("type", RequestType.HTTP);
}
requestTmpObject.keySet().forEach(key -> requestObject.put(key, requestTmpObject.get(key)));
requestObject.put("name", requestName);
parseBody(requestObject);
requestsObjects.add(requestObject);
});
scenario.put("requests", requestsObjects);
scenarios.add(scenario);
});
JSONObject result = new JSONObject();
result.put("scenarios", scenarios);
return result.toJSONString();
}
}
private void parseBody(JSONObject requestObject) {
if (requestObject.containsKey("body")) {
Object body = requestObject.get("body");
if (body instanceof JSONArray) {
JSONArray bodies = requestObject.getJSONArray("body");
if (bodies != null) {
StringBuilder bodyStr = new StringBuilder();
for (int i = 0; i < bodies.size(); i++) {
String tmp = bodies.getString(i);
bodyStr.append(tmp);
}
JSONObject bodyObject = new JSONObject();
bodyObject.put("raw", bodyStr);
bodyObject.put("type", MsRequestBodyType.RAW.value());
requestObject.put("body", bodyObject);
}
} else if (body instanceof JSONObject) {
JSONObject bodyObj = requestObject.getJSONObject("body");
if (bodyObj != null) {
JSONArray kvs = new JSONArray();
bodyObj.keySet().forEach(key -> {
JSONObject kv = new JSONObject();
kv.put("name", key);
kv.put("value", bodyObj.getString(key));
kvs.add(kv);
});
JSONObject bodyRes = new JSONObject();
bodyRes.put("kvs", kvs);
bodyRes.put("type", MsRequestBodyType.KV.value());
requestObject.put("body", bodyRes);
}
}
}
}
}

View File

@ -0,0 +1,184 @@
package io.metersphere.api.parse.old;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.parse.postman.*;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.api.dto.scenario.request.Request;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.PostmanRequestBodyMode;
import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
public class PostmanParser extends ApiImportAbstractParser {
@Override
public ApiImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
PostmanCollectionInfo info = postmanCollection.getInfo();
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ApiImport apiImport = new ApiImport();
List<Scenario> scenarios = new ArrayList<>();
Scenario scenario = new Scenario();
scenario.setName(info.getName());
setScenarioByRequest(scenario, request);
parseItem(postmanCollection.getItem(), scenario, variables, scenarios);
apiImport.setScenarios(scenarios);
return apiImport;
}
@Override
public ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ApiDefinitionImport apiImport = new ApiDefinitionImport();
List<ApiDefinitionResult> requests = new ArrayList<>();
parseItem(postmanCollection.getItem(), variables, requests);
apiImport.setData(requests);
return apiImport;
}
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionResult> scenarios) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
parseItem(childItems, variables, scenarios);
} else {
ApiDefinitionResult request = parsePostman(item);
if (request != null) {
scenarios.add(request);
}
}
}
}
private ApiDefinitionResult parsePostman(PostmanItem requestItem) {
PostmanRequest requestDesc = requestItem.getRequest();
if (requestDesc == null) {
return null;
}
PostmanUrl url = requestDesc.getUrl();
ApiDefinitionResult request = new ApiDefinitionResult();
request.setName(requestItem.getName());
request.setPath(url.getRaw());
request.setMethod(requestDesc.getMethod());
request.setProtocol(RequestType.HTTP);
MsHTTPSamplerProxy requestElement = new MsHTTPSamplerProxy();
requestElement.setName(requestItem.getName() + "Postman MHTTPSamplerProxy");
requestElement.setBody(parseBody(requestDesc));
requestElement.setArguments(parseKeyValue(url.getQuery()));
requestElement.setProtocol(RequestType.HTTP);
requestElement.setPath(url.getRaw());
requestElement.setMethod(requestDesc.getMethod());
requestElement.setId(UUID.randomUUID().toString());
requestElement.setRest(new ArrayList<KeyValue>());
MsHeaderManager headerManager = new MsHeaderManager();
headerManager.setId(UUID.randomUUID().toString());
headerManager.setName(requestItem.getName() + "Postman MsHeaderManager");
headerManager.setHeaders(parseKeyValue(requestDesc.getHeader()));
HashTree tree = new HashTree();
tree.add(headerManager);
LinkedList<MsTestElement> list = new LinkedList<>();
list.add(headerManager);
requestElement.setHashTree(list);
request.setRequest(JSON.toJSONString(requestElement));
return request;
}
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())));
return keyValues;
}
private void parseItem(List<PostmanItem> items, Scenario scenario, List<PostmanKeyValue> variables, List<Scenario> scenarios) {
List<Request> requests = new ArrayList<>();
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
Scenario subScenario = new Scenario();
subScenario.setName(item.getName());
subScenario.setEnvironmentId(scenario.getEnvironmentId());
parseItem(childItems, subScenario, variables, scenarios);
} else {
Request request = parseRequest(item);
if (request != null) {
requests.add(request);
}
}
}
scenario.setVariables(parseKeyValue(variables));
scenario.setRequests(requests);
scenarios.add(scenario);
}
private Request parseRequest(PostmanItem requestItem) {
HttpRequest request = new HttpRequest();
PostmanRequest requestDesc = requestItem.getRequest();
if (requestDesc == null) {
return null;
}
PostmanUrl url = requestDesc.getUrl();
request.setName(requestItem.getName());
request.setUrl(url.getRaw());
request.setUseEnvironment(false);
request.setMethod(requestDesc.getMethod());
request.setHeaders(parseKeyValue(requestDesc.getHeader()));
request.setParameters(parseKeyValue(url.getQuery()));
request.setBody(parseBody(requestDesc));
return request;
}
private Body parseBody(PostmanRequest requestDesc) {
Body body = new Body();
JSONObject postmanBody = requestDesc.getBody();
if (postmanBody == null) {
return null;
}
String bodyMode = postmanBody.getString("mode");
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
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) {
body.setFormat(raw.getString("language"));
}
}
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value()) || StringUtils.equals(bodyMode, PostmanRequestBodyMode.URLENCODED.value())) {
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.getString(bodyMode), PostmanKeyValue.class);
body.setType(MsRequestBodyType.KV.value());
body.setKvs(parseKeyValue(postmanKeyValues));
}
return body;
}
}

View File

@ -0,0 +1,268 @@
package io.metersphere.api.parse.old;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.api.dto.scenario.request.Request;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.SwaggerParameterType;
import io.swagger.models.*;
import io.swagger.models.parameters.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
import java.io.InputStream;
import java.util.*;
public class Swagger2Parser extends ApiImportAbstractParser {
@Override
public ApiImport parse(InputStream source, ApiTestImportRequest request) {
Swagger swagger;
if (StringUtils.isNotBlank(request.getSwaggerUrl())) {
swagger = new SwaggerParser().read(request.getSwaggerUrl());
} else {
swagger = new SwaggerParser().readWithInfo(getApiTestStr(source)).getSwagger();
}
ApiImport apiImport = new ApiImport();
apiImport.setScenarios(parseRequests(swagger));
apiImport.getScenarios().forEach(scenario -> scenario.setEnvironmentId(request.getEnvironmentId()));
return apiImport;
}
@Override
public ApiDefinitionImport parseApi(InputStream source, ApiTestImportRequest request) {
ApiImport apiImport = this.parse(source, request);
ApiDefinitionImport definitionImport = new ApiDefinitionImport();
definitionImport.setData(parseSwagger(apiImport));
return definitionImport;
}
private List<ApiDefinitionResult> parseSwagger(ApiImport apiImport) {
List<ApiDefinitionResult> results = new LinkedList<>();
apiImport.getScenarios().forEach(item -> {
item.getRequests().forEach(childItem -> {
if (childItem instanceof HttpRequest) {
HttpRequest res = (HttpRequest) childItem;
ApiDefinitionResult request = new ApiDefinitionResult();
request.setName(res.getName());
request.setPath(res.getPath());
request.setMethod(res.getMethod());
request.setProtocol(RequestType.HTTP);
MsHTTPSamplerProxy requestElement = new MsHTTPSamplerProxy();
requestElement.setName(res.getName() + "Postman MHTTPSamplerProxy");
requestElement.setBody(res.getBody());
requestElement.setArguments(res.getParameters());
requestElement.setProtocol(RequestType.HTTP);
requestElement.setPath(res.getPath());
requestElement.setMethod(res.getMethod());
requestElement.setId(UUID.randomUUID().toString());
requestElement.setRest(new ArrayList<KeyValue>());
MsHeaderManager headerManager = new MsHeaderManager();
headerManager.setId(UUID.randomUUID().toString());
headerManager.setName(res.getName() + "Postman MsHeaderManager");
headerManager.setHeaders(res.getHeaders());
// HashTree tree = new HashTree();
// tree.add(headerManager);
LinkedList<MsTestElement> list = new LinkedList<>();
list.add(headerManager);
requestElement.setHashTree(list);
request.setRequest(JSON.toJSONString(requestElement));
results.add(request);
}
});
});
return results;
}
private List<Scenario> parseRequests(Swagger swagger) {
Map<String, Path> paths = swagger.getPaths();
Set<String> pathNames = paths.keySet();
Map<String, Scenario> scenarioMap = new HashMap<>();
for (String pathName : pathNames) {
Path path = paths.get(pathName);
Map<HttpMethod, Operation> operationMap = path.getOperationMap();
Set<HttpMethod> httpMethods = operationMap.keySet();
for (HttpMethod method : httpMethods) {
Operation operation = operationMap.get(method);
HttpRequest request = new HttpRequest();
if (StringUtils.isNotBlank(operation.getSummary())) {
request.setName(operation.getSummary());
} else {
request.setName(operation.getOperationId());
}
request.setPath(pathName);
request.setUseEnvironment(true);
request.setMethod(method.name());
parseParameters(operation, swagger.getDefinitions(), request);
List<String> tags = operation.getTags();
if (tags != null) {
tags.forEach(tag -> {
Scenario scenario = Optional.ofNullable(scenarioMap.get(tag)).orElse(new Scenario());
List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
requests.add(request);
scenario.setRequests(requests);
scenario.setName(tag);
scenarioMap.put(tag, scenario);
});
} else {
Scenario scenario = Optional.ofNullable(scenarioMap.get("default")).orElse(new Scenario());
List<Request> requests = Optional.ofNullable(scenario.getRequests()).orElse(new ArrayList<>());
requests.add(request);
scenario.setRequests(requests);
scenarioMap.put("default", scenario);
}
}
}
return new ArrayList<>(scenarioMap.values());
}
private void parseParameters(Operation operation, Map<String, Model> definitions, HttpRequest request) {
List<Parameter> parameters = operation.getParameters();
for (Parameter parameter : parameters) {
switch (parameter.getIn()) {
// case SwaggerParameterType.PATH:
// parsePathParameters(parameter, request);
// break;
case SwaggerParameterType.QUERY:
parseQueryParameters(parameter, request);
break;
case SwaggerParameterType.FORM_DATA:
parseFormDataParameters(parameter, request);
break;
case SwaggerParameterType.BODY:
parseBodyParameters(parameter, request, definitions);
break;
case SwaggerParameterType.HEADER:
parseHeaderParameters(parameter, request);
break;
case SwaggerParameterType.COOKIE:
parseCookieParameters(parameter, request);
break;
// case SwaggerParameterType.FILE:
// parsePathParameters(parameter, request);
// break;
}
}
}
private void parseCookieParameters(Parameter parameter, HttpRequest request) {
CookieParameter cookieParameter = (CookieParameter) parameter;
addCookie(request, cookieParameter.getName(), cookieParameter.getDescription());
}
private void parseHeaderParameters(Parameter parameter, HttpRequest request) {
HeaderParameter headerParameter = (HeaderParameter) parameter;
addHeader(request, headerParameter.getName(), headerParameter.getDescription());
}
private void parseBodyParameters(Parameter parameter, HttpRequest request, Map<String, Model> definitions) {
BodyParameter bodyParameter = (BodyParameter) parameter;
Body body = Optional.ofNullable(request.getBody()).orElse(new Body());
body.setType(MsRequestBodyType.RAW.value());
Model schema = bodyParameter.getSchema();
if (schema instanceof RefModel) {
String simpleRef = "";
RefModel refModel = (RefModel) bodyParameter.getSchema();
String originalRef = refModel.getOriginalRef();
if (refModel.getOriginalRef().split("/").length > 3) {
simpleRef = originalRef.replace("#/definitions/", "");
} else {
simpleRef = refModel.getSimpleRef();
}
Model model = definitions.get(simpleRef);
HashSet<String> refSet = new HashSet<>();
refSet.add(simpleRef);
if (model != null) {
JSONObject bodyParameters = getBodyJSONObjectParameters(model.getProperties(), definitions, refSet);
body.setRaw(bodyParameters.toJSONString());
}
} else if (schema instanceof ArrayModel) {
ArrayModel arrayModel = (ArrayModel) bodyParameter.getSchema();
Property items = arrayModel.getItems();
if (items instanceof RefProperty) {
RefProperty refProperty = (RefProperty) items;
String simpleRef = refProperty.getSimpleRef();
HashSet<String> refSet = new HashSet<>();
refSet.add(simpleRef);
Model model = definitions.get(simpleRef);
JSONArray propertyList = new JSONArray();
propertyList.add(getBodyJSONObjectParameters(model.getProperties(), definitions, refSet));
body.setRaw(propertyList.toString());
}
}
request.setBody(body);
body.setFormat("json");
}
private JSONObject getBodyJSONObjectParameters(Map<String, Property> properties, Map<String, Model> definitions, HashSet<String> refSet) {
JSONObject jsonObject = new JSONObject();
if (properties != null) {
properties.forEach((key, value) -> {
if (value instanceof ObjectProperty) {
ObjectProperty objectProperty = (ObjectProperty) value;
jsonObject.put(key, getBodyJSONObjectParameters(objectProperty.getProperties(), definitions, refSet));
} else if (value instanceof ArrayProperty) {
ArrayProperty arrayProperty = (ArrayProperty) value;
Property items = arrayProperty.getItems();
if (items instanceof RefProperty) {
RefProperty refProperty = (RefProperty) items;
String simpleRef = refProperty.getSimpleRef();
if (refSet.contains(simpleRef)) {
jsonObject.put(key, new JSONArray());
return;
}
refSet.add(simpleRef);
Model model = definitions.get(simpleRef);
JSONArray propertyList = new JSONArray();
propertyList.add(getBodyJSONObjectParameters(model.getProperties(), definitions, refSet));
jsonObject.put(key, propertyList);
} else {
jsonObject.put(key, new ArrayList<>());
}
} else {
jsonObject.put(key, Optional.ofNullable(value.getDescription()).orElse(""));
}
});
}
return jsonObject;
}
private void parseFormDataParameters(Parameter parameter, HttpRequest request) {
Body body = Optional.ofNullable(request.getBody()).orElse(new Body());
body.setType(MsRequestBodyType.FORM_DATA.value());
List<KeyValue> keyValues = Optional.ofNullable(body.getKvs()).orElse(new ArrayList<>());
keyValues.add(new KeyValue(parameter.getName(), "", parameter.getDescription()));
body.setKvs(keyValues);
request.setBody(body);
}
private void parseQueryParameters(Parameter parameter, HttpRequest request) {
QueryParameter queryParameter = (QueryParameter) parameter;
List<KeyValue> parameters = Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>());
parameters.add(new KeyValue(queryParameter.getName(), "", queryParameter.getDescription()));
request.setParameters(parameters);
}
}

View File

@ -6,9 +6,9 @@ import io.metersphere.api.dto.*;
import io.metersphere.api.dto.parse.ApiImport; import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.parse.ApiImportParser; import io.metersphere.api.parse.old.ApiImportParser;
import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.api.parse.old.ApiImportParserFactory;
import io.metersphere.api.parse.JmeterDocumentParser; import io.metersphere.api.parse.old.JmeterDocumentParser;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiTestFileMapper; import io.metersphere.base.mapper.ApiTestFileMapper;
import io.metersphere.base.mapper.ApiTestMapper; import io.metersphere.base.mapper.ApiTestMapper;

View File

@ -75,6 +75,7 @@
}); });
} }
}); });
if (request.body.binary) {
request.body.binary.forEach(param => { request.body.binary.forEach(param => {
if (param.files) { if (param.files) {
param.files.forEach(item => { param.files.forEach(item => {
@ -91,6 +92,7 @@
} }
}); });
} }
}
}); });
return bodyUploadFiles; return bodyUploadFiles;
}, },

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-radio-group v-model="body.type" size="mini"> <el-radio-group v-model="body.type" size="mini">
<el-radio :disabled="isReadOnly" :label="type.KV" @change="modeChange"> <el-radio :disabled="isReadOnly" :label="type.FORM_DATA" @change="modeChange">
{{ $t('api_test.definition.request.body_form_data') }} {{ $t('api_test.definition.request.body_form_data') }}
</el-radio> </el-radio>
@ -29,19 +29,19 @@
:parameters="body.kvs" :parameters="body.kvs"
:isShowEnable="isShowEnable" :isShowEnable="isShowEnable"
type="body" type="body"
v-if="body.type == 'KeyValue'"/> v-if="body.type == 'Form Data'"/>
<ms-api-from-url-variable :is-read-only="isReadOnly" <ms-api-from-url-variable :is-read-only="isReadOnly"
:parameters="body.fromUrlencoded" :parameters="body.kvs"
type="body" type="body"
v-if="body.type == 'WWW_FORM'"/> v-if="body.type == 'WWW_FORM'"/>
<div class="ms-body" v-if="body.type == 'JSON'"> <div class="ms-body" v-if="body.type == 'JSON'">
<ms-json-code-edit @json-change="jsonChange" @onError="jsonError" :value="body.json" ref="jsonCodeEdit"/> <ms-json-code-edit @json-change="jsonChange" @onError="jsonError" :value="body.raw" ref="jsonCodeEdit"/>
</div> </div>
<div class="ms-body" v-if="body.type == 'XML'"> <div class="ms-body" v-if="body.type == 'XML'">
<ms-code-edit :read-only="isReadOnly" :data.sync="body.xml" :modes="modes" ref="codeEdit"/> <ms-code-edit :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/>
</div> </div>
@ -145,7 +145,7 @@
} }
}, },
jsonChange(json) { jsonChange(json) {
this.body.json = json; this.body.raw = JSON.stringify(json);
}, },
jsonError(e) { jsonError(e) {
this.$error(e); this.$error(e);

View File

@ -18,7 +18,7 @@
</el-tab-pane> </el-tab-pane>
<!--query 参数--> <!--query 参数-->
<el-tab-pane :label="$t('api_test.definition.request.query_param')" name="parameters" :disabled="request.rest.length>1"> <el-tab-pane :label="$t('api_test.definition.request.query_param')" name="parameters" :disabled="request.arguments.length>1">
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.query_info')" placement="top-start" slot="label"> <el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.query_info')" placement="top-start" slot="label">
<span>{{$t('api_test.definition.request.query_param')}} <span>{{$t('api_test.definition.request.query_param')}}
<div class="el-step__icon is-text ms-api-col ms-query" v-if="request.arguments.length>1"> <div class="el-step__icon is-text ms-api-col ms-query" v-if="request.arguments.length>1">
@ -30,7 +30,7 @@
</el-tab-pane> </el-tab-pane>
<!--REST 参数--> <!--REST 参数-->
<el-tab-pane :label="$t('api_test.definition.request.rest_param')" name="rest" :disabled="request.arguments.length>1"> <el-tab-pane :label="$t('api_test.definition.request.rest_param')" name="rest" >
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.rest_info')" placement="top-start" slot="label"> <el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.rest_info')" placement="top-start" slot="label">
<span> <span>
{{$t('api_test.definition.request.rest_param')}} {{$t('api_test.definition.request.rest_param')}}
@ -98,7 +98,7 @@
import {createComponent} from "../../jmeter/components"; import {createComponent} from "../../jmeter/components";
import MsApiAssertions from "../../assertion/ApiAssertions"; import MsApiAssertions from "../../assertion/ApiAssertions";
import MsApiExtract from "../../extract/ApiExtract"; import MsApiExtract from "../../extract/ApiExtract";
import {Assertions, Extract} from "../../../model/ApiTestModel"; import {Assertions, Body, Extract} from "../../../model/ApiTestModel";
export default { export default {
name: "MsApiHttpRequestForm", name: "MsApiHttpRequestForm",
@ -109,7 +109,12 @@
}, },
props: { props: {
request: {}, request: {},
headers: Array, headers: {
type: Array,
default() {
return [];
}
},
isShowEnable: Boolean, isShowEnable: Boolean,
jsonPathList: Array, jsonPathList: Array,
isReadOnly: { isReadOnly: {
@ -144,6 +149,11 @@
isReloadData: false, isReloadData: false,
} }
}, },
created() {
this.init();
},
methods: { methods: {
addPre() { addPre() {
let jsr223PreProcessor = createComponent("JSR223PreProcessor"); let jsr223PreProcessor = createComponent("JSR223PreProcessor");
@ -176,6 +186,20 @@
this.isReloadData = false this.isReloadData = false
}) })
}, },
init() {
if (!this.request.body) {
this.request.body = new Body();
}
if (!this.request.body.kvs) {
this.request.body.kvs = [];
}
if (!this.request.rest) {
this.request.rest = [];
}
if (!this.request.arguments) {
this.request.arguments = [];
}
}
}, },
} }
</script> </script>

View File

@ -720,12 +720,9 @@ export class Body extends BaseConfig {
this.type = "KeyValue"; this.type = "KeyValue";
this.raw = undefined; this.raw = undefined;
this.kvs = []; this.kvs = [];
this.fromUrlencoded = [];
this.binary = []; this.binary = [];
this.xml = undefined;
this.json = undefined;
this.set(options); this.set(options);
this.sets({kvs: KeyValue}, {fromUrlencoded: KeyValue}, {binary: KeyValue}, options); this.sets({kvs: KeyValue}, {binary: KeyValue}, options);
} }
isValid() { isValid() {

View File

@ -42,7 +42,7 @@
return { return {
editor: null, editor: null,
error: false, error: false,
json: this.value, json: JSON.parse(this.value),
internalChange: false, internalChange: false,
expandedModes: ["tree", "view", "form"], expandedModes: ["tree", "view", "form"],
}; };

@ -1 +1 @@
Subproject commit a22a3005d9bd254793fcf634d72539cbdf31be3a Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8