feat(接口测试): 接口调试导入curl

This commit is contained in:
WangXu10 2024-08-27 15:25:27 +08:00 committed by Craftsman
parent 3164f98e8b
commit 0b7826c0f9
16 changed files with 835 additions and 3 deletions

View File

@ -453,3 +453,7 @@ api_definition.status.continuous=Continuous
api_test_case.clear.api_change=Ignore the differences in this change api_test_case.clear.api_change=Ignore the differences in this change
api_test_case.ignore.api_change=Ignore all change differences api_test_case.ignore.api_change=Ignore all change differences
curl_script_is_empty=Curl script cannot be empty
curl_script_is_invalid=Curl script is invalid
curl_raw_content_is_invalid=Raw content is invalid

View File

@ -421,3 +421,7 @@ api_definition.status.continuous=连调中
api_test_case.clear.api_change=忽略本次变更差异 api_test_case.clear.api_change=忽略本次变更差异
api_test_case.ignore.api_change=忽略全部变更差异 api_test_case.ignore.api_change=忽略全部变更差异
curl_script_is_empty=cURL脚本不能为空
curl_script_is_invalid=cURL脚本格式不正确
curl_raw_content_is_invalid=raw内容格式不正确

View File

@ -421,3 +421,7 @@ api_definition.status.continuous=持續中
api_test_case.clear.api_change=忽略本次變更差異 api_test_case.clear.api_change=忽略本次變更差異
api_test_case.ignore.api_change=忽略全部變更差異 api_test_case.ignore.api_change=忽略全部變更差異
curl_script_is_empty=curl脚本不能爲空
curl_script_is_invalid=curl脚本格式不正確
curl_raw_content_is_invalid=raw内容格式不正確

View File

@ -1,8 +1,11 @@
package io.metersphere.api.controller.debug; package io.metersphere.api.controller.debug;
import io.metersphere.api.curl.domain.CurlEntity;
import io.metersphere.api.curl.util.CurlParserUtil;
import io.metersphere.api.domain.ApiDebug; import io.metersphere.api.domain.ApiDebug;
import io.metersphere.api.dto.debug.*; import io.metersphere.api.dto.debug.*;
import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ApiEditPosRequest;
import io.metersphere.api.dto.request.ApiImportCurlRequest;
import io.metersphere.api.dto.request.ApiTransferRequest; import io.metersphere.api.dto.request.ApiTransferRequest;
import io.metersphere.api.service.ApiFileResourceService; import io.metersphere.api.service.ApiFileResourceService;
import io.metersphere.api.service.debug.ApiDebugLogService; import io.metersphere.api.service.debug.ApiDebugLogService;
@ -120,4 +123,14 @@ public class ApiDebugController {
public List<BaseTreeNode> options(@PathVariable String projectId) { public List<BaseTreeNode> options(@PathVariable String projectId) {
return fileModuleService.getTree(projectId); return fileModuleService.getTree(projectId);
} }
@PostMapping("/import-curl")
@Operation(summary = "接口测试-接口调试-导入curl")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_IMPORT)
public CurlEntity importCurl(@RequestBody ApiImportCurlRequest request) {
CurlEntity parse = CurlParserUtil.parse(request.getCurl());
return parse;
}
} }

View File

@ -0,0 +1,73 @@
package io.metersphere.api.curl.constants;
import java.util.regex.Pattern;
/**
* @author wx
*/
public interface CurlPatternConstants {
/**
* CURL结构校验
*/
Pattern CURL_STRUCTURE_PATTERN = Pattern.compile("^curl");
/**
* URL路径
*/
Pattern URL_PATH_PATTERN = Pattern.compile("(?:\\s|^)(?:'|\")?(https?://[^\\s'\"]*(?:\\?[^\\s'\"]*)?)(?:'|\")?(?:\\s|$)");
/**
* URL_PARAMS请求参数
*/
Pattern URL_PARAMS_PATTERN = Pattern.compile("(?:\\s|^)(?:'|\")?(https?://[^\\s'\"]+)(?:'|\")?(?:\\s|$)");
/**
* HTTP请求方法
*/
Pattern HTTP_METHOD_PATTERN = Pattern.compile("curl\\s+[^\\s]*\\s+(?:-X|--request)\\s+'?(GET|POST)'?");
/**
* 默认HTTP请求方法
*/
Pattern DEFAULT_HTTP_METHOD_PATTERN = Pattern.compile(".*\\s(-d|--data|--data-binary)\\s.*");
/**
* 请求头
*/
Pattern CURL_HEADERS_PATTERN = Pattern.compile("(?:-H|--header)\\s+(?:\"([^\"]*)\"|'([^']*)')");
/**
* -u/--user 请求头
*/
Pattern CURL_USER_HEAD_PATTERN = Pattern.compile("-(u|user)\\s+(\\S+:\\S+)");
/**
* -d/--data 请求体
*/
Pattern DEFAULT_HTTP_BODY_PATTERN = Pattern.compile("(?:--data|-d)\\s+(?:'([^']*)'|\"([^\"]*)\"|(\\S+))", Pattern.DOTALL);
Pattern DEFAULT_HTTP_BODY_PATTERN_KV = Pattern.compile("^([^=&]+=[^=&]+)(?:&[^=&]+=[^=&]+)*$", Pattern.DOTALL);
/**
* --data-raw 请求体
*/
Pattern HTTP_ROW_BODY_PATTERN = Pattern.compile("--data-raw '(.+?)'(?s)", Pattern.DOTALL);
/**
* --form 请求体
*/
Pattern HTTP_FROM_BODY_PATTERN = Pattern.compile("--form\\s+'(.*?)'|-F\\s+'(.*?)'");
/**
* --data-urlencode 请求体
*/
Pattern HTTP_URLENCODE_BODY_PATTERN = Pattern.compile("--data-urlencode\\s+'(.*?)'");
/**
* -x/--proxy 代理配置
*/
Pattern PROXY_PATTERN = Pattern.compile("(-x|--proxy)\\s+[\\S]+");
}

View File

@ -0,0 +1,50 @@
package io.metersphere.api.curl.domain;
import lombok.Builder;
import lombok.Data;
import org.json.JSONObject;
import java.util.Map;
/**
* @author wx
*/
@Data
@Builder
public class CurlEntity {
/**
* URL路径
*/
private String url;
/**
* 请求方法类型
*/
private Method method;
/**
* URL参数
*/
private Map<String, String> queryParams;
/**
* header参数
*/
private Map<String, String> headers;
/**
* 请求体
*/
private JSONObject body;
public enum Method {
GET,
POST,
PUT,
DELETE,
PATCH,
OPTIONS,
HEAD,
CONNECT
}
}

View File

@ -0,0 +1,76 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
/**
* @author wx
*/
public abstract class CurlHandlerChain implements ICurlHandler<CurlEntity, String> {
ICurlHandler<CurlEntity, String> next;
@Override
public ICurlHandler<CurlEntity, String> next(ICurlHandler<CurlEntity, String> handler) {
this.next = handler;
return this.next;
}
@Override
public abstract void handle(CurlEntity entity, String curl);
protected void nextHandle(CurlEntity curlEntity, String curl) {
if (next != null) {
next.handle(curlEntity, curl);
}
}
protected void validate(String curl) {
if (StringUtils.isBlank(curl)) {
throw new MSException(Translator.get("curl_script_is_empty"));
}
Matcher matcher = CurlPatternConstants.CURL_STRUCTURE_PATTERN.matcher(curl);
if (!matcher.find()) {
throw new MSException(Translator.get("curl_script_is_invalid"));
}
}
public static CurlHandlerChain init() {
return new CurlHandlerChain() {
@Override
public void handle(CurlEntity entity, String curl) {
this.validate(curl);
// 替换掉可能存在的转译(字符串中的空白字符包括空格换行符和制表符...)
curl = curl.replace("\\", "")
.replace("\n", "")
.replace("\t", "");
Matcher matcher = CurlPatternConstants.PROXY_PATTERN.matcher(curl);
if (matcher.find()) {
curl = matcher.replaceAll("").trim();
}
int compressedIndex = curl.indexOf("--compressed");
if (compressedIndex != -1) {
String beforeCompressed = curl.substring(4, compressedIndex);
String afterCompressed = curl.substring(compressedIndex + "--compressed".length());
curl = "curl" + afterCompressed + beforeCompressed;
}
if (next != null) {
next.handle(entity, curl);
}
}
};
}
}

View File

@ -0,0 +1,61 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import org.apache.commons.lang3.StringUtils;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
/**
* @author wx
*/
public class HeaderHandler extends CurlHandlerChain {
@Override
public void handle(CurlEntity entity, String curl) {
Map<String, String> headers = parseHeaders(curl);
entity.setHeaders(headers);
super.nextHandle(entity, curl);
}
/**
* header解析
*
* @param curl
* @return
*/
private Map<String, String> parseHeaders(String curl) {
if (StringUtils.isBlank(curl)) {
return Collections.emptyMap();
}
Matcher matcher = CurlPatternConstants.CURL_HEADERS_PATTERN.matcher(curl);
Map<String, String> headers = new HashMap<>();
while (matcher.find()) {
String header = "";
if (matcher.group(1) != null) {
header = matcher.group(1);
} else {
header = matcher.group(2);
}
String[] headerKeyValue = header.split(":", 2);
if (headerKeyValue.length == 2) {
// 去除键和值的首尾空白字符
headers.put(headerKeyValue[0].trim(), headerKeyValue[1].trim());
}
}
Matcher userMatcher = CurlPatternConstants.CURL_USER_HEAD_PATTERN.matcher(curl);
if (userMatcher.find()) {
String user = userMatcher.group(2);
headers.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(user.getBytes()));
}
return headers;
}
}

View File

@ -0,0 +1,186 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import io.metersphere.api.utils.JSONUtil;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
/**
* @author wx
*/
public class HttpBodyHandler extends CurlHandlerChain {
@Override
public void handle(CurlEntity entity, String curl) {
JSONObject body = parseBody(curl);
entity.setBody(body);
super.nextHandle(entity, curl);
}
/**
* 请求体解析
*
* @param curl
* @return
*/
private JSONObject parseBody(String curl) {
Matcher formMatcher = CurlPatternConstants.HTTP_FROM_BODY_PATTERN.matcher(curl);
if (formMatcher.find()) {
return parseFormBody(formMatcher);
}
Matcher urlencodeMatcher = CurlPatternConstants.HTTP_URLENCODE_BODY_PATTERN.matcher(curl);
if (urlencodeMatcher.find()) {
return parseUrlEncodeBody(urlencodeMatcher);
}
Matcher rawMatcher = CurlPatternConstants.HTTP_ROW_BODY_PATTERN.matcher(curl);
if (rawMatcher.find()) {
return parseRowBody(rawMatcher);
}
Matcher defaultMatcher = CurlPatternConstants.DEFAULT_HTTP_BODY_PATTERN.matcher(curl);
if (defaultMatcher.find()) {
return parseDefaultBody(defaultMatcher);
}
return new JSONObject();
}
private JSONObject parseDefaultBody(Matcher defaultMatcher) {
String bodyStr = "";
if (defaultMatcher.group(1) != null) {
//单引号数据
bodyStr = defaultMatcher.group(1);
} else if (defaultMatcher.group(2) != null) {
//双引号数据
bodyStr = defaultMatcher.group(2);
} else {
//无引号数据
bodyStr = defaultMatcher.group(3);
}
if (isJSON(bodyStr)) {
return JSONUtil.parseObject(bodyStr);
}
//其他格式 a=b&c=d
Matcher kvMatcher = CurlPatternConstants.DEFAULT_HTTP_BODY_PATTERN_KV.matcher(bodyStr);
return kvMatcher.matches() ? parseKVBody(bodyStr) : new JSONObject();
}
private JSONObject parseKVBody(String kvBodyStr) {
JSONObject json = new JSONObject();
String[] pairs = kvBodyStr.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
String key = URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8);
String value = URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8);
json.put(key, value);
}
return json;
}
private JSONObject parseFormBody(Matcher formMatcher) {
JSONObject formData = new JSONObject();
formMatcher.reset();
while (formMatcher.find()) {
//提取表单
String formItem = formMatcher.group(1) != null ? formMatcher.group(1) : formMatcher.group(2);
String[] keyValue = formItem.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
//文件属性
if (value.startsWith("@")) {
//获取文件名
formData.put(key, value.substring(1));
} else {
formData.put(key, value);
}
}
}
return formData;
}
private JSONObject parseUrlEncodeBody(Matcher urlencodeMatcher) {
JSONObject urlEncodeData = new JSONObject();
urlencodeMatcher.reset();
while (urlencodeMatcher.find()) {
String keyValueEncoded = urlencodeMatcher.group(1);
String[] keyValue = keyValueEncoded.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
String decodedValue = URLDecoder.decode(value, StandardCharsets.UTF_8);
urlEncodeData.put(key, decodedValue);
}
}
return urlEncodeData;
}
private JSONObject parseRowBody(Matcher rowMatcher) {
String rawData = rowMatcher.group(1);
if (isXML(rawData)) {
return xml2json(rawData);
}
try {
return JSONUtil.parseObject(rawData);
} catch (Exception e) {
throw new MSException(Translator.get("curl_raw_content_is_invalid"), e);
}
}
private boolean isJSON(String jsonStr) {
try {
JSONUtil.parseObject(jsonStr);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isXML(String xmlStr) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("disallow-doctype-decl", false);
factory.setFeature("external-general-entities", false);
factory.setFeature("external-parameter-entities", false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xmlStr));
builder.parse(is);
return true;
} catch (Exception e) {
return false;
}
}
private JSONObject xml2json(String xmlStr) {
try {
JSONObject orgJsonObj = XML.toJSONObject(xmlStr);
String jsonString = orgJsonObj.toString();
return JSONUtil.parseObject(jsonString);
} catch (JSONException e) {
throw new MSException(Translator.get("curl_raw_content_is_invalid"), e);
}
}
}

View File

@ -0,0 +1,41 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import java.util.regex.Matcher;
/**
* @author wx
*/
public class HttpMethodHandler extends CurlHandlerChain {
@Override
public void handle(CurlEntity entity, String curl) {
CurlEntity.Method method = parseMethod(curl);
entity.setMethod(method);
super.nextHandle(entity, curl);
}
/**
* 请求方法解析
*
* @param curl
* @return
*/
private CurlEntity.Method parseMethod(String curl) {
Matcher matcher = CurlPatternConstants.HTTP_METHOD_PATTERN.matcher(curl);
Matcher defaultMatcher = CurlPatternConstants.DEFAULT_HTTP_METHOD_PATTERN.matcher(curl);
if (matcher.find()) {
String method = matcher.group(1);
return CurlEntity.Method.valueOf(method.toUpperCase());
} else if (defaultMatcher.find()) {
//如果命令中包含 -d --data没有明确请求方法默认为 POST
return CurlEntity.Method.POST;
} else {
//没有明确指定请求方法默认为 GET
return CurlEntity.Method.GET;
}
}
}

View File

@ -0,0 +1,13 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.domain.CurlEntity;
/**
* @author wx
*/
public interface ICurlHandler<R, S> {
ICurlHandler<CurlEntity, String> next(ICurlHandler<CurlEntity, String> handler);
void handle(CurlEntity entity, String curl);
}

View File

@ -0,0 +1,63 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
/**
* @author wx
*/
public class QueryParamsHandler extends CurlHandlerChain {
@Override
public void handle(CurlEntity entity, String curl) {
String url = extractUrl(curl);
Map<String, String> queryParams = parseQueryParams(url);
entity.setQueryParams(queryParams);
super.nextHandle(entity, curl);
}
private String extractUrl(String curl) {
Matcher matcher = CurlPatternConstants.URL_PARAMS_PATTERN.matcher(curl);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
/**
* query参数解析
*
* @param url
* @return
*/
private Map<String, String> parseQueryParams(String url) {
if (StringUtils.isBlank(url)) {
return Collections.emptyMap();
}
Map<String, String> queryParams = new HashMap<>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
if (idx != -1 && idx < pair.length() - 1) {
String key = pair.substring(0, idx);
String value = pair.substring(idx + 1);
queryParams.put(key, value);
} else {
queryParams.put(pair, null);
}
}
}
return queryParams;
}
}

View File

@ -0,0 +1,34 @@
package io.metersphere.api.curl.handler;
import io.metersphere.api.curl.constants.CurlPatternConstants;
import io.metersphere.api.curl.domain.CurlEntity;
import java.util.regex.Matcher;
/**
* @author wx
*/
public class UrlPathHandler extends CurlHandlerChain {
@Override
public void handle(CurlEntity entity, String curl) {
String url = parseUrlPath(curl);
entity.setUrl(url);
super.nextHandle(entity, curl);
}
/**
* url路径解析
*
* @param curl
* @return
*/
private String parseUrlPath(String curl) {
Matcher matcher = CurlPatternConstants.URL_PATH_PATTERN.matcher(curl);
if (matcher.find()) {
return matcher.group(1) != null ? matcher.group(1) : matcher.group(3);
}
return null;
}
}

View File

@ -0,0 +1,30 @@
package io.metersphere.api.curl.util;
import io.metersphere.api.curl.domain.CurlEntity;
import io.metersphere.api.curl.handler.*;
/**
* @author wx
*/
public class CurlParserUtil {
/**
* 解析crul 工具类
* @param curl
* @return
*/
public static CurlEntity parse(String curl) {
CurlEntity entity = CurlEntity.builder().build();
ICurlHandler<CurlEntity, String> handlerChain = CurlHandlerChain.init();
handlerChain.next(new UrlPathHandler())
.next(new QueryParamsHandler())
.next(new HttpMethodHandler())
.next(new HeaderHandler())
.next(new HttpBodyHandler());
handlerChain.handle(entity, curl);
return entity;
}
}

View File

@ -0,0 +1,17 @@
package io.metersphere.api.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* @author wx
*/
@Data
public class ApiImportCurlRequest implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "curl字符串")
private String curl;
}

View File

@ -12,6 +12,7 @@ import io.metersphere.api.dto.debug.*;
import io.metersphere.api.dto.definition.ResponseBinaryBody; import io.metersphere.api.dto.definition.ResponseBinaryBody;
import io.metersphere.api.dto.definition.ResponseBody; import io.metersphere.api.dto.definition.ResponseBody;
import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ApiEditPosRequest;
import io.metersphere.api.dto.request.ApiImportCurlRequest;
import io.metersphere.api.dto.request.ApiTransferRequest; import io.metersphere.api.dto.request.ApiTransferRequest;
import io.metersphere.api.dto.request.MsCommonElement; import io.metersphere.api.dto.request.MsCommonElement;
import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.api.dto.request.http.MsHTTPElement;
@ -94,6 +95,8 @@ public class ApiDebugControllerTests extends BaseTest {
public static final String TRANSFER_OPTION = "transfer/options"; public static final String TRANSFER_OPTION = "transfer/options";
public static final String TRANSFER = "transfer"; public static final String TRANSFER = "transfer";
public static final String IMPORT_CURL = "import-curl";
@Resource @Resource
private ApiDebugMapper apiDebugMapper; private ApiDebugMapper apiDebugMapper;
@Resource @Resource
@ -782,4 +785,164 @@ public class ApiDebugControllerTests extends BaseTest {
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_DELETE, DEFAULT_DELETE, addApiDebug.getId()); requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_DELETE, DEFAULT_DELETE, addApiDebug.getId());
} }
@Test
@Order(18)
public void testImportCurl() throws Exception {
ApiImportCurlRequest request = new ApiImportCurlRequest();
//浏览器 curl 测试
String curl = "curl 'https://127.0.0.1:8081/api/definition/page' \\\n" +
" -H 'Accept: application/json, text/plain, */*' \\\n" +
" -H 'Accept-Language: zh-CN' \\\n" +
" -H 'CSRF-TOKEN: 1234454351313131431' \\\n" +
" -H 'Connection: keep-alive' \\\n" +
" -H 'Content-Type: application/json;charset=UTF-8' \\\n" +
" -H 'ORGANIZATION: 100001' \\\n" +
" -H 'Origin: http://127.0.0.1:8081' \\\n" +
" -H 'PROJECT: 100001100001' \\\n" +
" -H 'Referer: http://127.0.0.1:8081/' \\\n" +
" -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \\\n" +
" -H 'X-AUTH-TOKEN: 45fdgsrgdsg-2baf-40bc-98ba-5dsg15s1fg' \\\n" +
" --data-raw '{\"current\":1,\"pageSize\":10,\"sort\":{},\"keyword\":\"\",\"combine\":{},\"searchMode\":\"AND\",\"projectId\":\"100001100001\",\"moduleIds\":[],\"protocols\":[\"HTTP\"],\"filter\":{\"status\":[],\"method\":[],\"priority\":[]},\"excludeIds\":[\"123456783242123\",\"\",\"\"]}' \\\n" +
" --insecure";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl 'http://127.0.0.1:8081/project/get-member/option/100001100001?_t=1724293604633' \\\n" +
" -H 'Accept: application/json, text/plain, */*' \\\n" +
" -H 'Accept-Language: zh-CN' \\\n" +
" -H 'CSRF-TOKEN: Q+DnK2GzMwG07cIVmaaeqSHZFeOk6RnorsyXL9eSCASECASDFJzHzwj60q9uW43o/yESDFSCESASDSFASDH3xXTiCXRxPXT6spuFIHjmYQ+AYbw=' \\\n" +
" -H 'ORGANIZATION: 100001' \\\n" +
" -H 'PROJECT: 1202136548611' \\\n" +
" -H 'Proxy-Connection: keep-alive' \\\n" +
" -H 'Referer: http://127.0.0.1:8081/' \\\n" +
" -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \\\n" +
" -H 'X-AUTH-TOKEN: 85de962d-2baf-40bc-98ba-9af2e6564d0b' \\\n" +
" --insecure";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//抓包格式测试
//Charles工具 curl 测试
curl = "curl \n" +
"-H 'Host: 127.0.0.1:8081' \n" +
"-H 'Accept: application/json, text/plain, */*' \n" +
"-H 'CSRF-TOKEN: Q+DnK2GzMwG07cIVmaaeqSHZFeOk6RnorsyXL9eD9VxP3FEJzHzwj60q9uW43o/y0Exoa6kQub0sN0H3xXTiCXRxPXT6spuFIHjmYQ+AYbw=' \n" +
"-H 'X-AUTH-TOKEN: 512dsfsfds255d-2baf-40bc-98ba-5dsg15s1fg' \n" +
"-H 'PROJECT: 124548721548' \n" +
"-H 'Accept-Language: zh-CN' \n" +
"-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \n" +
"-H 'ORGANIZATION: 100001' -H 'Referer: http://127.0.0.1:8081/' \n" +
"--compressed 'http://127.0.0.1:8081/project/get/100001100001?_t=1724294013069'";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//Fiddler工具 curl 测试
curl = "curl -X POST 'http://example.com/api' -H 'Accept: application/json' -H 'User-Agent: Fiddler' -H 'Authorization: Bearer token_here'";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//GET 请求 测试
curl = "curl -X GET https://example.com";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//POST 请求带数据 测试
curl = "curl -X POST -d 'key1=value1&key2=value2' https://example.com/post";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//json数据 测试
curl = "curl -X POST -H 'Content-Type: application/json' -d '{\"key\":\"value\"}' https://example.com/post";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//文件 测试
curl = "curl -F 'file=@path/to/file' https://example.com/upload";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//自定义头部和认证 测试
curl = "curl -H 'Authorization: Bearer token' -H 'Accept: application/json' -u username:password https://example.com";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
//组合 测试
curl = "curl -X POST \\\n" +
"-u username:password \\\n" +
"-H 'Content-Type: multipart/form-data' \\\n" +
"-H 'Custom-Header: Value' \\\n" +
"-F 'file=@/path/to/file' \\\n" +
"-F 'param1=value1' \\\n" +
"https://example.com/upload";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl -X GET \\\n" +
"-H 'Authorization: Bearer YOUR_TOKEN' \\\n" +
"-L \\\n" +
"-v \\\n" +
"https://example.com/resource";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl -X GET \\\n" +
"-H 'Accept: application/json' \\\n" +
"-x http://proxyserver:port \\\n" +
"-i \\\n" +
"https://example.com/api?param1=value1&param2=value2";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl -X POST \\\n" +
"-H 'Content-Type: application/json' \\\n" +
"-d '{\"key1\": \"value1\", \"key2\": \"value2\"}' \\\n" +
"--max-time 30 \\\n" +
"--retry 3 \\\n" +
"https://example.com/api";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl 'https://www.tapd.cn/2335412151/prong/iterations/card_view/123465456789431534?q=fsadfasjhkahkrhfdsasccasfsdf' \\\n" +
" -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \\\n" +
" -H 'Accept-Language: zh-CN,zh;q=0.9' \\\n" +
" -H 'Cache-Control: max-age=0' \\\n" +
" -H 'Connection: keep-alive' \\\n" +
" -H 'Cookie: iter_card_status=; 66565258464512_55234234_iterations_card_view_close_status=0; 232564132154_55023423_/prong/iterations/index_remember_view=134247554678224278546; iter_card_status=; 412045464_5123433_iterations_card_view_close_status=0; left_iteration_list_token=20225424528746eda6e21g1dfgd51867891ef7cbb3a9; tui_filter_fields=%5B%13d1gd51r1gf23d1r%2C%22owner%22%2C%22dg13dr51ation_id2C%dsf22priority%22%5D; 112315sc39_5501533_/prong/tasks/index_remember_view=115501223315036973; 5dfsse933_11324fsd3001000025_story_create_template=1155041233424001000009; tapdsession=17174887199dc61sdfscaeerg229dcd5beb5c16d6062b32d6cesc68a61f51fb; __root_domain_v=.tapd.cn; _qddaz=QD.147917cscse0554; t_u=7ab057cd1f0c6casedfcasfr61d09eb29f94c12a82c73007d3e505f68411bdfgdrg156f1b984a7b98566b7bdsafs2937ccb1974809f3fsef3f828%7C1; iteration_view_type_cookie=card_view; fsefdcdcbug_create_template=1155049f12055242000010; new_worktable=search_filter; dsc-token=V0FahgEQeO8hNyzI; 5532133_11550434242340025_story_create_template=115504234234000009; iteration_card_tab_33242490=list; iteration_card_current_iteration_334235590=--; cloud_current_workspaceId=53429234; iteration_card_tab_324234dd=list; _t_uid=19732439; _t_crop=6049432436; tapd_div=101_2885; locale=zh_CN; iteration_card_current_iteration_5234234=1155042344512542342863' \\\n" +
" -H 'Referer: https://www.tapd.cn/5324120234165/bugtrace/bugs/view?bug_id=1445248132543744315' \\\n" +
" -H 'Sec-Fetch-Dest: document' \\\n" +
" -H 'Sec-Fetch-Mode: navigate' \\\n" +
" -H 'Sec-Fetch-Site: same-origin' \\\n" +
" -H 'Sec-Fetch-User: ?1' \\\n" +
" -H 'Upgrade-Insecure-Requests: 1' \\\n" +
" -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \\\n" +
" -H 'sec-ch-ua: \"Not)A;Brand\";v=\"99\", \"Google Chrome\";v=\"127\", \"Chromium\";v=\"127\"' \\\n" +
" -H 'sec-ch-ua-mobile: ?0' \\\n" +
" -H 'sec-ch-ua-platform: \"macOS\"'";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
curl = "curl 'https://127.0.0.1:8081/api/definition/page' \\\n" +
" -H 'Accept: application/json, text/plain, */*' \\\n" +
" -H 'Accept-Language: zh-CN' \\\n" +
" -H 'CSRF-TOKEN: 1234454351313131431' \\\n" +
" -H 'Connection: keep-alive' \\\n" +
" -H 'Content-Type: application/json;charset=UTF-8' \\\n" +
" -H 'ORGANIZATION: 100001' \\\n" +
" -H 'Origin: http://127.0.0.1:8081' \\\n" +
" -H 'PROJECT: 100001100001' \\\n" +
" -H 'Referer: http://127.0.0.1:8081/' \\\n" +
" -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \\\n" +
" -H 'X-AUTH-TOKEN: 45fdgsrgdsg-2baf-40bc-98ba-5dsg15s1fg' \\\n" +
" --data-raw '{current:1,\"pageSize\":10,\"sort\":{},\"keyword\":\"\",\"combine\":{},\"searchMode\":\"AND\",\"projectId\":\"100001100001\",\"moduleIds\":[],\"protocols\":[\"HTTP\"],\"filter\":{\"status\":[],\"method\":[],\"priority\":[]},\"excludeIds\":[\"123456783242123\",\"\",\"\"]}' \\\n" +
" --insecure";
request.setCurl(curl);
this.requestPost(IMPORT_CURL, request);
curl = "curl -X POST -H 'Content-Type: application/json' --data-urlencode '{\"key\":\"value\"}' https://example.com/post";
request.setCurl(curl);
this.requestPostWithOk(IMPORT_CURL, request);
}
} }