diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml
index f3e41d94..6a032d17 100644
--- a/sop-admin/sop-admin-server/pom.xml
+++ b/sop-admin/sop-admin-server/pom.xml
@@ -30,7 +30,7 @@
com.gitee.sop
sop-registry-api
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
diff --git a/sop-common/pom.xml b/sop-common/pom.xml
index 627e7d0d..6b19dffd 100644
--- a/sop-common/pom.xml
+++ b/sop-common/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.gitee.sop
sop-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
pom
diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml
index 8532ebda..223f94fa 100644
--- a/sop-common/sop-gateway-common/pom.xml
+++ b/sop-common/sop-gateway-common/pom.xml
@@ -5,11 +5,11 @@
com.gitee.sop
sop-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
../pom.xml
sop-gateway-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
jar
sop-gateway-common
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
index c0ba6457..7ed69b01 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
@@ -9,7 +9,7 @@ import java.nio.charset.StandardCharsets;
public class SopConstants {
private SopConstants() {}
-
+
public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
public static final String UTF8 = "UTF-8";
public static final String FORMAT_JSON = "json";
@@ -51,5 +51,7 @@ public class SopConstants {
public static final String SOP_MSG_CHANNEL_PATH = "/com.gitee.sop.channel";
-
+ public static final String UNKNOWN_SERVICE= "_sop_unknown_service_";
+ public static final String UNKNOWN_METHOD = "_sop_unknown_method_";
+ public static final String UNKNOWN_VERSION = "_sop_unknown_version_";
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java
index c1fe98ec..8b7e2d2c 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java
@@ -1,9 +1,78 @@
package com.gitee.sop.gatewaycommon.gateway;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
+import com.gitee.sop.gatewaycommon.bean.SopConstants;
+import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.util.RequestUtil;
+import org.springframework.http.HttpMethod;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP;
+import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY;
/**
* @author tanghc
*/
public class GatewayContext extends ApiContext {
+
+ /**
+ * 获取请求参数
+ * @param exchange
+ * @return
+ */
+ public static ApiParam getApiParam(ServerWebExchange exchange) {
+ return exchange.getAttribute(SopConstants.CACHE_API_PARAM);
+ }
+
+ /**
+ * 设置请求参数
+ * @param exchange
+ * @param apiParam
+ */
+ public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) {
+ exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam);
+ }
+
+ /**
+ * 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory
+ * @param exchange
+ * @return 没有参数返回null
+ * @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
+ */
+ public static Map getRequestParams(ServerWebExchange exchange) {
+ Map params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP);
+ if (params != null) {
+ return params;
+ }
+ if (exchange.getRequest().getMethod() == HttpMethod.GET) {
+ MultiValueMap queryParams = exchange.getRequest().getQueryParams();
+ params = buildParams(queryParams);
+ } else {
+ String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
+ if (cachedBody != null) {
+ params = RequestUtil.parseQueryToMap(cachedBody);
+ }
+ }
+ if (params != null) {
+ exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params);
+ }
+ return params;
+ }
+
+ private static Map buildParams(MultiValueMap queryParams) {
+ if (queryParams == null || queryParams.size() == 0) {
+ return null;
+ }
+ Map params = new HashMap<>(queryParams.size());
+ for (Map.Entry> entry : queryParams.entrySet()) {
+ String val = entry.getValue().get(0);
+ params.put(entry.getKey(), val);
+ }
+ return params;
+ }
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
index 4cdee962..084560bb 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
@@ -3,8 +3,8 @@ package com.gitee.sop.gatewaycommon.gateway.filter;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
import com.gitee.sop.gatewaycommon.limit.LimitManager;
import com.gitee.sop.gatewaycommon.limit.LimitType;
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
@@ -35,7 +35,7 @@ public class LimitFilter implements GlobalFilter, Ordered {
if (!apiConfig.isOpenLimit()) {
return chain.filter(exchange);
}
- ApiParam apiParam = exchange.getAttribute(SopConstants.CACHE_API_PARAM);
+ ApiParam apiParam = GatewayContext.getApiParam(exchange);
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
if (configLimitDto == null) {
return null;
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
index 32dc3baa..36911028 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
@@ -2,8 +2,8 @@ package com.gitee.sop.gatewaycommon.gateway.filter;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.validate.Validator;
import lombok.extern.slf4j.Slf4j;
@@ -24,7 +24,7 @@ public class ValidateFilter implements GlobalFilter, Ordered {
ApiConfig apiConfig = ApiContext.getApiConfig();
// 解析参数
ApiParam param = apiConfig.getGatewayParamBuilder().build(exchange);
- exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, param);
+ GatewayContext.setApiParam(exchange, param);
// 验证操作,这里有负责验证签名参数
Validator validator = apiConfig.getValidator();
try {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
index 19b17100..e0f1ae96 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
@@ -1,9 +1,10 @@
package com.gitee.sop.gatewaycommon.gateway.param;
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
+import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
import com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
import org.springframework.web.server.ServerWebExchange;
+import java.util.Collections;
import java.util.Map;
/**
@@ -12,7 +13,8 @@ import java.util.Map;
public class GatewayParamBuilder extends BaseParamBuilder {
@Override
- public Map buildRequestParams(ServerWebExchange request) {
- return request.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
+ public Map buildRequestParams(ServerWebExchange exchange) {
+ Map params = GatewayContext.getRequestParams(exchange);
+ return params == null ? Collections.emptyMap() : params;
}
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
index f9f14d68..f3beb109 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
@@ -3,22 +3,12 @@ package com.gitee.sop.gatewaycommon.gateway.route;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.RouteRepository;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.PredicateArgsEvent;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
-import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
-import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
-import org.springframework.cloud.gateway.support.ConfigurationUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
-import org.springframework.core.convert.ConversionService;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.validation.Validator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -39,27 +29,17 @@ import static java.util.Collections.synchronizedMap;
@Slf4j
public class GatewayRouteRepository implements ApplicationEventPublisherAware,
RouteDefinitionRepository,
- BeanFactoryAware,
RouteRepository {
private final Map routes = synchronizedMap(new LinkedHashMap<>());
- private final SpelExpressionParser parser = new SpelExpressionParser();
-
- @Autowired
- private ConversionService conversionService;
-
- @Autowired
- private Validator validator;
-
private ApplicationEventPublisher publisher;
- private BeanFactory beanFactory;
-
@Override
public Flux getRouteDefinitions() {
List list = routes.values().parallelStream()
.map(TargetRoute::getTargetRouteDefinition)
+ .filter(routeDefinition -> !routeDefinition.getId().contains("_first.route_"))
.collect(Collectors.toList());
return Flux.fromIterable(list);
}
@@ -97,7 +77,6 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
public String add(GatewayTargetRoute targetRoute) {
GatewayRouteDefinition baseRouteDefinition = targetRoute.getRouteDefinition();
routes.put(baseRouteDefinition.getId(), targetRoute);
- this.initPredicateDefinition(targetRoute);
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
@@ -108,23 +87,6 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
routes.put(baseRouteDefinition.getId(), targetRoute);
}
- protected void initPredicateDefinition(GatewayTargetRoute targetRoute) {
- GatewayRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
- RouteDefinition targetRouteDefinition = targetRoute.getTargetRouteDefinition();
- for (PredicateDefinition predicate : targetRouteDefinition.getPredicates()) {
- Map args = predicate.getArgs();
- if (!args.isEmpty()) {
- RoutePredicateFactory factory = new NameVersionRoutePredicateFactory();
- Map properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
- Object config = factory.newConfig();
- ConfigurationUtils.bind(config, properties, factory.shortcutFieldPrefix(), predicate.getName(),
- validator, conversionService);
- this.publisher.publishEvent(new PredicateArgsEvent(this, routeDefinition.getId(), properties));
- }
- }
-
- }
-
/**
* 删除路由
*/
@@ -150,8 +112,4 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
this.publisher = applicationEventPublisher;
}
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = beanFactory;
- }
}
\ No newline at end of file
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayZookeeperRouteManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayZookeeperRouteManager.java
index e515df03..b77844e0 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayZookeeperRouteManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayZookeeperRouteManager.java
@@ -12,6 +12,7 @@ import org.springframework.core.env.Environment;
import java.net.URI;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -44,7 +45,7 @@ public class GatewayZookeeperRouteManager extends BaseRouteManager filterDefinitionList = new ArrayList<>(gatewayRouteDefinition.getFilters().size());
- List predicateDefinitionList = new ArrayList<>(gatewayRouteDefinition.getPredicates().size());
+ LinkedList predicateDefinitionList = new LinkedList<>();
for (GatewayFilterDefinition filter : gatewayRouteDefinition.getFilters()) {
FilterDefinition filterDefinition = new FilterDefinition();
BeanUtils.copyProperties(filter, filterDefinition);
@@ -56,10 +57,28 @@ public class GatewayZookeeperRouteManager extends BaseRouteManager predicateDefinitionList, String name, String args) {
+ for (PredicateDefinition predicateDefinition : predicateDefinitionList) {
+ // 如果已经存在,直接返回
+ if (predicateDefinition.getName().equals(name)) {
+ return;
+ }
+ }
+ predicateDefinitionList.addFirst(new PredicateDefinition(name + "=" + args));
+ }
+
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
index b13a53c6..10ffb40e 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
@@ -1,10 +1,11 @@
package com.gitee.sop.gatewaycommon.gateway.route;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
+import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
import com.gitee.sop.gatewaycommon.param.ParamNames;
-import com.gitee.sop.gatewaycommon.util.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
+import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
@@ -15,17 +16,15 @@ import java.util.Map;
import java.util.function.Predicate;
/**
+ * 此断言决定执行哪个路由
+ *
* @author tanghc
*/
@Slf4j
public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFactory {
- public static final String PARAM_KEY = "param";
- public static final String REGEXP_KEY = "regexp";
-
- private static final String CACHE_REQUEST_BODY_OBJECT_KEY = SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY;
- public static final String CACHE_REQUEST_BODY_FOR_MAP = SopConstants.CACHE_REQUEST_BODY_FOR_MAP;
-
+ private static final String PARAM_KEY = "param";
+ private static final String REGEXP_KEY = "regexp";
public NameVersionRoutePredicateFactory() {
super(Config.class);
@@ -37,7 +36,7 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
}
/**
- * config.param为nameVersion
+ * config.param为nameVersion,即路由id
*
* @param config
* @return 返回断言
@@ -46,21 +45,14 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
public Predicate apply(Config config) {
return exchange -> {
- String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
- if (cachedBody == null) {
+ Map params = GatewayContext.getRequestParams(exchange);
+ if (CollectionUtils.isEmpty(params)) {
return false;
}
- Map params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP);
- if (params == null) {
- params = RequestUtil.parseQueryToMap(cachedBody);
- exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params);
- }
-
String nameVersion = config.param;
- String name = params.getOrDefault(ParamNames.API_NAME, String.valueOf(System.currentTimeMillis()));
+ String name = params.getOrDefault(ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD);
String version = params.getOrDefault(ParamNames.VERSION_NAME, "");
- boolean match = (name + version).equals(nameVersion);
- return match;
+ return (name + version).equals(nameVersion);
};
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
index dc5b3259..8dfd7f05 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
@@ -1,19 +1,145 @@
package com.gitee.sop.gatewaycommon.gateway.route;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.gateway.handler.AsyncPredicate;
+import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.codec.HttpMessageReader;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.server.HandlerStrategies;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.function.Predicate;
+
+import static org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter.CACHED_REQUEST_BODY_KEY;
/**
- * 获取form表单插件,使用方式:
+ * 获取请求参数插件,兼容get,post,使用方式:
* @Bean
* ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() {
* return new ReadBodyRoutePredicateFactory();
* }
*
+ * @see org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory
+ * 详见:https://blog.51cto.com/thinklili/2329184
* @author tanghc
*/
-public class ReadBodyRoutePredicateFactory extends ReadBodyPredicateFactory {
+public class ReadBodyRoutePredicateFactory extends AbstractRoutePredicateFactory {
+
+ protected static final Log LOGGER = LogFactory.getLog(ReadBodyPredicateFactory.class);
+
+ private static final String TEST_ATTRIBUTE = "read_body_predicate_test_attribute";
+ private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";
+ private static final List> messageReaders = HandlerStrategies.withDefaults().messageReaders();
+
+
+ public ReadBodyRoutePredicateFactory() {
+ super(ReadBodyRoutePredicateFactory.Config.class);
+ }
+
+ @Override
+ public AsyncPredicate applyAsync(Config config) {
+ return exchange -> {
+ HttpMethod method = exchange.getRequest().getMethod();
+ if (method == HttpMethod.POST) {
+ return this.applyForPost(exchange, config);
+ } else {
+ return this.applyForGet(exchange, config);
+ }
+ };
+ }
+
+ /**
+ * 获取post表单参数
+ * @param exchange
+ * @param config
+ * @return
+ */
+ protected Mono applyForPost(ServerWebExchange exchange, Config config) {
+ Class inClass = config.getInClass();
+
+ Object cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
+ // We can only read the body from the request once, once that happens if we try to read the body again an
+ // exception will be thrown. The below if/else caches the body object as a request attribute in the ServerWebExchange
+ // so if this filter is run more than once (due to more than one route using it) we do not try to read the
+ // request body multiple times
+ if (cachedBody != null) {
+ try {
+ boolean test = config.getPredicate().test(cachedBody);
+ exchange.getAttributes().put(TEST_ATTRIBUTE, test);
+ return Mono.just(test);
+ } catch (ClassCastException e) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Predicate test failed because class in predicate does not match the cached body object",
+ e);
+ }
+ }
+ return Mono.just(false);
+ } else {
+ //Join all the DataBuffers so we have a single DataBuffer for the body
+ return DataBufferUtils.join(exchange.getRequest().getBody())
+ .flatMap(dataBuffer -> {
+ //Update the retain counts so we can read the body twice, once to parse into an object
+ //that we can test the predicate against and a second time when the HTTP client sends
+ //the request downstream
+ //Note: if we end up reading the body twice we will run into a problem, but as of right
+ //now there is no good use case for doing this
+ DataBufferUtils.retain(dataBuffer);
+ //Make a slice for each read so each read has its own read/write indexes
+ Flux cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
+
+ ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
+ @Override
+ public Flux getBody() {
+ return cachedFlux;
+ }
+ };
+ return ServerRequest.create(exchange.mutate().request(mutatedRequest).build(), messageReaders)
+ .bodyToMono(inClass)
+ .doOnNext(objectValue -> {
+ exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue);
+ exchange.getAttributes().put(CACHED_REQUEST_BODY_KEY, cachedFlux);
+ })
+ .map(objectValue -> config.getPredicate().test(objectValue));
+ });
+
+ }
+ }
+
+ /**
+ * 获取GET请求参数
+ * @param exchange
+ * @param config
+ * @return
+ */
+ protected Mono applyForGet(ServerWebExchange exchange, Config config) {
+ // 处理get请求
+ MultiValueMap queryParams = exchange.getRequest().getQueryParams();
+ String objectValue = null;
+ if (queryParams != null && queryParams.size() > 0) {
+ List params = new ArrayList<>(queryParams.size());
+ for (Map.Entry> entry : queryParams.entrySet()) {
+ params.add(entry.getKey() + "=" + entry.getValue().get(0));
+ }
+ objectValue = StringUtils.join(params.toArray());
+ exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue);
+ }
+ return Mono.just(config.getPredicate().test(objectValue));
+ }
@Override
public Config newConfig() {
@@ -22,4 +148,51 @@ public class ReadBodyRoutePredicateFactory extends ReadBodyPredicateFactory {
config.setPredicate(Objects::nonNull);
return config;
}
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Predicate apply(Config config) {
+ throw new UnsupportedOperationException(
+ "ReadBodyPredicateFactory is only async.");
+ }
+
+ public static class Config {
+ private Class inClass;
+ private Predicate predicate;
+ private Map hints;
+
+ public Class getInClass() {
+ return inClass;
+ }
+
+ public Config setInClass(Class inClass) {
+ this.inClass = inClass;
+ return this;
+ }
+
+ public Predicate getPredicate() {
+ return predicate;
+ }
+
+ public Config setPredicate(Class inClass, Predicate predicate) {
+ setInClass(inClass);
+ this.predicate = predicate;
+ return this;
+ }
+
+ public Config setPredicate(Predicate predicate) {
+ this.predicate = predicate;
+ return this;
+ }
+
+ public Map getHints() {
+ return hints;
+ }
+
+ public Config setHints(Map hints) {
+ this.hints = hints;
+ return this;
+ }
+ }
+
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
index 5b56bb66..800a675f 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
@@ -38,9 +38,8 @@ public class DefaultRouteConfigManager implements RouteConfigManager {
routeConfig = newRouteConfig();
routeConfig.setRouteId(routeId);
routeConfigMap.put(routeId, routeConfig);
- } else {
- MyBeanUtil.copyPropertiesIgnoreNull(res, routeConfig);
}
+ MyBeanUtil.copyPropertiesIgnoreNull(res, routeConfig);
routeConfig.initRateLimiter();
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParamNames.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParamNames.java
index 5d5e0928..5167423e 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParamNames.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParamNames.java
@@ -42,5 +42,8 @@ public class ParamNames {
/** */
public static String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ /** 返回sign名称 */
+ public static String RESPONSE_SIGN_NAME = "sign";
+
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
index 34ca08cc..c2340712 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
@@ -145,15 +145,15 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
protected ApiInfo getApiInfo(T request) {
Map params = this.getApiParam(request);
- String name = this.getParamValue(params, ParamNames.API_NAME, "method.unknown");
- String version = this.getParamValue(params, ParamNames.VERSION_NAME, "version.unknown");
+ String name = this.getParamValue(params, ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD);
+ String version = this.getParamValue(params, ParamNames.VERSION_NAME, SopConstants.UNKNOWN_VERSION);
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(name + version);
String serviceId = Optional.ofNullable(targetRoute)
.flatMap(route -> Optional.ofNullable(route.getServiceRouteInfo()))
.map(BaseServiceRouteInfo::getServiceId)
- .orElse("serviceId.unknown");
+ .orElse(SopConstants.UNKNOWN_SERVICE);
BaseRouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute)
.map(route -> route.getRouteDefinition())
@@ -182,7 +182,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
}
public String merge(T exchange, JSONObject responseData) {
- JSONObject finalData = new JSONObject();
+ JSONObject finalData = new JSONObject(true);
Map params = this.getApiParam(exchange);
String name = this.getParamValue(params, ParamNames.API_NAME, ERROR_METHOD);
ApiConfig apiConfig = ApiConfig.getInstance();
@@ -200,9 +200,10 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
if (apiConfig.isShowReturnSign() && !CollectionUtils.isEmpty(params)) {
// 添加try...catch,生成sign出错不影响结果正常返回
try {
- String sign = this.createResponseSign(apiConfig, params, responseData.toJSONString());
+ String responseSignContent = this.buildResponseSignContent(responseDataNodeName, finalData);
+ String sign = this.createResponseSign(apiConfig, params, responseSignContent);
if (StringUtils.hasLength(sign)) {
- finalData.put(ParamNames.SIGN_NAME, sign);
+ finalData.put(ParamNames.RESPONSE_SIGN_NAME, sign);
}
} catch (Exception e) {
log.error("生成平台签名失败, params: {}, serviceResult:{}", JSON.toJSONString(params), responseData, e);
@@ -211,6 +212,24 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
return finalData.toJSONString();
}
+ /**
+ * 获取待签名内容
+ *
+ * @param rootNodeName 业务数据节点
+ * @param finalData 最终结果
+ * @return 返回待签名内容
+ */
+ protected String buildResponseSignContent(String rootNodeName, JSONObject finalData) {
+ String body = finalData.toJSONString();
+ int indexOfRootNode = body.indexOf(rootNodeName);
+ if (indexOfRootNode > 0) {
+ int signDataStartIndex = indexOfRootNode + rootNodeName.length() + 2;
+ int length = body.length() - 1;
+ return body.substring(signDataStartIndex, length);
+ }
+ return null;
+ }
+
protected String getParamValue(Map apiParam, String key, String defaultValue) {
return CollectionUtils.isEmpty(apiParam) ? defaultValue : (String) apiParam.getOrDefault(key, defaultValue);
}
@@ -219,12 +238,15 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
/**
* 这里需要使用平台的私钥生成一个sign,需要配置两套公私钥。
*
- * @param apiConfig 配置
- * @param params 请求参数
- * @param serviceResult 业务返回结果
+ * @param apiConfig 配置
+ * @param params 请求参数
+ * @param responseSignContent 待签名内容
* @return 返回平台生成的签名
*/
- protected String createResponseSign(ApiConfig apiConfig, Map params, String serviceResult) {
+ protected String createResponseSign(ApiConfig apiConfig, Map params, String responseSignContent) {
+ if (StringUtils.isEmpty(responseSignContent)) {
+ return null;
+ }
IsvManager isvManager = apiConfig.getIsvManager();
// 根据appId获取秘钥
String appKey = this.getParamValue(params, ParamNames.APP_KEY_NAME, "");
@@ -240,7 +262,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
.map(String::valueOf)
.orElse(SopConstants.UTF8);
String signType = getParamValue(params, ParamNames.SIGN_TYPE_NAME, AlipayConstants.SIGN_TYPE_RSA2);
- return AlipaySignature.rsaSign(serviceResult, privateKeyPlatform, charset, signType);
+ return AlipaySignature.rsaSign(responseSignContent, privateKeyPlatform, charset, signType);
}
@Getter
diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml
index 83bd1dd1..e613f1b4 100644
--- a/sop-common/sop-registry-api/pom.xml
+++ b/sop-common/sop-registry-api/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.gitee.sop
sop-registry-api
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
UTF-8
diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml
index cda7acb7..ac643b22 100644
--- a/sop-common/sop-service-common/pom.xml
+++ b/sop-common/sop-service-common/pom.xml
@@ -6,11 +6,11 @@
com.gitee.sop
sop-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
../pom.xml
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
jar
sop-service-common
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
index 7dc95210..2807e123 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.gitee.sop.servercommon.bean.ServiceApiInfo;
import com.gitee.sop.servercommon.bean.ServiceConstants;
import com.gitee.sop.servercommon.bean.ZookeeperTool;
-import com.gitee.sop.servercommon.route.GatewayPredicateDefinition;
import com.gitee.sop.servercommon.route.GatewayRouteDefinition;
import com.gitee.sop.servercommon.route.ServiceRouteInfo;
import lombok.Getter;
@@ -16,7 +15,6 @@ import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -36,14 +34,6 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
public static final String SOP_SERVICE_ROUTE_PATH = ServiceConstants.SOP_SERVICE_ROUTE_PATH;
public static final String PATH_START_CHAR = "/";
- /**
- * NameVersion=alipay.story.get1.0
- * see com.gitee.sop.gatewaycommon.routeDefinition.NameVersionRoutePredicateFactory
- */
- private static String QUERY_PREDICATE_DEFINITION_TPL = "NameVersion=%s";
-
- private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first.route_", "/", "v_000");
-
private final String routeRootPath = SOP_SERVICE_ROUTE_PATH;
private Environment environment;
@@ -99,8 +89,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
*/
protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
List apis = serviceApiInfo.getApis();
- List routeDefinitionList = new ArrayList<>(apis.size() + 1);
- routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
+ List routeDefinitionList = new ArrayList<>(apis.size());
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
GatewayRouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
routeDefinitionList.add(gatewayRouteDefinition);
@@ -118,32 +107,12 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
return serviceRouteInfo;
}
- /**
- * 添加com.gitee.sop.gatewaycommon.routeDefinition.ReadBodyRoutePredicateFactory,解决form表单获取不到问题
- *
- * @return 返回路由定义
- */
- protected GatewayRouteDefinition buildReadBodyRouteDefinition(ServiceApiInfo serviceApiInfo) {
- GatewayRouteDefinition readBodyRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META);
- readBodyRouteDefinition.setOrder(Integer.MIN_VALUE);
-
- GatewayPredicateDefinition gatewayPredicateDefinition = new GatewayPredicateDefinition();
- gatewayPredicateDefinition.setName("ReadBody");
- GatewayPredicateDefinition readerBodyPredicateDefinition = this.buildNameVersionPredicateDefinition(FIRST_API_META);
- List predicates = Arrays.asList(gatewayPredicateDefinition, readerBodyPredicateDefinition);
- readBodyRouteDefinition.setPredicates(predicates);
-
- return readBodyRouteDefinition;
- }
-
protected GatewayRouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
// 唯一id规则:接口名 + 版本号
BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
gatewayRouteDefinition.setId(apiMeta.fetchNameVersion());
gatewayRouteDefinition.setFilters(Collections.emptyList());
- List predicates = Arrays.asList(this.buildNameVersionPredicateDefinition(apiMeta));
- gatewayRouteDefinition.setPredicates(predicates);
String uri = this.buildUri(serviceApiInfo, apiMeta);
String path = this.buildServletPath(serviceApiInfo, apiMeta);
gatewayRouteDefinition.setUri(uri);
@@ -166,10 +135,6 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
return servletPath;
}
- protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
- return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
- }
-
/**
* 上传接口信息到zookeeper
*
diff --git a/sop-example/sop-auth/pom.xml b/sop-example/sop-auth/pom.xml
index c51520ed..614784d8 100644
--- a/sop-example/sop-auth/pom.xml
+++ b/sop-example/sop-auth/pom.xml
@@ -26,7 +26,7 @@
com.gitee.sop
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml
index e2fa4087..3354d840 100644
--- a/sop-example/sop-book/sop-book-web/pom.xml
+++ b/sop-example/sop-book/sop-book-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
com.gitee.sop
diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml
index f4bd1d23..3dc21475 100644
--- a/sop-example/sop-easyopen/pom.xml
+++ b/sop-example/sop-easyopen/pom.xml
@@ -29,7 +29,7 @@
com.gitee.sop
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml
index 0aea2861..e3a1d8d4 100644
--- a/sop-example/sop-springmvc/pom.xml
+++ b/sop-example/sop-springmvc/pom.xml
@@ -20,7 +20,7 @@
com.gitee.sop
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml
index c9118361..889978af 100644
--- a/sop-example/sop-story/sop-story-web/pom.xml
+++ b/sop-example/sop-story/sop-story-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
com.gitee.sop
diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml
index 534f30d5..10badb21 100644
--- a/sop-gateway/pom.xml
+++ b/sop-gateway/pom.xml
@@ -23,7 +23,7 @@
com.gitee.sop
sop-gateway-common
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java
index 3127d28f..a1d09f27 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java
@@ -6,7 +6,10 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
/**
* @author tanghc
@@ -18,14 +21,15 @@ public class RedirectController {
private String path;
@RequestMapping("/{method}/{version}/")
- public String redirect(
+ public void redirect(
@PathVariable("method") String method
, @PathVariable("version") String version
, HttpServletRequest request
- ) {
+ , HttpServletResponse response
+ ) throws ServletException, IOException {
request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method);
request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version);
- return "forward:" + path;
+ request.getRequestDispatcher(path).forward(request, response);
}
}
diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml
index 2e35282c..3fe34ed0 100644
--- a/sop-website/website-server/pom.xml
+++ b/sop-website/website-server/pom.xml
@@ -25,7 +25,7 @@
com.gitee.sop
sop-registry-api
- 1.12.0-SNAPSHOT
+ 1.12.1-SNAPSHOT