Merge branch 'master' into registry-nacos

pull/1/head
tanghc 5 years ago
commit d9bd18f72e
  1. 2
      sop-admin/sop-admin-server/pom.xml
  2. 2
      sop-common/pom.xml
  3. 4
      sop-common/sop-gateway-common/pom.xml
  4. 6
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
  5. 69
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java
  6. 4
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
  7. 4
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
  8. 8
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
  9. 44
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
  10. 23
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayZookeeperRouteManager.java
  11. 30
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
  12. 177
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
  13. 3
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
  14. 3
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParamNames.java
  15. 44
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
  16. 2
      sop-common/sop-registry-api/pom.xml
  17. 4
      sop-common/sop-service-common/pom.xml
  18. 37
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
  19. 2
      sop-example/sop-auth/pom.xml
  20. 2
      sop-example/sop-book/sop-book-web/pom.xml
  21. 2
      sop-example/sop-easyopen/pom.xml
  22. 2
      sop-example/sop-springmvc/pom.xml
  23. 2
      sop-example/sop-story/sop-story-web/pom.xml
  24. 2
      sop-gateway/pom.xml
  25. 10
      sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java
  26. 2
      sop-website/website-server/pom.xml

@ -30,7 +30,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<!-- easyopen starter -->

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>

@ -5,11 +5,11 @@
<parent>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>sop-gateway-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>sop-gateway-common</name>

@ -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_";
}

@ -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<String, String> getRequestParams(ServerWebExchange exchange) {
Map<String, String> params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP);
if (params != null) {
return params;
}
if (exchange.getRequest().getMethod() == HttpMethod.GET) {
MultiValueMap<String, String> 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<String, String> buildParams(MultiValueMap<String, String> queryParams) {
if (queryParams == null || queryParams.size() == 0) {
return null;
}
Map<String, String> params = new HashMap<>(queryParams.size());
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
String val = entry.getValue().get(0);
params.put(entry.getKey(), val);
}
return params;
}
}

@ -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;

@ -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 {

@ -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<ServerWebExchange> {
@Override
public Map<String, String> buildRequestParams(ServerWebExchange request) {
return request.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
public Map<String, String> buildRequestParams(ServerWebExchange exchange) {
Map<String, String> params = GatewayContext.getRequestParams(exchange);
return params == null ? Collections.emptyMap() : params;
}
}

@ -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<GatewayTargetRoute> {
private final Map<String, GatewayTargetRoute> 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<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> 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<String, String> args = predicate.getArgs();
if (!args.isEmpty()) {
RoutePredicateFactory<NameVersionRoutePredicateFactory.Config> factory = new NameVersionRoutePredicateFactory();
Map<String, Object> 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;
}
}

@ -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<GatewayServic
routeDefinition.setUri(URI.create(gatewayRouteDefinition.getUri() + "#" + gatewayRouteDefinition.getPath()));
routeDefinition.setOrder(gatewayRouteDefinition.getOrder());
List<FilterDefinition> filterDefinitionList = new ArrayList<>(gatewayRouteDefinition.getFilters().size());
List<PredicateDefinition> predicateDefinitionList = new ArrayList<>(gatewayRouteDefinition.getPredicates().size());
LinkedList<PredicateDefinition> 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<GatewayServic
BeanUtils.copyProperties(predicate, predicateDefinition);
predicateDefinitionList.add(predicateDefinition);
}
this.addPredicate(predicateDefinitionList, "NameVersion", gatewayRouteDefinition.getId());
this.addPredicate(predicateDefinitionList, "ReadBody", "");
routeDefinition.setFilters(filterDefinitionList);
routeDefinition.setPredicates(predicateDefinitionList);
return new GatewayTargetRoute(serviceRouteInfo, gatewayRouteDefinition, routeDefinition);
}
/**
* 添加断言
*
* @param predicateDefinitionList
* @param name 断言名称
* @param args 断言参数
*/
protected void addPredicate(LinkedList<PredicateDefinition> predicateDefinitionList, String name, String args) {
for (PredicateDefinition predicateDefinition : predicateDefinitionList) {
// 如果已经存在,直接返回
if (predicateDefinition.getName().equals(name)) {
return;
}
}
predicateDefinitionList.addFirst(new PredicateDefinition(name + "=" + args));
}
}

@ -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<NameVersionRoutePredicateFactory.Config> {
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<ServerWebExchange> apply(Config config) {
return exchange -> {
String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
if (cachedBody == null) {
Map<String, String> params = GatewayContext.getRequestParams(exchange);
if (CollectionUtils.isEmpty(params)) {
return false;
}
Map<String, String> 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);
};
}

@ -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表单插件使用方式
* 获取请求参数插件兼容getpost使用方式
* &#64;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<ReadBodyRoutePredicateFactory.Config> {
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<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
public ReadBodyRoutePredicateFactory() {
super(ReadBodyRoutePredicateFactory.Config.class);
}
@Override
public AsyncPredicate<ServerWebExchange> 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<Boolean> 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<DataBuffer> cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux<DataBuffer> 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<Boolean> applyForGet(ServerWebExchange exchange, Config config) {
// 处理get请求
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
String objectValue = null;
if (queryParams != null && queryParams.size() > 0) {
List<String> params = new ArrayList<>(queryParams.size());
for (Map.Entry<String, List<String>> 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<ServerWebExchange> apply(Config config) {
throw new UnsupportedOperationException(
"ReadBodyPredicateFactory is only async.");
}
public static class Config {
private Class inClass;
private Predicate predicate;
private Map<String, Object> hints;
public Class getInClass() {
return inClass;
}
public Config setInClass(Class inClass) {
this.inClass = inClass;
return this;
}
public Predicate getPredicate() {
return predicate;
}
public <T> Config setPredicate(Class<T> inClass, Predicate<T> predicate) {
setInClass(inClass);
this.predicate = predicate;
return this;
}
public Config setPredicate(Predicate predicate) {
this.predicate = predicate;
return this;
}
public Map<String, Object> getHints() {
return hints;
}
public Config setHints(Map<String, Object> hints) {
this.hints = hints;
return this;
}
}
}

@ -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();
}

@ -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";
}

@ -145,15 +145,15 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
protected ApiInfo getApiInfo(T request) {
Map<String, Object> 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<T, R> implements ResultExecutor<T, R>
}
public String merge(T exchange, JSONObject responseData) {
JSONObject finalData = new JSONObject();
JSONObject finalData = new JSONObject(true);
Map<String, Object> 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<T, R> implements ResultExecutor<T, R>
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<T, R> implements ResultExecutor<T, R>
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<String, Object> apiParam, String key, String defaultValue) {
return CollectionUtils.isEmpty(apiParam) ? defaultValue : (String) apiParam.getOrDefault(key, defaultValue);
}
@ -219,12 +238,15 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
/**
* 这里需要使用平台的私钥生成一个sign需要配置两套公私钥
*
* @param apiConfig 配置
* @param params 请求参数
* @param serviceResult 业务返回结果
* @param apiConfig 配置
* @param params 请求参数
* @param responseSignContent 待签名内容
* @return 返回平台生成的签名
*/
protected String createResponseSign(ApiConfig apiConfig, Map<String, Object> params, String serviceResult) {
protected String createResponseSign(ApiConfig apiConfig, Map<String, Object> 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<T, R> implements ResultExecutor<T, R>
.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

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

@ -6,11 +6,11 @@
<parent>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>sop-service-common</name>

@ -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<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
List<GatewayRouteDefinition> routeDefinitionList = new ArrayList<>(apis.size() + 1);
routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
List<GatewayRouteDefinition> 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<GatewayPredicateDefinition> 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<GatewayPredicateDefinition> 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
*

@ -26,7 +26,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

@ -24,7 +24,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.gitee.sop</groupId>

@ -29,7 +29,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

@ -20,7 +20,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<!-- eureka 服务发现 -->
<dependency>

@ -24,7 +24,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.gitee.sop</groupId>

@ -23,7 +23,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-gateway-common</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->

@ -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);
}
}

@ -25,7 +25,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.12.0-SNAPSHOT</version>
<version>1.12.1-SNAPSHOT</version>
</dependency>
<dependency>

Loading…
Cancel
Save