From 48d64a869aae897930588ee60028d1e0cf8a4c9f Mon Sep 17 00:00:00 2001 From: ztzh_xieyun Date: Mon, 3 Jun 2024 15:41:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=86=97=E4=BD=99=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=20mock=E4=BB=A3=E7=A0=81=E8=BF=98=E5=8E=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sf/vertx/constans/SACConstants.java | 2 - .../com/sf/vertx/handle/AppConfigHandler.java | 18 +- .../handle/BodyPostAnalysisHandlerImpl.java | 12 +- .../handle/BodyPostCheckHandlerImpl.java | 5 +- .../java/com/sf/vertx/security/RSAUtil.java | 7 +- .../java/com/sf/vertx/utils/AppUtils.java | 303 ++++++++---------- 6 files changed, 163 insertions(+), 184 deletions(-) diff --git a/sf-vertx/src/main/java/com/sf/vertx/constans/SACConstants.java b/sf-vertx/src/main/java/com/sf/vertx/constans/SACConstants.java index 237e8cb..8f31a3d 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/constans/SACConstants.java +++ b/sf-vertx/src/main/java/com/sf/vertx/constans/SACConstants.java @@ -20,6 +20,4 @@ public class SACConstants { * 业务码 key */ public static final String GATEWAY_SERVICE_CODE = "serviceCode"; - - public static final String GATEWAY_BODY_CODE = "httpBody"; } diff --git a/sf-vertx/src/main/java/com/sf/vertx/handle/AppConfigHandler.java b/sf-vertx/src/main/java/com/sf/vertx/handle/AppConfigHandler.java index 242174d..c79b90b 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/handle/AppConfigHandler.java +++ b/sf-vertx/src/main/java/com/sf/vertx/handle/AppConfigHandler.java @@ -1,5 +1,7 @@ package com.sf.vertx.handle; +import static com.sf.vertx.constans.SACConstants.CACHE_KEY_CONNECTOR; + import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -34,6 +36,7 @@ import com.sf.vertx.pojo.ClusterEventMsg; import com.sf.vertx.pojo.SacCircuitBreaker; import com.sf.vertx.pojo.SacCurrentLimiting; import com.sf.vertx.security.MainSecurity; +import com.sf.vertx.utils.AppUtils; import com.sf.vertx.utils.ProxyTool; import cn.hutool.core.collection.ConcurrentHashSet; @@ -45,6 +48,7 @@ import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.net.JksOptions; @@ -276,7 +280,7 @@ public class AppConfigHandler { String keyCircuitBreaker = key + ":" + "CIRCUIT_BREAKER"; SacCircuitBreaker sacCircuitBreaker = APICODE_CONFIG_CIRCUIT_BREAKER_MAP.get(key); if (sacCircuitBreaker != null) { - if(sacCircuitBreaker.getCircuitBreaker() != null) { + if (sacCircuitBreaker.getCircuitBreaker() != null) { sacCircuitBreaker.getCircuitBreaker().close(); } APICODE_CONFIG_CIRCUIT_BREAKER_MAP.remove(keyCircuitBreaker); @@ -551,6 +555,16 @@ public class AppConfigHandler { // // 会跳转到 RestfulFailureHandlerImpl // throw new HttpException(10003); // } + + // apiconfig uri rewrite + String appCode = context.request().headers().get(getAppCodeHeaderKey()); + String apiCode = context.request().headers().get(getApiCodeHeaderKey()); + String key = appCode + CACHE_KEY_CONNECTOR + apiCode; + if (isServiceTypeSac(key)) { + String uri = APICODE_CONFIG_MAP.get(key).getUri(); + String method = APICODE_CONFIG_MAP.get(key).getMethod(); + context.request().setURI(uri).setMethod(HttpMethod.valueOf(method)); + } return context.sendRequest(); } @@ -604,7 +618,7 @@ public class AppConfigHandler { } // TODO - // blockedThreadCheckInterval = 1000000L; + blockedThreadCheckInterval = 1000000L; if (blockedThreadCheckInterval != -1) { vertxOptions.setBlockedThreadCheckInterval(blockedThreadCheckInterval); // 不打印Thread blocked 阻塞日志 } diff --git a/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostAnalysisHandlerImpl.java b/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostAnalysisHandlerImpl.java index 07bfd8a..02f9fd7 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostAnalysisHandlerImpl.java +++ b/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostAnalysisHandlerImpl.java @@ -1,11 +1,7 @@ package com.sf.vertx.handle; -import static com.sf.vertx.constans.SACConstants.GATEWAY_BODY_CODE; - -import com.sf.vertx.api.pojo.AppConfig; import com.sf.vertx.enums.GatewayError; import com.sf.vertx.exception.ServiceException; -import com.sf.vertx.utils.AppUtils; import io.vertx.ext.web.RoutingContext; import lombok.extern.slf4j.Slf4j; @@ -16,13 +12,7 @@ public class BodyPostAnalysisHandlerImpl implements BodyPostAnalysisHandler { @Override public void handle(RoutingContext ctx) { try { - // body加解密 - AppConfig appConfig = AppUtils.getAppConfigFromRoutingContext(ctx); - if (AppUtils.isEnableDataSecurity(appConfig)) { - // 解密 - String bodyStr = AppConfigHandler.bodyDecrypt(ctx.body().asString(), appConfig.getAppCode()); - ctx.put(GATEWAY_BODY_CODE, bodyStr); - } + } catch (Exception e) { log.error("BodyPostAnalysisHandlerImpl:",e); ctx.fail(new ServiceException(GatewayError.DEFAULT_SERVICE_ERROR)); diff --git a/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostCheckHandlerImpl.java b/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostCheckHandlerImpl.java index 2dddef8..d6c3208 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostCheckHandlerImpl.java +++ b/sf-vertx/src/main/java/com/sf/vertx/handle/BodyPostCheckHandlerImpl.java @@ -1,12 +1,12 @@ package com.sf.vertx.handle; -import com.sf.vertx.api.pojo.ApiConfig; import com.sf.vertx.api.pojo.MockResponse; import com.sf.vertx.enums.GatewayError; import com.sf.vertx.exception.MockException; import com.sf.vertx.exception.ServiceException; import com.sf.vertx.utils.AppUtils; + import io.vertx.ext.web.RoutingContext; import lombok.extern.slf4j.Slf4j; @@ -16,9 +16,8 @@ public class BodyPostCheckHandlerImpl implements BodyPostCheckHandler { @Override public void handle(RoutingContext ctx) { try { - ApiConfig apiConfig = AppUtils.getApiConfigFromRoutingContext(ctx); // mock - MockResponse mockResponse = AppUtils.mock(ctx, apiConfig); + MockResponse mockResponse = AppUtils.mock(ctx); if (mockResponse != null) { ctx.fail(new MockException(mockResponse.getHttpStatus(), mockResponse.getMockResponse())); return; diff --git a/sf-vertx/src/main/java/com/sf/vertx/security/RSAUtil.java b/sf-vertx/src/main/java/com/sf/vertx/security/RSAUtil.java index 118c2f2..360e2f0 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/security/RSAUtil.java +++ b/sf-vertx/src/main/java/com/sf/vertx/security/RSAUtil.java @@ -131,10 +131,7 @@ public class RSAUtil { log.info("publicKey = " + publicKey); log.info("privateKey = " + privateKey); String originValue = "{\n" - + " \"data\": {\n" - + " \"a\": 1,\n" - + " \"b\": \"dd\"\n" - + " },\n" + + " \"data\": 1,\n" + " \"divideHttpUrl\": {\n" + " \"company\": {\n" + " \"aesKey\": \"dadddsdfadfadsfa33323223\"\n" @@ -146,7 +143,7 @@ public class RSAUtil { String encrypt = encrypt(originValue, publicKey); log.info("加密后:" + encrypt); - encrypt = "Rk3UOW4UG+a/MmnddEvv03mdcv5B2+Rhu7A7mRuu9MgBTBTYrX8RVRgLwXkQq5Wuo8O33/b9n6qGhLX/GDWQ4unuO0IR4wkYwbL5EOXkOmozxScfSyiypu1zD+hSw+B4uMO5LZql+jRJeCtEjph9RZK5EFD186qktUWP1QcKHzGGIM7Ex1YZogWdn6g2I3iyYTStJrofWfUtMQzEj2UUbaAJ/KuCKSXBAJ1oBjmfT856R9TZrHxVXLf5+jNgoUQrSit6ca/hZ8HSZ+rRLf9r+pgAsU0zYLmifRVDc+F819I3XIdi/FNNm9fwNuX7ZpXyKAGP93j8V35uQ6p1ZMw+xQ=="; + encrypt = "Rh8k/Aj5vnmlsNhc9QxO8UoCxz9r6vrJASKbZMC61cuY4QVp8ECaNI70z7aEK3wugKYp9FPCgYXtfn/erhkWOD+np9mTZ+XU4DT6/Qa7atv92vTt9TYQLmY2TLXvPbdH5qT7LrI4dKZAlBZSV36krHi0MSkX9che90TAyy0pGqpcy1dz9nJ8XAiRsfgCy1rYQp7Tt8FwaS2q367ukmK8rTD/pHngEXXoRWlkzclFfPkwQuT43YBaRgnHAAIGgWcHGILiTXdbe1y1mUxVZavrvzPPbOZtwjTBsa2uV2YCo9K4HNTvFLA2SHhMp0YAcxy1bU7FjctBli9UW32R1d3H1A=="; String decrypt = decrypt(encrypt, privateKey); log.info("解密后:" + decrypt); } diff --git a/sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java b/sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java index ba0de10..c1cf137 100644 --- a/sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java +++ b/sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java @@ -1,10 +1,9 @@ package com.sf.vertx.utils; -import static com.sf.vertx.constans.SACConstants.CACHE_KEY_CONNECTOR; import static com.sf.vertx.constans.SACConstants.API_CONFIG; import static com.sf.vertx.constans.SACConstants.API_SERVICE_TYPE; import static com.sf.vertx.constans.SACConstants.APP_CONFIG; -import static com.sf.vertx.constans.SACConstants.GATEWAY_BODY_CODE; +import static com.sf.vertx.constans.SACConstants.CACHE_KEY_CONNECTOR; import java.math.BigDecimal; import java.util.List; @@ -20,13 +19,12 @@ import com.sf.vertx.enums.GatewayError; import com.sf.vertx.enums.GatewayServiceType; import com.sf.vertx.enums.MatchType; import com.sf.vertx.enums.RequestMethod; -import com.sf.vertx.exception.ServiceException; import com.sf.vertx.handle.AppConfigHandler; import com.sf.vertx.pojo.SacCircuitBreaker; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.NumberUtil; -import io.vertx.circuitbreaker.CircuitBreaker; +import io.vertx.core.http.HttpServerRequest; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; import lombok.experimental.UtilityClass; @@ -41,7 +39,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j @UtilityClass public class AppUtils { - + /** * 将AppConfig设置到上下文中 配合getAppConfigFromRoutingContext(RoutingContext rc)使用 * @@ -100,138 +98,121 @@ public class AppUtils { return appConfig != null && appConfig.getDataSecurity() != null; } - public static MockResponse mock(RoutingContext rc, ApiConfig apiConfig) { - String apiServiceType = rc.get(API_SERVICE_TYPE); - if (AppUtils.isEnableMockApi(apiConfig)) { - // 如果是sac服务,query和body参数都从body中取 - Integer httpStatus = apiConfig.getMockDefaultHttpStatus(); - String mockResponse = apiConfig.getMockDefaultResponse(); - List mockExpectations = apiConfig.getMockExpectations(); - if (mockExpectations != null && !mockExpectations.isEmpty()) { - for (MockExpectation mockExpectation : mockExpectations) { - // 匹配条件需要全部匹配成功 - boolean matchSuccess = true; - for (MockMatchCondition matchCondition : mockExpectation.getMatchConditions()) { - if (!matchSuccess) { - break; - } - MatchType matchType = MatchType.getByCode(matchCondition.getMatchType()); - if (matchType == null) { - matchSuccess = false; - break; - } - String parameterPosition = matchCondition.getParameterPosition(); - String parameterKey = matchCondition.getParameterKey(); - List parameterValue = matchCondition.getParameterValue(); - String requestParameterValue = getRequestParameterValue(rc, - AppUtils.isSACServiceType(apiServiceType), parameterPosition, parameterKey); - if (!MatchType.IS_NULL.equals(matchType) && !MatchType.NOT_NULL.equals(matchType)) { - // 需要值而没有设置值,直接匹配失败 - if (CollectionUtil.isEmpty(parameterValue) || requestParameterValue == null) { - matchSuccess = false; - break; - } - } + public static MockResponse mock(RoutingContext rc) { + AppConfig appConfig = getAppConfigFromRoutingContext(rc); + ApiConfig apiConfig = getApiConfigFromRoutingContext(rc); + String apiServiceType = rc.get(API_SERVICE_TYPE); + if (AppUtils.isEnableMockApi(apiConfig)) { + // 如果是sac服务,query和body参数都从body中取 + Integer httpStatus = apiConfig.getMockDefaultHttpStatus(); + String mockResponse = apiConfig.getMockDefaultResponse(); + List mockExpectations = apiConfig.getMockExpectations(); + if (mockExpectations != null && !mockExpectations.isEmpty()) { + String bodyStr = rc.body().asString(); + if (AppUtils.isEnableDataSecurity(appConfig)) { + bodyStr = AppConfigHandler.bodyDecrypt(bodyStr, appConfig.getAppCode()); + } + JsonObject jsonBody = new JsonObject(bodyStr); + for (MockExpectation mockExpectation : mockExpectations) { + // 匹配条件需要全部匹配成功 + boolean matchSuccess = true; + for (MockMatchCondition matchCondition : mockExpectation.getMatchConditions()) { + if (!matchSuccess) { + break; + } + MatchType matchType = MatchType.getByCode(matchCondition.getMatchType()); + if (matchType == null) { + matchSuccess = false; + break; + } + String parameterPosition = matchCondition.getParameterPosition(); + String parameterKey = matchCondition.getParameterKey(); + List parameterValue = matchCondition.getParameterValue(); + String requestParameterValue = getRequestParameterValue(AppUtils.isSACServiceType(apiServiceType), parameterPosition, parameterKey, rc.request(), jsonBody); + if (!MatchType.IS_NULL.equals(matchType) && !MatchType.NOT_NULL.equals(matchType)) { + // 需要值而没有设置值,直接匹配失败 + if (CollectionUtil.isEmpty(parameterValue) || requestParameterValue == null) { + matchSuccess = false; + break; + } + } - switch (matchType) { - case EQ: - matchSuccess = parameterValue.get(0).equals(requestParameterValue); - break; - case NOT_EQ: - matchSuccess = !parameterValue.get(0).equals(requestParameterValue); - break; - case GT: - if (NumberUtil.isNumber(requestParameterValue) - && NumberUtil.isNumber(parameterValue.get(0))) { - matchSuccess = new BigDecimal(requestParameterValue) - .compareTo(new BigDecimal(parameterValue.get(0))) > 0; - } else { - matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) > 0; - } - break; - case GE: - if (NumberUtil.isNumber(requestParameterValue) - && NumberUtil.isNumber(parameterValue.get(0))) { - matchSuccess = new BigDecimal(requestParameterValue) - .compareTo(new BigDecimal(parameterValue.get(0))) >= 0; - } else { - matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) >= 0; - } - break; - case LT: - if (NumberUtil.isNumber(requestParameterValue) - && NumberUtil.isNumber(parameterValue.get(0))) { - matchSuccess = new BigDecimal(requestParameterValue) - .compareTo(new BigDecimal(parameterValue.get(0))) < 0; - } else { - matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) < 0; - } - break; - case LE: - if (NumberUtil.isNumber(requestParameterValue) - && NumberUtil.isNumber(parameterValue.get(0))) { - matchSuccess = new BigDecimal(requestParameterValue) - .compareTo(new BigDecimal(parameterValue.get(0))) <= 0; - } else { - matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) <= 0; - } - break; - case IN: - matchSuccess = parameterValue.contains(requestParameterValue); - break; - case NOT_IN: - matchSuccess = !parameterValue.contains(requestParameterValue); - break; - case IS_NULL: - matchSuccess = requestParameterValue == null; - break; - case NOT_NULL: - matchSuccess = requestParameterValue != null; - break; - default: - break; - } + switch (matchType) { + case EQ: + matchSuccess = parameterValue.get(0).equals(requestParameterValue); + break; + case NOT_EQ: + matchSuccess = !parameterValue.get(0).equals(requestParameterValue); + break; + case GT: + if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) { + matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) > 0; + } else { + matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) > 0; + } + break; + case GE: + if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) { + matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) >= 0; + } else { + matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) >= 0; + } + break; + case LT: + if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) { + matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) < 0; + } else { + matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) < 0; + } + break; + case LE: + if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) { + matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) <= 0; + } else { + matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) <= 0; + } + break; + case IN: + matchSuccess = parameterValue.contains(requestParameterValue); + break; + case NOT_IN: + matchSuccess = !parameterValue.contains(requestParameterValue); + break; + case IS_NULL: + matchSuccess = requestParameterValue == null; + break; + case NOT_NULL: + matchSuccess = requestParameterValue != null; + break; + default: + break; + } - } - if (matchSuccess) { - httpStatus = mockExpectation.getHttpStatus(); - mockResponse = mockExpectation.getMockResponse(); - break; - } - } - } - return new MockResponse(httpStatus, mockResponse); - } - return null; - } - - /*** - * BodyPostAnalysisHandler之后调用 - * @param rc - * @param parameterKey - * @return - */ - private static String mockBodyVal(RoutingContext rc, String parameterKey) { - String bodyStr = rc.get(GATEWAY_BODY_CODE); - if(StringUtils.isBlank(bodyStr)) { - throw new ServiceException(GatewayError.DEFAULT_SERVICE_ERROR); - } - JsonObject jsonBody = new JsonObject(bodyStr); - return jsonBody.getString(parameterKey); - } - - private static String getRequestParameterValue(RoutingContext rc, Boolean isServiceTypeSac, - String parameterPosition, String parameterKey) { + } + if (matchSuccess) { + httpStatus = mockExpectation.getHttpStatus(); + mockResponse = mockExpectation.getMockResponse(); + break; + } + } + } + return new MockResponse(httpStatus, mockResponse); + } + return null; + } + + private static String getRequestParameterValue(Boolean isServiceTypeSac, String parameterPosition, + String parameterKey, HttpServerRequest request, JsonObject jsonBody) { switch (parameterPosition) { case "query": if (isServiceTypeSac) { - return mockBodyVal(rc, parameterKey); + return jsonBody.getString(parameterKey); } - return rc.request().getParam(parameterKey); + return request.getParam(parameterKey); case "header": - return rc.request().getHeader(parameterKey); + return request.getHeader(parameterKey); case "body": - return mockBodyVal(rc, parameterKey); + return jsonBody.getString(parameterKey); default: break; } @@ -254,36 +235,36 @@ public class AppUtils { } return getResponseJsonByGatewayError(GatewayError.DEFAULT_SERVICE_ERROR); } - - public static boolean isAnalysisBody(AppConfig appConfig, ApiConfig apiConfig,String apiServiceType, String contentType) { - // 不是Mock(是mock模式的话,存在body就解析。) - if (AppUtils.isEnableMockApi(apiConfig)) { - return true; - } - // 文件上传不走加解密 - if (StringUtils.startsWith(contentType, "multipart")) { - return false; - } - - // uri不能模糊匹配 - if (StringUtils.equals(apiConfig.getUri(), "*")) { - return false; - } - - // SAC模式,实际API请求方式GET,DELETE,HEAD请求需要解析body,可能需要二次处理。(SAC模式请求方式参数统一使用body传递) - // SAC模式,如果是POST或者PUT,并且没有设置数据加密则跳过 - if (AppUtils.isSACServiceType(apiServiceType)) { - RequestMethod requestMethod = RequestMethod.getByCode(apiConfig.getMethod()); - if (RequestMethod.GET.equals(requestMethod) - || RequestMethod.DELETE.equals(requestMethod) - || RequestMethod.HEAD.equals(requestMethod)) { - return true; - } - } - - String keyCircuitBreaker = appConfig.getAppCode() + CACHE_KEY_CONNECTOR + apiConfig.getApiCode(); - SacCircuitBreaker sacCircuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker); - boolean isDataSecurity = AppUtils.isEnableDataSecurity(appConfig); - return (isDataSecurity || sacCircuitBreaker != null); - } + + public static boolean isAnalysisBody(AppConfig appConfig, ApiConfig apiConfig, String apiServiceType, + String contentType) { + // mock模式,存在body就解析。 + if (AppUtils.isEnableMockApi(apiConfig)) { + return true; + } + // 文件上传不走加解密 + if (StringUtils.startsWith(contentType, "multipart")) { + return false; + } + + // uri不能模糊匹配 + if (StringUtils.equals(apiConfig.getUri(), "*")) { + return false; + } + + // SAC模式,实际API请求方式GET,DELETE,HEAD请求需要解析body,可能需要二次处理。(SAC模式请求方式参数统一使用body传递) + // SAC模式,如果是POST或者PUT,并且没有设置数据加密则跳过 + if (AppUtils.isSACServiceType(apiServiceType)) { + RequestMethod requestMethod = RequestMethod.getByCode(apiConfig.getMethod()); + if (RequestMethod.GET.equals(requestMethod) || RequestMethod.DELETE.equals(requestMethod) + || RequestMethod.HEAD.equals(requestMethod)) { + return true; + } + } + + String keyCircuitBreaker = appConfig.getAppCode() + CACHE_KEY_CONNECTOR + apiConfig.getApiCode(); + SacCircuitBreaker sacCircuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker); + boolean isDataSecurity = AppUtils.isEnableDataSecurity(appConfig); + return (isDataSecurity || sacCircuitBreaker != null); + } }