You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2022/07/04 04:32:18 UTC
[incubator-shenyu] branch master updated: [ISSUE 3623][admin] API document enhancement and Optimization: supports the "spring cloud" plug-in and fix bug. (#3649)
This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new afa69b88c [ISSUE 3623][admin] API document enhancement and Optimization: supports the "spring cloud" plug-in and fix bug. (#3649)
afa69b88c is described below
commit afa69b88cc12c1e5742424d10e75483fdef56a2a
Author: lianjunwei <13...@users.noreply.github.com>
AuthorDate: Mon Jul 4 12:32:12 2022 +0800
[ISSUE 3623][admin] API document enhancement and Optimization: supports the "spring cloud" plug-in and fix bug. (#3649)
* apidoc sql
* refact
* commit
* [Task] Shenyu-admin: Fix API document failed to build because of NPE.
* [Task] Shenyu-admin: Fix API document failed to build because of NPE.
* solve conficts,modify LICENSE.
* [ISSUE 3623][admin] API document enhancement and Optimization: pulling the swagger file supports the "spring cloud" plug-in.
* [ISSUE 3623][admin] API document enhancement and Optimization: supports the "spring cloud" plug-in and fix bug.
* delete useless code.
* Undo changes to static files.
* Undo changes to static files.
* solve Server-side request forgery.
* solve Server-side request forgery.
* delete useless code.
* solve Server-side request forgery.
* pull api document needs startTime.
Co-authored-by: lianjunwei <li...@didiglobal.com>
---
.../shenyu/admin/controller/ApiDocController.java | 14 +-
.../shenyu/admin/controller/SandboxController.java | 146 +++++++++------------
.../shenyu/admin/model/dto/ProxyGatewayDTO.java | 139 ++++++++++++++++++++
.../shenyu/admin/model/query/SelectorQuery.java | 30 +++++
.../shenyu/admin/service/AppAuthService.java | 9 ++
.../admin/service/impl/AppAuthServiceImpl.java | 9 +-
.../manager/impl/LoadServiceDocEntryImpl.java | 131 ++++++++++--------
.../service/manager/impl/SwaggerDocParser.java | 3 +-
.../shenyu/admin/utils/CommonUpstreamUtils.java | 2 +-
.../src/main/resources/mappers/selector-sqlmap.xml | 6 +
.../dto/convert/selector/CommonUpstream.java | 38 +++---
.../apache/shenyu/common/enums/RpcTypeEnum.java | 12 +-
.../dto/convert/selector/CommonUpstreamTest.java | 4 +-
13 files changed, 366 insertions(+), 177 deletions(-)
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ApiDocController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ApiDocController.java
index fe762e853..dae0a5614 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ApiDocController.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ApiDocController.java
@@ -21,7 +21,6 @@ import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
-import javax.annotation.Resource;
import org.apache.shenyu.admin.config.properties.ApiDocProperties;
import org.apache.shenyu.admin.model.bean.DocInfo;
import org.apache.shenyu.admin.model.bean.DocItem;
@@ -31,7 +30,6 @@ import org.apache.shenyu.admin.model.vo.MenuDocItem;
import org.apache.shenyu.admin.model.vo.MenuModule;
import org.apache.shenyu.admin.model.vo.MenuProject;
import org.apache.shenyu.admin.service.manager.DocManager;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -43,11 +41,15 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/apidoc")
public class ApiDocController {
- @Autowired
- private DocManager docManager;
+ private final DocManager docManager;
- @Resource
- private ApiDocProperties apiDocProperties;
+ private final ApiDocProperties apiDocProperties;
+
+ public ApiDocController(final DocManager docManager,
+ final ApiDocProperties apiDocProperties) {
+ this.docManager = docManager;
+ this.apiDocProperties = apiDocProperties;
+ }
/**
* Menu list of documents.
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/SandboxController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/SandboxController.java
index 5bb8d5de2..2bacd3c20 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/SandboxController.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/SandboxController.java
@@ -17,7 +17,6 @@
package org.apache.shenyu.admin.controller;
-import com.google.common.collect.Maps;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@@ -28,27 +27,32 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
-import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.shenyu.admin.mapper.AppAuthMapper;
+import org.apache.shenyu.admin.model.dto.ProxyGatewayDTO;
import org.apache.shenyu.admin.model.entity.AppAuthDO;
+import org.apache.shenyu.admin.service.AppAuthService;
+import org.apache.shenyu.admin.utils.Assert;
import org.apache.shenyu.admin.utils.HttpUtils;
import org.apache.shenyu.admin.utils.ShenyuSignatureUtils;
import org.apache.shenyu.admin.utils.UploadUtils;
+import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
/**
@@ -61,74 +65,50 @@ public class SandboxController {
private static final HttpUtils HTTP_UTILS = new HttpUtils();
- @Resource
- private AppAuthMapper appAuthMapper;
+ private final AppAuthService appAuthService;
+
+ public SandboxController(final AppAuthService appAuthService) {
+ this.appAuthService = appAuthService;
+ }
/**
- * proxyGateway.
+ * proxy Gateway.
*
- * @param gatewayUrl gatewayUrl
- * @param appKey appKey
- * @param method method
- * @param cookie cookie
- * @param bizParam bizParam
- * @param httpMethod httpMethod
- * @param request request
- * @param response response
+ * @param proxyGatewayDTO proxyGatewayDTO
+ * @param request request
+ * @param response response
* @throws IOException IOException
*/
- @RequestMapping("/proxyGateway")
- public void proxyGateway(
- @RequestParam(required = false) final String gatewayUrl,
- @RequestParam final String appKey,
- @RequestParam final String method,
- @RequestParam final String cookie,
- @RequestParam final String bizParam,
- @RequestParam(defaultValue = "get") final String httpMethod,
+ @PostMapping(path = "/proxyGateway")
+ public void proxyGateway(@RequestBody @Valid final ProxyGatewayDTO proxyGatewayDTO,
final HttpServletRequest request,
final HttpServletResponse response) throws IOException {
-
- Assert.isTrue(StringUtils.isNotBlank(method), "method cannot be empty.");
- Assert.isTrue(StringUtils.isNotBlank(gatewayUrl), "gatewayUrl cannot be empty.");
- String gatewayUrlStr = gatewayUrl + method;
-
// Public request parameters.
- Map<String, String> params = new HashMap<String, String>();
+ Map<String, Object> reqParams = new HashMap<>();
try {
- String bizParamStr = StringEscapeUtils.escapeHtml4(bizParam);
- Map<String, String> map = (Map) JsonUtils.toMap(bizParamStr);
- LOG.info("bizParam toMap= {}", JsonUtils.toJson(map));
- if (map != null) {
- params.putAll(map);
+ String reqJson = JsonUtils.toJson(proxyGatewayDTO.getBizParam());
+ reqJson = StringEscapeUtils.escapeHtml4(reqJson);
+ Map<String, Object> reqMap = JsonUtils.toMap(reqJson);
+ LOG.info("bizParam toMap= {}", JsonUtils.toJson(reqMap));
+ if (Objects.nonNull(reqMap)) {
+ reqParams.putAll(reqMap);
}
} catch (Exception e) {
- LOG.error("JsonUtils.toMap error={}", e);
+ LOG.error("proxyGateway JsonUtils.toMap error={}", e);
}
- String paramsQuery = buildParamQuery(params);
-
- Collection<MultipartFile> uploadFiles = UploadUtils.getUploadFiles(request);
- List<HttpUtils.UploadFile> files = uploadFiles.stream()
- .map(multipartFile -> {
- try {
- return new HttpUtils.UploadFile(multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getBytes());
- } catch (IOException e) {
- LOG.error("upload file fail", e);
- return null;
- }
- })
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
-
Map<String, String> header = new HashMap<>();
- header.put("Cookie", cookie);
+ header.put("Cookie", proxyGatewayDTO.getCookie());
+ String appKey = proxyGatewayDTO.getAppKey();
+ UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(proxyGatewayDTO.getRequestUrl()).build();
String signContent = null;
String sign = null;
if (StringUtils.isNotEmpty(appKey)) {
String timestamp = String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
String secureKey = getSecureKey(appKey);
- signContent = ShenyuSignatureUtils.getSignContent(secureKey, timestamp, method);
+ Assert.notBlack(secureKey, Constants.SIGN_APP_KEY_IS_NOT_EXIST);
+ signContent = ShenyuSignatureUtils.getSignContent(secureKey, timestamp, uriComponents.getPath());
sign = ShenyuSignatureUtils.generateSign(signContent);
header.put("timestamp", timestamp);
@@ -137,45 +117,39 @@ public class SandboxController {
header.put("version", ShenyuSignatureUtils.VERSION);
}
- try {
- Response resp = HTTP_UTILS.requestCall(gatewayUrlStr, params, header, HttpUtils.HTTPMethod.fromValue(httpMethod), files);
- ResponseBody body = resp.body();
- if (Objects.isNull(body)) {
- return;
- }
- Map<String, List<String>> headersMap = resp.headers().toMultimap();
- Map<String, String> targetHeaders = Maps.newHashMapWithExpectedSize(headersMap.size());
- headersMap.forEach((key, value) -> {
- String headerValue = String.join(",", value);
- response.setHeader(key, headerValue);
- targetHeaders.put(key, headerValue);
- });
- response.addHeader("response-headers", JsonUtils.toJson(targetHeaders));
- response.addHeader("sendbox-params", UriUtils.encode(paramsQuery, StandardCharsets.UTF_8));
- response.addHeader("sendbox-beforesign", UriUtils.encode(signContent, StandardCharsets.UTF_8));
- response.addHeader("sendbox-sign", UriUtils.encode(sign, StandardCharsets.UTF_8));
- IOUtils.copy(body.byteStream(), response.getOutputStream());
- response.flushBuffer();
- } catch (Exception e) {
- LOG.error("request error", e);
- throw new RuntimeException(e.getMessage());
+ List<HttpUtils.UploadFile> files = uploadFiles(request);
+ Response resp = HTTP_UTILS.requestCall(uriComponents.toUriString(), reqParams, header, HttpUtils.HTTPMethod.fromValue(proxyGatewayDTO.getHttpMethod()), files);
+ ResponseBody body = resp.body();
+ if (Objects.isNull(body)) {
+ return;
}
+ if (StringUtils.isNotEmpty(appKey)) {
+ response.addHeader("sandbox-beforesign", UriUtils.encode(signContent, StandardCharsets.UTF_8));
+ response.addHeader("sandbox-sign", UriUtils.encode(sign, StandardCharsets.UTF_8));
+ }
+ IOUtils.copy(body.byteStream(), response.getOutputStream());
+ response.flushBuffer();
}
private String getSecureKey(final String appKey) {
- AppAuthDO appAuthDO = appAuthMapper.findByAppKey(appKey);
- if (Objects.isNull(appAuthDO) || StringUtils.isEmpty(appAuthDO.getAppSecret())) {
- throw new RuntimeException("security key not found.");
- }
- return appAuthDO.getAppSecret();
+ AppAuthDO appAuthDO = appAuthService.findByAppKey(appKey);
+ return Objects.nonNull(appAuthDO) ? appAuthDO.getAppSecret() : null;
}
- protected String buildParamQuery(final Map<String, String> params) {
- StringBuilder sb = new StringBuilder();
- for (Map.Entry<String, String> entry : params.entrySet()) {
- sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
- }
- return sb.substring(1);
+ private List<HttpUtils.UploadFile> uploadFiles(final HttpServletRequest request) {
+ Collection<MultipartFile> uploadFiles = UploadUtils.getUploadFiles(request);
+ List<HttpUtils.UploadFile> files = uploadFiles.stream()
+ .map(multipartFile -> {
+ try {
+ return new HttpUtils.UploadFile(multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getBytes());
+ } catch (IOException e) {
+ LOG.error("upload file fail", e);
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ return files;
}
}
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/ProxyGatewayDTO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/ProxyGatewayDTO.java
new file mode 100644
index 000000000..6d6c5244c
--- /dev/null
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/ProxyGatewayDTO.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.dto;
+
+/**
+ * this User Role Dto.
+ */
+public class ProxyGatewayDTO {
+
+ /**
+ * request Url.
+ */
+ private String requestUrl;
+
+ /**
+ * request appKey.
+ */
+ private String appKey;
+
+ /**
+ * request cookie.
+ */
+ private String cookie;
+
+ /**
+ * request bizParam.
+ */
+ private Object bizParam;
+
+ /**
+ * request httpMethod.
+ */
+ private String httpMethod = "get";
+
+ /**
+ * getRequestUrl.
+ *
+ * @return request Url
+ */
+ public String getRequestUrl() {
+ return requestUrl;
+ }
+
+ /**
+ * setRequestUrl.
+ *
+ * @param requestUrl requestUrl
+ */
+ public void setRequestUrl(final String requestUrl) {
+ this.requestUrl = requestUrl;
+ }
+
+ /**
+ * getAppKey.
+ *
+ * @return appKey
+ */
+ public String getAppKey() {
+ return appKey;
+ }
+
+ /**
+ * setAppKey.
+ *
+ * @param appKey appKey
+ */
+ public void setAppKey(final String appKey) {
+ this.appKey = appKey;
+ }
+
+ /**
+ * getCookie.
+ *
+ * @return cookie
+ */
+ public String getCookie() {
+ return cookie;
+ }
+
+ /**
+ * setCookie.
+ *
+ * @param cookie cookie
+ */
+ public void setCookie(final String cookie) {
+ this.cookie = cookie;
+ }
+
+ /**
+ * getBizParam.
+ *
+ * @return bizParam
+ */
+ public Object getBizParam() {
+ return bizParam;
+ }
+
+ /**
+ * setBizParam.
+ *
+ * @param bizParam bizParam
+ */
+ public void setBizParam(final Object bizParam) {
+ this.bizParam = bizParam;
+ }
+
+ /**
+ * getHttpMethod.
+ *
+ * @return httpMethod
+ */
+ public String getHttpMethod() {
+ return httpMethod;
+ }
+
+ /**
+ * httpMethod.
+ *
+ * @param httpMethod httpMethod
+ */
+ public void setHttpMethod(final String httpMethod) {
+ this.httpMethod = httpMethod;
+ }
+}
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/SelectorQuery.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/SelectorQuery.java
index b15a6409a..12177eeda 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/SelectorQuery.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/SelectorQuery.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.admin.model.query;
+import java.util.List;
import org.apache.shenyu.admin.model.page.PageParameter;
import java.util.Objects;
@@ -33,6 +34,11 @@ public class SelectorQuery extends FilterQuery {
*/
private String pluginId;
+ /**
+ * plugin ids.
+ */
+ private List<String> pluginIds;
+
/**
* selector name.
*/
@@ -52,6 +58,12 @@ public class SelectorQuery extends FilterQuery {
this.pageParameter = pageParameter;
}
+ public SelectorQuery(final List<String> pluginIds, final String name, final PageParameter pageParameter) {
+ this.pluginIds = pluginIds;
+ this.name = name;
+ this.pageParameter = pageParameter;
+ }
+
/**
* Gets the value of pluginId.
*
@@ -70,6 +82,24 @@ public class SelectorQuery extends FilterQuery {
this.pluginId = pluginId;
}
+ /**
+ * Gets the value of pluginIds.
+ *
+ * @return the value of pluginIds
+ */
+ public List<String> getPluginIds() {
+ return pluginIds;
+ }
+
+ /**
+ * Sets the pluginIds.
+ *
+ * @param pluginIds pluginIds
+ */
+ public void setPluginIds(final List<String> pluginIds) {
+ this.pluginIds = pluginIds;
+ }
+
/**
* Gets the value of name.
*
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
index f6c20bd56..063a06abb 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
@@ -20,6 +20,7 @@ package org.apache.shenyu.admin.service;
import org.apache.shenyu.admin.model.dto.AppAuthDTO;
import org.apache.shenyu.admin.model.dto.AuthApplyDTO;
import org.apache.shenyu.admin.model.dto.AuthPathWarpDTO;
+import org.apache.shenyu.admin.model.entity.AppAuthDO;
import org.apache.shenyu.admin.model.page.CommonPager;
import org.apache.shenyu.admin.model.query.AppAuthQuery;
import org.apache.shenyu.admin.model.result.ShenyuAdminResult;
@@ -136,6 +137,14 @@ public interface AppAuthService extends PageService<AppAuthQuery, AppAuthVO> {
*/
ShenyuAdminResult updateAppSecretByAppKey(String appKey, String appSecret);
+ /**
+ * Find by app key app auth do.
+ *
+ * @param appKey the app key
+ * @return the app auth do
+ */
+ AppAuthDO findByAppKey(String appKey);
+
/**
* Sync data shenyu result.
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
index 5eb37d4c5..e632b708a 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
@@ -85,12 +85,12 @@ public class AppAuthServiceImpl implements AppAuthService {
this.authParamMapper = authParamMapper;
this.authPathMapper = authPathMapper;
}
-
+
@Override
public List<AppAuthVO> searchByCondition(final AppAuthQuery condition) {
return appAuthMapper.selectByCondition(condition);
}
-
+
@Override
@Transactional(rollbackFor = Exception.class)
public ShenyuAdminResult applyCreate(final AuthApplyDTO authApplyDTO) {
@@ -421,6 +421,11 @@ public class AppAuthServiceImpl implements AppAuthService {
return ShenyuAdminResult.success(appAuthMapper.updateAppSecretByAppKey(appKey, appSecret));
}
+ @Override
+ public AppAuthDO findByAppKey(final String appKey) {
+ return appAuthMapper.findByAppKey(appKey);
+ }
+
private AppAuthData buildByEntity(final AppAuthDO appAuthDO) {
AppAuthData data = AppAuthData.builder()
.appKey(appAuthDO.getAppKey())
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/LoadServiceDocEntryImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/LoadServiceDocEntryImpl.java
index 6017726e4..97b5907bf 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/LoadServiceDocEntryImpl.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/LoadServiceDocEntryImpl.java
@@ -17,32 +17,38 @@
package org.apache.shenyu.admin.service.manager.impl;
+import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
-import javax.annotation.Resource;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.admin.mapper.PluginMapper;
import org.apache.shenyu.admin.model.bean.UpstreamInstance;
+import org.apache.shenyu.admin.model.entity.PluginDO;
import org.apache.shenyu.admin.model.page.CommonPager;
import org.apache.shenyu.admin.model.page.PageParameter;
import org.apache.shenyu.admin.model.query.SelectorQuery;
import org.apache.shenyu.admin.model.vo.SelectorVO;
import org.apache.shenyu.admin.service.SelectorService;
+import org.apache.shenyu.admin.service.converter.SelectorHandleConverterFactor;
import org.apache.shenyu.admin.service.manager.LoadServiceDocEntry;
+import org.apache.shenyu.admin.service.manager.ServiceDocManager;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.dto.convert.selector.CommonUpstream;
import org.apache.shenyu.common.enums.DataEventTypeEnum;
-import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.common.utils.PluginNameAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
/**
* Load Service Doc Entry.
@@ -51,11 +57,25 @@ import org.springframework.util.CollectionUtils;
public class LoadServiceDocEntryImpl implements LoadServiceDocEntry {
private static final Logger LOG = LoggerFactory.getLogger(LoadServiceDocEntryImpl.class);
- @Resource
- private SelectorService selectorService;
+ private static Map<String, String> supportSwaggePluginMap = Collections.EMPTY_MAP;
- @Resource
- private ServiceDocManagerImpl serviceDocManager;
+ private final SelectorService selectorService;
+
+ private final SelectorHandleConverterFactor converterFactor;
+
+ private final PluginMapper pluginMapper;
+
+ private final ServiceDocManager serviceDocManager;
+
+ public LoadServiceDocEntryImpl(final SelectorService selectorService,
+ final SelectorHandleConverterFactor converterFactor,
+ final PluginMapper pluginMapper,
+ final ServiceDocManager serviceDocManager) {
+ this.selectorService = selectorService;
+ this.converterFactor = converterFactor;
+ this.pluginMapper = pluginMapper;
+ this.serviceDocManager = serviceDocManager;
+ }
@Override
public synchronized void loadApiDocument() {
@@ -102,13 +122,17 @@ public class LoadServiceDocEntryImpl implements LoadServiceDocEntry {
* @return List
*/
private List<UpstreamInstance> getAllClusterLastUpdateInstanceList() {
- List<SelectorVO> clusterList = null;
- try {
- CommonPager<SelectorVO> commonPager = selectorService.listByPage(new SelectorQuery("5", null, new PageParameter(1, Integer.MAX_VALUE)));
- clusterList = commonPager.getDataList();
- } catch (Exception e) {
- LOG.error("getAllClusterLastUpdateInstanceList fail. error={}", e);
+ List<String> pluginNames = new ArrayList<>();
+ RpcTypeEnum.acquireSupportSwaggers().forEach(rpcTypeEnum -> pluginNames.add(PluginNameAdapter.rpcTypeAdapter(rpcTypeEnum.getName())));
+ final List<PluginDO> pluginDOList = pluginMapper.selectByNames(pluginNames);
+ if (CollectionUtils.isEmpty(pluginDOList)) {
+ return Collections.EMPTY_LIST;
}
+ supportSwaggePluginMap = pluginDOList.stream().filter(Objects::nonNull)
+ .collect(Collectors.toMap(PluginDO::getId, PluginDO::getName, (value1, value2) -> value1));
+
+ CommonPager<SelectorVO> commonPager = selectorService.listByPage(new SelectorQuery(Lists.newArrayList(supportSwaggePluginMap.keySet()), null, new PageParameter(1, Integer.MAX_VALUE)));
+ List<SelectorVO> clusterList = commonPager.getDataList();
if (CollectionUtils.isEmpty(clusterList)) {
LOG.info("getAllClusterLastUpdateInstanceList, Not loaded into available backend services.");
return Collections.EMPTY_LIST;
@@ -122,77 +146,68 @@ public class LoadServiceDocEntryImpl implements LoadServiceDocEntry {
}
private UpstreamInstance getClusterLastUpdateInstance(final SelectorVO selectorVO) {
- List<UpstreamInstance> allInstances = null;
- // Get service instance.
- String handle = selectorVO.getHandle();
- if (StringUtils.isNotEmpty(handle)) {
- allInstances = new ArrayList<>();
- try {
- List<CommonUpstream> upstreamList = this.convert(handle);
- for (CommonUpstream upstream : upstreamList) {
- String[] upstreamUrlArr = upstream.getUpstreamUrl().split(":");
- UpstreamInstance instance = new UpstreamInstance();
- instance.setContextPath(selectorVO.getName());
- instance.setIp(upstreamUrlArr[0]);
- instance.setPort(Integer.parseInt(upstreamUrlArr[1]));
- instance.setEnabled(selectorVO.getEnabled());
- instance.setHealthy(true);
- instance.setStartupTime(upstream.getTimestamp());
- allInstances.add(instance);
- }
- } catch (Exception e) {
- LOG.error("Error getting cluster instance list. serviceName={} error={}", selectorVO.getName(), e);
- return null;
- }
+ List<UpstreamInstance> allInstances = getInstances(selectorVO.getPluginId(), selectorVO.getHandle(), selectorVO.getName(), selectorVO.getEnabled());
+ if (CollectionUtils.isEmpty(allInstances)) {
+ return null;
}
-
return getClusterLastUpdateInstance(allInstances);
}
private UpstreamInstance getClusterLastUpdateInstance(final SelectorData selectorData) {
- if (!selectorData.getPluginId().equals("5")) {
+ if (!supportSwaggePluginMap.keySet().contains(selectorData.getPluginId())) {
LOG.info("getClusterLastUpdateInstance. pluginNae={} does not support pulling API documents.", selectorData.getPluginName());
return null;
}
+ List<UpstreamInstance> allInstances = getInstances(selectorData.getPluginId(), selectorData.getHandle(), selectorData.getName(), selectorData.getEnabled());
+ if (Objects.isNull(allInstances)) {
+ return null;
+ }
+ return getClusterLastUpdateInstance(allInstances);
+ }
+
+ private UpstreamInstance getClusterLastUpdateInstance(final List<UpstreamInstance> allInstances) {
+ if (CollectionUtils.isEmpty(allInstances)) {
+ return null;
+ }
+ return allInstances.stream()
+ .filter(UpstreamInstance::isHealthy)
+ .filter(Objects::nonNull)
+ .max(Comparator.comparing(UpstreamInstance::getStartupTime))
+ .orElse(null);
+ }
+
+ private List<UpstreamInstance> getInstances(final String pluginId, final String handle, final String contextPath,
+ final boolean enabled) {
List<UpstreamInstance> allInstances = null;
// Get service instance.
- String handle = selectorData.getHandle();
if (StringUtils.isNotEmpty(handle)) {
allInstances = new ArrayList<>();
try {
- List<CommonUpstream> upstreamList = this.convert(handle);
+ List<CommonUpstream> upstreamList = this.convert(pluginId, handle);
for (CommonUpstream upstream : upstreamList) {
- String[] upstreamUrlArr = upstream.getUpstreamUrl().split(":");
UpstreamInstance instance = new UpstreamInstance();
- instance.setContextPath(selectorData.getName());
+ instance.setContextPath(contextPath);
+ String[] upstreamUrlArr = upstream.getUpstreamUrl().split(":");
instance.setIp(upstreamUrlArr[0]);
- instance.setPort(Integer.parseInt(upstreamUrlArr[1]));
- instance.setEnabled(selectorData.getEnabled());
+ instance.setPort(upstreamUrlArr.length == 1 ? 80 : Integer.parseInt(upstreamUrlArr[1]));
+ instance.setEnabled(enabled);
instance.setHealthy(true);
instance.setStartupTime(upstream.getTimestamp());
allInstances.add(instance);
}
} catch (Exception e) {
- LOG.error("Error getting cluster instance list. serviceName={} error={}", selectorData.getName(), e);
+ LOG.error("Error getting cluster instance list. contextPath={} error={}", contextPath, e);
return null;
}
}
- return getClusterLastUpdateInstance(allInstances);
- }
-
- private UpstreamInstance getClusterLastUpdateInstance(final List<UpstreamInstance> allInstances) {
- if (CollectionUtils.isEmpty(allInstances)) {
- return null;
- }
- return allInstances.stream()
- .filter(UpstreamInstance::isHealthy)
- .filter(Objects::nonNull)
- .max(Comparator.comparing(UpstreamInstance::getStartupTime))
- .orElse(null);
+ return allInstances;
}
- private List<CommonUpstream> convert(final String handle) {
- return GsonUtils.getInstance().fromList(handle, CommonUpstream.class);
+ private List<CommonUpstream> convert(final String pluginId, final String handle) {
+ String pluginName = supportSwaggePluginMap.get(pluginId);
+ return converterFactor.newInstance(pluginName).convertUpstream(handle)
+ .stream().filter(upstream -> upstream.isStatus())
+ .collect(Collectors.toList());
}
}
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/SwaggerDocParser.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/SwaggerDocParser.java
index 238a53cbc..4685cf733 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/SwaggerDocParser.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/manager/impl/SwaggerDocParser.java
@@ -170,12 +170,11 @@ public class SwaggerDocParser implements DocParser {
}
protected String buildModuleName(final JsonObject docInfo, final JsonObject docRoot, final String basePath) {
- final String title = Optional.ofNullable(docRoot.getAsJsonObject("info")).map(jsonObject -> jsonObject.get("title").getAsString()).orElse(basePath);
JsonArray tags = docInfo.getAsJsonArray("tags");
if (Objects.nonNull(tags) && tags.size() > 0) {
return tags.get(0).getAsString();
}
- return title;
+ return Optional.ofNullable(docRoot.getAsJsonObject("info")).map(jsonObject -> jsonObject.get("title").getAsString()).orElse(basePath);
}
protected List<DocParameter> buildRequestParameterList(final JsonObject docInfo, final JsonObject docRoot) {
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
index b54e95ed3..be6cc842b 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
@@ -171,7 +171,7 @@ public class CommonUpstreamUtils {
return Optional.ofNullable(upstreamList)
.orElse(Collections.emptyList())
.stream()
- .map(upstream -> new CommonUpstream(upstream.getProtocol(), upstream.getUpstreamHost(), upstream.getUpstreamUrl(), upstream.isStatus()))
+ .map(upstream -> new CommonUpstream(upstream.getProtocol(), upstream.getUpstreamHost(), upstream.getUpstreamUrl(), upstream.isStatus(), upstream.getTimestamp()))
.collect(Collectors.toList());
}
diff --git a/shenyu-admin/src/main/resources/mappers/selector-sqlmap.xml b/shenyu-admin/src/main/resources/mappers/selector-sqlmap.xml
index 9801880b8..100d6f6e9 100644
--- a/shenyu-admin/src/main/resources/mappers/selector-sqlmap.xml
+++ b/shenyu-admin/src/main/resources/mappers/selector-sqlmap.xml
@@ -89,6 +89,12 @@
<if test="pluginId != null">
plugin_id = #{pluginId, jdbcType=VARCHAR}
</if>
+ <if test="pluginIds != null and pluginIds.size > 0">
+ AND plugin_id IN
+ <foreach item="pluginId" collection="pluginIds" open="(" separator="," close=")">
+ #{pluginId, jdbcType=VARCHAR}
+ </foreach>
+ </if>
<if test="name != null and name != ''">
<bind name="nameLike" value="('%' + name + '%')"/>
AND name LIKE #{nameLike, jdbcType=VARCHAR}
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstream.java b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstream.java
index e08822782..17bf60172 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstream.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstream.java
@@ -23,7 +23,7 @@ import java.util.Objects;
* this is common upstream.
*/
public class CommonUpstream {
-
+
/**
* this is http protocol.
*/
@@ -38,24 +38,24 @@ public class CommonUpstream {
* url.
*/
private String upstreamUrl;
-
+
/**
* false close/ true open.
*/
private boolean status = true;
-
+
/**
* startup time.
*/
private long timestamp;
-
+
/**
* Instantiates a new Common upstream.
*/
public CommonUpstream() {
-
+
}
-
+
/**
* Instantiates a new Common upstream.
*
@@ -63,14 +63,16 @@ public class CommonUpstream {
* @param upstreamHost the upstream host
* @param upstreamUrl the upstream url
* @param status the upstream status
+ * @param timestamp the upstream timestamp
*/
- public CommonUpstream(final String protocol, final String upstreamHost, final String upstreamUrl, final boolean status) {
+ public CommonUpstream(final String protocol, final String upstreamHost, final String upstreamUrl, final boolean status, final long timestamp) {
this.protocol = protocol;
this.upstreamHost = upstreamHost;
this.upstreamUrl = upstreamUrl;
this.status = status;
+ this.timestamp = timestamp;
}
-
+
/**
* get upstreamHost.
*
@@ -79,7 +81,7 @@ public class CommonUpstream {
public String getUpstreamHost() {
return upstreamHost;
}
-
+
/**
* set upstreamHost.
*
@@ -88,7 +90,7 @@ public class CommonUpstream {
public void setUpstreamHost(final String upstreamHost) {
this.upstreamHost = upstreamHost;
}
-
+
/**
* get protocol.
*
@@ -97,7 +99,7 @@ public class CommonUpstream {
public String getProtocol() {
return protocol;
}
-
+
/**
* set protocol.
*
@@ -106,7 +108,7 @@ public class CommonUpstream {
public void setProtocol(final String protocol) {
this.protocol = protocol;
}
-
+
/**
* get upstreamUrl.
*
@@ -115,7 +117,7 @@ public class CommonUpstream {
public String getUpstreamUrl() {
return upstreamUrl;
}
-
+
/**
* set upstreamUrl.
*
@@ -124,7 +126,7 @@ public class CommonUpstream {
public void setUpstreamUrl(final String upstreamUrl) {
this.upstreamUrl = upstreamUrl;
}
-
+
/**
* get status.
*
@@ -133,7 +135,7 @@ public class CommonUpstream {
public boolean isStatus() {
return status;
}
-
+
/**
* set status.
*
@@ -142,7 +144,7 @@ public class CommonUpstream {
public void setStatus(final boolean status) {
this.status = status;
}
-
+
/**
* get timestamp.
*
@@ -151,7 +153,7 @@ public class CommonUpstream {
public long getTimestamp() {
return timestamp;
}
-
+
/**
* set timestamp.
*
@@ -160,7 +162,7 @@ public class CommonUpstream {
public void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
-
+
/**
* Default status boolean.
*
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
index e104148d4..572aee40f 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
@@ -130,6 +130,14 @@ public enum RpcTypeEnum {
return Arrays.asList(RpcTypeEnum.HTTP, RpcTypeEnum.DUBBO, RpcTypeEnum.GRPC, RpcTypeEnum.SPRING_CLOUD, RpcTypeEnum.SOFA, RpcTypeEnum.TARS, RpcTypeEnum.MOTAN);
}
+ /**
+ * acquire operator support swagger type.
+ * @return operator support.
+ */
+ public static List<RpcTypeEnum> acquireSupportSwaggers() {
+ return Arrays.asList(RpcTypeEnum.HTTP, RpcTypeEnum.SPRING_CLOUD);
+ }
+
/**
* acquireByName.
*
@@ -138,7 +146,7 @@ public enum RpcTypeEnum {
*/
public static RpcTypeEnum acquireByName(final String name) {
return Arrays.stream(RpcTypeEnum.values())
- .filter(e -> e.support && e.name.equals(name)).findFirst()
- .orElseThrow(() -> new ShenyuException(String.format(" this rpc type can not support %s", name)));
+ .filter(e -> e.support && e.name.equals(name)).findFirst()
+ .orElseThrow(() -> new ShenyuException(String.format(" this rpc type can not support %s", name)));
}
}
diff --git a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstreamTest.java b/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstreamTest.java
index c928fb8c3..83c13fd52 100644
--- a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstreamTest.java
+++ b/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/selector/CommonUpstreamTest.java
@@ -47,8 +47,8 @@ public class CommonUpstreamTest {
@Test
public void testEqualsAndHashCode() {
- CommonUpstream upstream1 = new CommonUpstream("protocol", "host", "url", true);
- CommonUpstream upstream2 = new CommonUpstream("protocol", "host", "url", true);
+ CommonUpstream upstream1 = new CommonUpstream("protocol", "host", "url", true, System.currentTimeMillis());
+ CommonUpstream upstream2 = new CommonUpstream("protocol", "host", "url", true, System.currentTimeMillis());
assertThat(ImmutableSet.of(upstream1, upstream2), hasSize(1));
}