网关Mock支持

This commit is contained in:
akun 2024-05-21 14:17:59 +08:00
parent c1666350f3
commit c9c0575014
10 changed files with 314 additions and 76 deletions

View File

@ -4,6 +4,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.sf.common.utils.*; import com.sf.common.utils.*;
import com.sf.service.gateway.domain.GatewayInterfaceInfo; import com.sf.service.gateway.domain.GatewayInterfaceInfo;
@ -228,6 +229,13 @@ public class GatewayInterfaceInfoServiceImpl implements IGatewayInterfaceInfoSer
case IS_NULL: case IS_NULL:
case NOT_NULL: case NOT_NULL:
break; break;
case LT:
case LE:
case GT:
case GE:
Assert.notEmpty(condition.getParameterValue(),"请输入参数值");
Assert.isTrue(NumberUtil.isNumber(condition.getParameterValue().get(0)),"大于、大于或等于、小于、小于或等于类型,参数值只能是数字");
break;
default: default:
Assert.notEmpty(condition.getParameterValue(),"请输入参数值"); Assert.notEmpty(condition.getParameterValue(),"请输入参数值");
break; break;

View File

@ -12,7 +12,7 @@ import com.sf.service.gateway.domain.GatewayServer;
import com.sf.service.gateway.enums.GatewayDataStatus; import com.sf.service.gateway.enums.GatewayDataStatus;
import com.sf.service.gateway.enums.GatewayServiceModel; import com.sf.service.gateway.enums.GatewayServiceModel;
import com.sf.service.gateway.enums.GatewayServiceType; import com.sf.service.gateway.enums.GatewayServiceType;
import com.sf.service.gateway.enums.RequestMethod; import com.sf.vertx.enums.RequestMethod;
import com.sf.service.gateway.mapper.GatewayServerMapper; import com.sf.service.gateway.mapper.GatewayServerMapper;
import com.sf.service.gateway.service.IGatewayInterfaceInfoService; import com.sf.service.gateway.service.IGatewayInterfaceInfoService;
import com.sf.service.gateway.service.IGatewayServerService; import com.sf.service.gateway.service.IGatewayServerService;

View File

@ -0,0 +1,27 @@
package com.sf.vertx.api.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 网关服务-接口Mock
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MockResponse {
/**
* http状态码
*/
private Integer httpStatus;
/**
* Mock响应JSON字符串
*/
private String mockResponse;
}

View File

@ -1,4 +1,4 @@
package com.sf.service.gateway.enums; package com.sf.vertx.enums;
/** /**
* 支持的请求方法 * 支持的请求方法
@ -35,7 +35,7 @@ public enum RequestMethod
public static RequestMethod getByCode(String code){ public static RequestMethod getByCode(String code){
for (RequestMethod value : RequestMethod.values()) { for (RequestMethod value : RequestMethod.values()) {
if (value.code.equals(code)){ if (value.code.equalsIgnoreCase(code)){
return value; return value;
} }
} }

View File

@ -0,0 +1,19 @@
package com.sf.vertx.handle;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
/***
* 接口mock处理
*
* @author zk
*
*/
@VertxGen
public interface ApiMockHandler extends Handler<RoutingContext> {
static ApiMockHandler create() {
return new ApiMockHandlerImpl();
}
}

View File

@ -0,0 +1,31 @@
package com.sf.vertx.handle;
import com.sf.vertx.api.pojo.AppConfig;
import com.sf.vertx.api.pojo.MockResponse;
import com.sf.vertx.constans.SacErrorCode;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.HttpException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@Slf4j
public class ApiMockHandlerImpl implements ApiMockHandler {
@Override
public void handle(RoutingContext rc) {
try {
String cacheKey = AppConfigHandler.getApiCodeConfigCacheKey(rc);
// mock
MockResponse mockResponse = AppConfigHandler.mock(cacheKey,rc);
if (mockResponse != null) {
rc.fail(new MockException(mockResponse.getHttpStatus(), mockResponse.getMockResponse()));
return;
}
} catch (Exception e) {
e.printStackTrace();
rc.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE));
return;
}
rc.next();
}
}

View File

@ -1,5 +1,6 @@
package com.sf.vertx.handle; package com.sf.vertx.handle;
import java.math.BigDecimal;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -7,6 +8,18 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.sf.vertx.api.pojo.*;
import com.sf.vertx.enums.MatchType;
import com.sf.vertx.enums.RequestMethod;
import com.sf.vertx.security.MainSecurity;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.*;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RequestBody;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.HttpException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@ -17,13 +30,6 @@ import com.hazelcast.config.Config;
import com.hazelcast.config.JoinConfig; import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.NetworkConfig; import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.TcpIpConfig; import com.hazelcast.config.TcpIpConfig;
import com.sf.vertx.api.pojo.ApiConfig;
import com.sf.vertx.api.pojo.AppConfig;
import com.sf.vertx.api.pojo.Node;
import com.sf.vertx.api.pojo.RouteContent;
import com.sf.vertx.api.pojo.SacService;
import com.sf.vertx.api.pojo.Strategy;
import com.sf.vertx.api.pojo.VertxConfig;
import com.sf.vertx.arithmetic.roundRobin.SacLoadBalancing; import com.sf.vertx.arithmetic.roundRobin.SacLoadBalancing;
import com.sf.vertx.constans.RedisKeyConfig; import com.sf.vertx.constans.RedisKeyConfig;
import com.sf.vertx.init.SacVertxConfig; import com.sf.vertx.init.SacVertxConfig;
@ -39,10 +45,6 @@ import io.vertx.circuitbreaker.CircuitBreakerOptions;
import io.vertx.core.Future; import io.vertx.core.Future;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions; 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; import io.vertx.core.net.JksOptions;
import io.vertx.core.spi.cluster.ClusterManager; import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.ext.web.Route; import io.vertx.ext.web.Route;
@ -57,7 +59,7 @@ import lombok.extern.slf4j.Slf4j;
/*** /***
* vertx配置维护 * vertx配置维护
* *
* @author xy * @author xy
* *
*/ */
@ -82,7 +84,7 @@ public class AppConfigHandler {
private static ConcurrentHashMap<String, SacCurrentLimiting> APICODE_CONFIG_CURRENT_LIMITING_MAP = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, SacCurrentLimiting> APICODE_CONFIG_CURRENT_LIMITING_MAP = new ConcurrentHashMap<>();
// 服务类型, apiCode限流配置 appCode:apiCode - 服务类型SAC=SAC规范服务OPEN=开放服务 // 服务类型, apiCode限流配置 appCode:apiCode - 服务类型SAC=SAC规范服务OPEN=开放服务
private static ConcurrentHashMap<String, String> APICODE_CONFIG_SERVICE_TYPE_MAP = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, String> APICODE_CONFIG_SERVICE_TYPE_MAP = new ConcurrentHashMap<>();
// 负载均衡路由类型 appCode:apiCode - routerType // 负载均衡路由类型 appCode:apiCode - routerType
// 执行流程 routerType= <br/> // 执行流程 routerType= <br/>
// 1serviceNodel="NORMAL", serviceNodel="ROUTE" and RouteType = "WEIGHT_ROUTE" // 1serviceNodel="NORMAL", serviceNodel="ROUTE" and RouteType = "WEIGHT_ROUTE"
@ -98,14 +100,14 @@ public class AppConfigHandler {
// apicode uri = * - appConfig // apicode uri = * - appConfig
private static ConcurrentHashMap<String, AppConfig> APICODE_APPCONFIG_MAP = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, AppConfig> APICODE_APPCONFIG_MAP = new ConcurrentHashMap<>();
// 禁用appCode // 禁用appCode
private static ConcurrentHashSet<String> DISABLED_APPCODE = new ConcurrentHashSet<String>(); private static ConcurrentHashSet<String> DISABLED_APPCODE = new ConcurrentHashSet<String>();
public static AppConfig getAppConfigByDomain(String domain) { public static AppConfig getAppConfigByDomain(String domain) {
return APICODE_APPCONFIG_MAP.get(domain); return APICODE_APPCONFIG_MAP.get(domain);
} }
public static Integer routerType(String key) { public static Integer routerType(String key) {
return APICODE_CONFIG_ROUTERTYPE_MAP.get(key) != null ? APICODE_CONFIG_ROUTERTYPE_MAP.get(key) : 1; return APICODE_CONFIG_ROUTERTYPE_MAP.get(key) != null ? APICODE_CONFIG_ROUTERTYPE_MAP.get(key) : 1;
} }
@ -131,7 +133,7 @@ public class AppConfigHandler {
public static String rpcUri() { public static String rpcUri() {
return sacVertxConfig.getRpcUri(); return sacVertxConfig.getRpcUri();
} }
public static void removeDisabledAppcode(String appCode) { public static void removeDisabledAppcode(String appCode) {
DISABLED_APPCODE.remove(appCode); DISABLED_APPCODE.remove(appCode);
} }
@ -173,25 +175,38 @@ public class AppConfigHandler {
/*** /***
* 是否解析, 走独立请求 * 是否解析, 走独立请求
* *
* @return * @return
*/ */
public static boolean isAnalysisBody(String appCode, String apiCode, String contentType) { public static boolean isAnalysisBody(String appCode, String apiCode, String contentType) {
String keyCircuitBreaker = appCode + ":" + apiCode + ":" + "CIRCUIT_BREAKER"; String apiCodeCacheKey = appCode + ":" + apiCode;
CircuitBreaker circuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker); // Mock解析body
boolean isDataSecurity = AppConfigHandler.isDataSecurity(appCode); if (APICODE_CONFIG_MAP.get(apiCodeCacheKey) != null && APICODE_CONFIG_MAP.get(apiCodeCacheKey).getMockDefaultHttpStatus() != null){
return true;
}
ApiConfig apicodeConfig = AppConfigHandler.getApicodeConfig(apiCodeCacheKey);
// GET,DELETE,HEAD请求不解析body
RequestMethod requestMethod = RequestMethod.getByCode(apicodeConfig.getMethod());
if (requestMethod == null || RequestMethod.GET.equals(requestMethod)
|| RequestMethod.DELETE.equals(requestMethod)
|| RequestMethod.HEAD.equals(requestMethod)){
return false;
}
// 模糊匹配不解析body // 模糊匹配不解析body
String uri = AppConfigHandler.getApicodeConfig(appCode + ":" + apiCode).getUri(); String uri = apicodeConfig.getUri();
if (StringUtils.equals(uri, "*")) { if (StringUtils.equals(uri, "*")) {
return false; return false;
} }
String keyCircuitBreaker = apiCodeCacheKey + ":" + "CIRCUIT_BREAKER";
CircuitBreaker circuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker);
boolean isDataSecurity = AppConfigHandler.isDataSecurity(appCode);
// 文件上传不走加解密 // 文件上传不走加解密
return (isDataSecurity || circuitBreaker != null) && StringUtils.startsWith(contentType, "multipart") == false; return (isDataSecurity || circuitBreaker != null) && StringUtils.startsWith(contentType, "multipart") == false;
} }
/*** /***
* 优先apicode配置限流无法找到匹配全局限流 * 优先apicode配置限流无法找到匹配全局限流
* *
* @param appCode * @param appCode
* @param apiCode * @param apiCode
* @return * @return
@ -226,7 +241,7 @@ public class AppConfigHandler {
public static ApiConfig getApicodeConfig(String key) { public static ApiConfig getApicodeConfig(String key) {
return APICODE_CONFIG_MAP.get(key); return APICODE_CONFIG_MAP.get(key);
} }
public static Long getApicodeConfigTimeOut(String key) { public static Long getApicodeConfigTimeOut(String key) {
return APICODE_CONFIG_MAP.get(key) != null ? APICODE_CONFIG_MAP.get(key).getTimeout() : 3000L; return APICODE_CONFIG_MAP.get(key) != null ? APICODE_CONFIG_MAP.get(key).getTimeout() : 3000L;
} }
@ -240,8 +255,115 @@ public class AppConfigHandler {
&& StringUtils.equals(httpMethod, APICODE_CONFIG_MAP.get(key).getMethod()); && StringUtils.equals(httpMethod, APICODE_CONFIG_MAP.get(key).getMethod());
} }
public static String mock(String key) { public static MockResponse mock(String key, RoutingContext rc) {
return APICODE_CONFIG_MAP.get(key) != null ? APICODE_CONFIG_MAP.get(key).getMockResponse() : null; if (APICODE_CONFIG_MAP.get(key) != null && APICODE_CONFIG_MAP.get(key).getMockDefaultHttpStatus() != null){
Integer httpStatus = APICODE_CONFIG_MAP.get(key).getMockDefaultHttpStatus();
String mockResponse = APICODE_CONFIG_MAP.get(key).getMockDefaultResponse();
List<MockExpectation> mockExpectations = APICODE_CONFIG_MAP.get(key).getMockExpectations();
if (mockExpectations != null && !mockExpectations.isEmpty()){
RequestBody body = rc.body();
JsonObject jsonBody = body.asJsonObject();
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<String> parameterValue = matchCondition.getParameterValue();
String requestParameterValue = getRequestParameterValue(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;
}
}
if (matchSuccess){
httpStatus = mockExpectation.getHttpStatus();
mockResponse = mockExpectation.getMockResponse();
break;
}
}
}
return new MockResponse(httpStatus,mockResponse);
}
return null;
}
private static String getRequestParameterValue(String parameterPosition, String parameterKey, HttpServerRequest request,JsonObject jsonBody) {
switch (parameterPosition){
case "query":
return request.getParam(parameterKey);
case "header":
return request.getHeader(parameterKey);
case "body":
return jsonBody.getString(parameterKey);
default:
break;
}
return null;
} }
private static RateLimiterRegistry createRateLimiter(Strategy strategy) { private static RateLimiterRegistry createRateLimiter(Strategy strategy) {
@ -263,7 +385,7 @@ public class AppConfigHandler {
/*** /***
* 从redis加载数据 * 从redis加载数据
* *
* @throws Exception * @throws Exception
*/ */
public static void initAllAppConfig() { public static void initAllAppConfig() {
@ -376,12 +498,12 @@ public class AppConfigHandler {
if(sacService.getServiceType() != null) { if(sacService.getServiceType() != null) {
APICODE_CONFIG_SERVICE_TYPE_MAP.put(key, sacService.getServiceType()); APICODE_CONFIG_SERVICE_TYPE_MAP.put(key, sacService.getServiceType());
} }
// OPEN模式, 域名映射 // OPEN模式, 域名映射
if(isServiceTypeOpen(key) && StringUtils.equals(apiConfig.getUri(), "*")) { if(isServiceTypeOpen(key) && StringUtils.equals(apiConfig.getUri(), "*")) {
APICODE_APPCONFIG_MAP.put(apiConfig.getApiCode(), appConfig); APICODE_APPCONFIG_MAP.put(apiConfig.getApiCode(), appConfig);
} }
// 负载均衡模式 // 负载均衡模式
APICODE_CONFIG_ROUTERTYPE_MAP.put(key, routerType); APICODE_CONFIG_ROUTERTYPE_MAP.put(key, routerType);
switch (routerType) { switch (routerType) {
@ -531,7 +653,7 @@ public class AppConfigHandler {
/*** /***
* 发布消息订阅消息 * 发布消息订阅消息
* *
* @param msg * @param msg
*/ */
public static void publishClusterEventMsg(ClusterEventMsg msg) { public static void publishClusterEventMsg(ClusterEventMsg msg) {
@ -607,14 +729,22 @@ public class AppConfigHandler {
String rateLimitModel = vertxConfig.getRateLimitModel(); String rateLimitModel = vertxConfig.getRateLimitModel();
Route routeSac = mainHttpRouter.route(rpcUri()); Route routeSac = mainHttpRouter.route(rpcUri());
Route routeOpen = mainHttpRouter.route(); Route routeOpen = mainHttpRouter.route();
routeSac.handler(ParameterCheckHandler.create()).handler(AppRateLimitHandler.create(rateLimitModel)) routeSac.handler(ParameterCheckHandler.create())
.handler(ApiRateLimitHandler.create(rateLimitModel)).handler(BodyHandler.create()) .handler(AppRateLimitHandler.create(rateLimitModel))
.handler(ProxyHandler.create(mainWebClient, proxy)).failureHandler(RestfulFailureHandler.create()); .handler(ApiRateLimitHandler.create(rateLimitModel))
.handler(BodyHandler.create())
.handler(ApiMockHandler.create())
.handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create());
// mainHttpRouter.route().handler(ProxyHandler.create(mainWebClient, proxy)); // mainHttpRouter.route().handler(ProxyHandler.create(mainWebClient, proxy));
routeOpen.handler(ParameterCheckHandler.create()).handler(AppRateLimitHandler.create(rateLimitModel)) routeOpen.handler(ParameterCheckHandler.create())
.handler(ApiRateLimitHandler.create(rateLimitModel)).handler(BodyHandler.create()) .handler(AppRateLimitHandler.create(rateLimitModel))
.handler(ProxyHandler.create(mainWebClient, proxy)).failureHandler(RestfulFailureHandler.create()); .handler(ApiRateLimitHandler.create(rateLimitModel))
.handler(BodyHandler.create())
.handler(ApiMockHandler.create())
.handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create());
} }
/*** /***
@ -651,4 +781,57 @@ public class AppConfigHandler {
} }
} }
public static String bodyEncrypt(String body, String appCode) {
DataSecurity dataSecurity = getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesEncrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaEncrypt(body, dataSecurity.getPublicKey());
default:
break;
}
log.info(" appCode:{}, encrypt key config is error.", appCode);
throw new HttpException(10011);
}
public static String bodyDecrypt(String body, String appCode) {
DataSecurity dataSecurity = getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesDecrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaDecrypt(body, dataSecurity.getPrivateKey());
default:
break;
}
log.info(" appCode:{}, decrypt key config is error.", appCode);
throw new HttpException(10011);
}
public static String getApiCodeConfigCacheKey(RoutingContext rc){
String domain = rc.request().authority().host();
log.info("domain:{}", domain);
String appCode = rc.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
String apiCode = rc.request().headers().get(AppConfigHandler.getApiCodeHeaderKey());
String key = appCode + ":" + apiCode;
if (StringUtils.isBlank(appCode) || StringUtils.isBlank(apiCode)
|| AppConfigHandler.getAppConfig(appCode) == null
|| AppConfigHandler.getApicodeConfig(key) == null) {
// 判断OPEN模式, header不传递参数, 走域名映射
AppConfig appConfig = AppConfigHandler.getAppConfigByDomain(domain);
if(appConfig != null) {
appCode = appConfig.getAppCode();
apiCode = domain;
rc.request().headers().add(AppConfigHandler.getAppCodeHeaderKey(), appCode);
rc.request().headers().add(AppConfigHandler.getApiCodeHeaderKey(), apiCode);
key = appCode + ":" + apiCode;
} else {
rc.fail(new HttpException(10012));
}
}
return key;
}
} }

View File

@ -1,5 +1,7 @@
package com.sf.vertx.handle; package com.sf.vertx.handle;
import com.sf.vertx.api.pojo.MockResponse;
import io.vertx.ext.web.RequestBody;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.sf.vertx.api.pojo.AppConfig; import com.sf.vertx.api.pojo.AppConfig;
@ -49,13 +51,7 @@ public class ParameterCheckHandlerImpl implements ParameterCheckHandler {
rc.fail(new HttpException(10018)); rc.fail(new HttpException(10018));
return; return;
} }
// mock
String mockResponse = AppConfigHandler.mock(key);
if(StringUtils.isNotBlank(mockResponse)) {
rc.fail(new MockException(10020, mockResponse));
return;
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
rc.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE)); rc.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE));

View File

@ -32,8 +32,8 @@ public class RestfulFailureHandlerImpl implements RestfulFailureHandler {
} else if (failure instanceof MockException) { } else if (failure instanceof MockException) {
MockException httpException = (MockException) failure; MockException httpException = (MockException) failure;
sc = httpException.getStatusCode(); sc = httpException.getStatusCode();
statusCode = httpException.getStatusCode();
if (StringUtils.isNoneBlank(httpException.getPayload())) { if (StringUtils.isNoneBlank(httpException.getPayload())) {
statusCode = 200;
errorJson = new JsonObject(httpException.getPayload()); errorJson = new JsonObject(httpException.getPayload());
} else { } else {
errorJson = SacErrorCode.returnErrorMsg(httpException.getStatusCode()); errorJson = SacErrorCode.returnErrorMsg(httpException.getStatusCode());

View File

@ -251,7 +251,7 @@ public class ReverseProxy implements HttpProxy {
HttpRequest<Buffer> requestBuffer = methodGetRequestBuffer(proxyRequest); HttpRequest<Buffer> requestBuffer = methodGetRequestBuffer(proxyRequest);
requestBuffer.timeout(AppConfigHandler.getApicodeConfigTimeOut(key)); requestBuffer.timeout(AppConfigHandler.getApicodeConfigTimeOut(key));
requestBuffer.putHeaders(proxyRequest.headers()) requestBuffer.putHeaders(proxyRequest.headers())
.sendJson(bodyDecrypt(ctx.getBodyAsString(), appCode), h -> { .sendJson(AppConfigHandler.bodyDecrypt(ctx.getBodyAsString(), appCode), h -> {
if (h.succeeded()) { if (h.succeeded()) {
log.info("==========uri:{},response http code:{}", proxyRequest.getURI(), log.info("==========uri:{},response http code:{}", proxyRequest.getURI(),
h.result().statusCode()); h.result().statusCode());
@ -268,7 +268,7 @@ public class ReverseProxy implements HttpProxy {
JsonObject responseData = h.result().bodyAsJsonObject(); JsonObject responseData = h.result().bodyAsJsonObject();
log.info("responseData:{}", responseData); log.info("responseData:{}", responseData);
// 加密 // 加密
String dataStr = bodyEncrypt(responseData.toString(), appCode); String dataStr = AppConfigHandler.bodyEncrypt(responseData.toString(), appCode);
log.info("aesEncrypt dataStr:{}", dataStr); log.info("aesEncrypt dataStr:{}", dataStr);
Buffer buffer = Buffer.buffer(dataStr); Buffer buffer = Buffer.buffer(dataStr);
ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200) ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200)
@ -362,7 +362,7 @@ public class ReverseProxy implements HttpProxy {
return Future.future(p -> { return Future.future(p -> {
HttpRequest<Buffer> requestBuffer = methodGetRequestBuffer(proxyRequest); HttpRequest<Buffer> requestBuffer = methodGetRequestBuffer(proxyRequest);
requestBuffer.timeout(AppConfigHandler.getApicodeConfigTimeOut(key)); requestBuffer.timeout(AppConfigHandler.getApicodeConfigTimeOut(key));
requestBuffer.putHeaders(proxyRequest.headers()).sendJson(bodyDecrypt(ctx.getBodyAsString(), appCode), requestBuffer.putHeaders(proxyRequest.headers()).sendJson(AppConfigHandler.bodyDecrypt(ctx.getBodyAsString(), appCode),
h -> { h -> {
if (h.succeeded()) { if (h.succeeded()) {
log.info("==========uri:{},response http code:{}", proxyRequest.getURI(), log.info("==========uri:{},response http code:{}", proxyRequest.getURI(),
@ -373,7 +373,7 @@ public class ReverseProxy implements HttpProxy {
JsonObject responseData = h.result().bodyAsJsonObject(); JsonObject responseData = h.result().bodyAsJsonObject();
log.info("responseData:{}", responseData); log.info("responseData:{}", responseData);
// 加密 // 加密
String dataStr = bodyEncrypt(responseData.toString(), appCode); String dataStr = AppConfigHandler.bodyEncrypt(responseData.toString(), appCode);
log.info("encrypt dataStr:{}", dataStr); log.info("encrypt dataStr:{}", dataStr);
Buffer buffer = Buffer.buffer(dataStr); Buffer buffer = Buffer.buffer(dataStr);
ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200) ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200)
@ -491,32 +491,6 @@ public class ReverseProxy implements HttpProxy {
return sendResponse(); return sendResponse();
} }
private String bodyEncrypt(String body, String appCode) {
DataSecurity dataSecurity = AppConfigHandler.getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesEncrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaEncrypt(body, dataSecurity.getPublicKey());
default:
break;
}
log.info(" appCode:{}, encrypt key config is error.", appCode);
throw new HttpException(10011);
}
private String bodyDecrypt(String body, String appCode) {
DataSecurity dataSecurity = AppConfigHandler.getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesDecrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaDecrypt(body, dataSecurity.getPrivateKey());
default:
break;
}
log.info(" appCode:{}, decrypt key config is error.", appCode);
throw new HttpException(10011);
}
} }
} }