diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java index 793e98a529..2614596d53 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java @@ -8,7 +8,7 @@ package io.metersphere.plugin.api.spi; public abstract class AbstractProtocolPlugin extends AbstractApiPlugin { /** - * 返回协议名称 + * 返回协议名 * @return */ abstract public String getProtocol(); diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/QueryParam.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/QueryParam.java index 7b68be2979..419f4853aa 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/QueryParam.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/QueryParam.java @@ -19,4 +19,16 @@ public class QueryParam extends KeyValueParam { * 是否必填 */ private Boolean required = false; + /** + * 最大长度 + */ + private Integer minLength; + /** + * 最小长度 + */ + private Integer maxLength; + /** + * 是否编码 + */ + private Boolean encode = false; } diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/RestParam.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/RestParam.java index 6aab61368e..ec5bc309ab 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/RestParam.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/http/RestParam.java @@ -18,4 +18,16 @@ public class RestParam extends KeyValueParam { * 是否必填 */ private Boolean required = false; + /** + * 最大长度 + */ + private Integer minLength; + /** + * 最小长度 + */ + private Integer maxLength; + /** + * 是否编码 + */ + private Boolean encode = false; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java new file mode 100644 index 0000000000..99ea236386 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java @@ -0,0 +1,32 @@ +package io.metersphere.api.controller; + +import io.metersphere.api.service.ApiTestService; +import io.metersphere.system.dto.ProtocolDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @Author: jianxing + * @CreateTime: 2023-11-06 10:54 + */ +@RestController +@RequestMapping("/api/test") +@Tag(name = "接口测试") +public class ApiTestController { + + @Resource + private ApiTestService apiTestService; + + @GetMapping("/protocol/{organizationId}") + @Operation(summary = "获取协议插件的的协议列表") + public List getProtocols(@PathVariable String organizationId) { + return apiTestService.getProtocols(organizationId); + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java new file mode 100644 index 0000000000..5dccb008c3 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java @@ -0,0 +1,26 @@ +package io.metersphere.api.service; + +import io.metersphere.system.dto.ProtocolDTO; +import io.metersphere.system.service.ApiPluginService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author jianxing + * @date : 2023-11-6 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class ApiTestService { + + @Resource + private ApiPluginService apiPluginService; + + public List getProtocols(String orgId) { + return apiPluginService.getProtocols(orgId); + } + +} \ No newline at end of file diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java new file mode 100644 index 0000000000..c1dfd3c4ff --- /dev/null +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java @@ -0,0 +1,32 @@ +package io.metersphere.api.controller; + +import io.metersphere.system.base.BaseTest; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * @Author: jianxing + * @CreateTime: 2023-11-07 17:07 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@AutoConfigureMockMvc +public class ApiTestControllerTests extends BaseTest { + + private static final String BASE_PATH = "/api/test/"; + protected static final String PROTOCOL_LIST = "protocol/{0}"; + + @Override + protected String getBasePath() { + return BASE_PATH; + } + + @Test + public void getProtocols() throws Exception { + // @@请求成功 + this.requestGetWithOk(PROTOCOL_LIST, this.DEFAULT_ORGANIZATION_ID).andReturn(); + } +} diff --git a/backend/services/api-test/src/test/resources/file/jdbc-sampler-v3.x.jar b/backend/services/api-test/src/test/resources/file/jdbc-sampler-v3.x.jar index 96819f90c6..b176f2bf1c 100644 Binary files a/backend/services/api-test/src/test/resources/file/jdbc-sampler-v3.x.jar and b/backend/services/api-test/src/test/resources/file/jdbc-sampler-v3.x.jar differ diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java index f8b72b6d76..93c76585fd 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/ProtocolDTO.java @@ -8,6 +8,13 @@ import lombok.Data; */ @Data public class ProtocolDTO { + /** + * 协议名 + */ private String protocol; - private String name; + /** + * 协议对应的组件名 + * 例如 Http 对应 MsHTTPElement + */ + private String polymorphicName; } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java index 875fad2372..8e57f2d3ab 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/ApiPluginService.java @@ -1,13 +1,20 @@ package io.metersphere.system.service; import io.metersphere.plugin.api.spi.AbstractProtocolPlugin; +import io.metersphere.plugin.api.spi.MsTestElement; import io.metersphere.sdk.constants.PluginScenarioType; +import io.metersphere.sdk.dto.api.request.http.MsHTTPElement; +import io.metersphere.sdk.util.LogUtils; import io.metersphere.system.domain.Plugin; +import io.metersphere.system.dto.ProtocolDTO; import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.pf4j.PluginWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -20,23 +27,50 @@ public class ApiPluginService { private PluginLoadService pluginLoadService; @Resource private BasePluginService basePluginService; + private static final String HTTP_PROTOCOL = "HTTP"; /** * 获取协议插件的的协议列表 * @param orgId * @return */ - public List getProtocols(String orgId) { + public List getProtocols(String orgId) { // 查询组织下有权限的插件 Set pluginIds = basePluginService.getOrgEnabledPlugins(orgId, PluginScenarioType.API_PROTOCOL) .stream() .map(Plugin::getId) .collect(Collectors.toSet()); + // 过滤协议插件 List plugins = pluginLoadService.getMsPluginManager().getPlugins(); - return plugins.stream() - .filter(plugin -> pluginIds.contains(plugin.getPluginId()) && plugin.getPlugin() instanceof AbstractProtocolPlugin) - .map(plugin -> ((AbstractProtocolPlugin) plugin.getPlugin()).getProtocol()) - .collect(Collectors.toList()); + List pluginWrappers = plugins.stream() + .filter(plugin -> pluginIds.contains(plugin.getPluginId()) && plugin.getPlugin() instanceof AbstractProtocolPlugin).toList(); + + List protocols = new ArrayList(); + pluginWrappers.forEach(pluginWrapper -> { + try { + // 获取插件中 MsTestElement 的实现类 + List> extensionClasses = pluginWrapper.getPluginManager() + .getExtensionClasses(MsTestElement.class, pluginWrapper.getPluginId()); + + AbstractProtocolPlugin protocolPlugin = ((AbstractProtocolPlugin) pluginWrapper.getPlugin()); + ProtocolDTO protocolDTO = new ProtocolDTO(); + protocolDTO.setProtocol(protocolPlugin.getProtocol()); + if (CollectionUtils.isNotEmpty(extensionClasses)) { + protocolDTO.setPolymorphicName(extensionClasses.get(0).getSimpleName()); + } + if (StringUtils.isNoneBlank(protocolDTO.getProtocol(), protocolDTO.getPolymorphicName())) { + protocols.add(protocolDTO); + } + } catch (Exception e) { + LogUtils.error(e); + } + }); + // 将 http 协议放最前面 + ProtocolDTO protocolDTO = new ProtocolDTO(); + protocolDTO.setProtocol(HTTP_PROTOCOL); + protocolDTO.setPolymorphicName(MsHTTPElement.class.getSimpleName()); + protocols.addFirst(protocolDTO); + return protocols; } } diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java new file mode 100644 index 0000000000..242a16327e --- /dev/null +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/service/ApiPluginServiceTests.java @@ -0,0 +1,48 @@ +package io.metersphere.system.service; + +import io.metersphere.sdk.dto.api.request.http.MsHTTPElement; +import io.metersphere.system.base.BaseApiPluginTestService; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.dto.ProtocolDTO; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: jianxing + * @CreateTime: 2023-11-08 16:34 + */ +@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ApiPluginServiceTests extends BaseTest { + @Resource + private BaseApiPluginTestService baseApiPluginTestService; + @Resource + private ApiPluginService apiPluginService; + + @Test + public void getProtocols() throws Exception { + baseApiPluginTestService.addJdbcPlugin(); + + // 校验数据是否正确 + List protocols = apiPluginService.getProtocols(this.DEFAULT_ORGANIZATION_ID); + List expected = new ArrayList(); + ProtocolDTO httpProtocol = new ProtocolDTO(); + httpProtocol.setProtocol("HTTP"); + httpProtocol.setPolymorphicName(MsHTTPElement.class.getSimpleName()); + ProtocolDTO jdbcProtocol = new ProtocolDTO(); + jdbcProtocol.setProtocol("JDBC"); + jdbcProtocol.setPolymorphicName("MsJDBCElement"); + expected.add(httpProtocol); + expected.add(jdbcProtocol); + Assertions.assertEquals(protocols, expected); + } +} diff --git a/backend/services/system-setting/src/test/resources/file/jdbc-sampler-v3.x.jar b/backend/services/system-setting/src/test/resources/file/jdbc-sampler-v3.x.jar new file mode 100644 index 0000000000..b176f2bf1c Binary files /dev/null and b/backend/services/system-setting/src/test/resources/file/jdbc-sampler-v3.x.jar differ