mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
Merge branch 'master' into registry-nacos
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- easyopen starter -->
|
<!-- easyopen starter -->
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sop-gateway-common</artifactId>
|
<artifactId>sop-gateway-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>sop-gateway-common</name>
|
<name>sop-gateway-common</name>
|
||||||
|
@@ -9,7 +9,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
public class SopConstants {
|
public class SopConstants {
|
||||||
|
|
||||||
private SopConstants() {}
|
private SopConstants() {}
|
||||||
|
|
||||||
public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
|
public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
|
||||||
public static final String UTF8 = "UTF-8";
|
public static final String UTF8 = "UTF-8";
|
||||||
public static final String FORMAT_JSON = "json";
|
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 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;
|
package com.gitee.sop.gatewaycommon.gateway;
|
||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
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
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
public class GatewayContext extends ApiContext {
|
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.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
|
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
|
||||||
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
|
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.exception.ApiException;
|
||||||
|
import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
|
||||||
import com.gitee.sop.gatewaycommon.limit.LimitManager;
|
import com.gitee.sop.gatewaycommon.limit.LimitManager;
|
||||||
import com.gitee.sop.gatewaycommon.limit.LimitType;
|
import com.gitee.sop.gatewaycommon.limit.LimitType;
|
||||||
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
||||||
@@ -35,7 +35,7 @@ public class LimitFilter implements GlobalFilter, Ordered {
|
|||||||
if (!apiConfig.isOpenLimit()) {
|
if (!apiConfig.isOpenLimit()) {
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
ApiParam apiParam = exchange.getAttribute(SopConstants.CACHE_API_PARAM);
|
ApiParam apiParam = GatewayContext.getApiParam(exchange);
|
||||||
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
|
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
|
||||||
if (configLimitDto == null) {
|
if (configLimitDto == null) {
|
||||||
return 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.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
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.exception.ApiException;
|
||||||
|
import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -24,7 +24,7 @@ public class ValidateFilter implements GlobalFilter, Ordered {
|
|||||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||||
// 解析参数
|
// 解析参数
|
||||||
ApiParam param = apiConfig.getGatewayParamBuilder().build(exchange);
|
ApiParam param = apiConfig.getGatewayParamBuilder().build(exchange);
|
||||||
exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, param);
|
GatewayContext.setApiParam(exchange, param);
|
||||||
// 验证操作,这里有负责验证签名参数
|
// 验证操作,这里有负责验证签名参数
|
||||||
Validator validator = apiConfig.getValidator();
|
Validator validator = apiConfig.getValidator();
|
||||||
try {
|
try {
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
package com.gitee.sop.gatewaycommon.gateway.param;
|
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 com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +13,8 @@ import java.util.Map;
|
|||||||
public class GatewayParamBuilder extends BaseParamBuilder<ServerWebExchange> {
|
public class GatewayParamBuilder extends BaseParamBuilder<ServerWebExchange> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> buildRequestParams(ServerWebExchange request) {
|
public Map<String, String> buildRequestParams(ServerWebExchange exchange) {
|
||||||
return request.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
|
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.bean.TargetRoute;
|
||||||
import com.gitee.sop.gatewaycommon.manager.RouteRepository;
|
import com.gitee.sop.gatewaycommon.manager.RouteRepository;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.PredicateArgsEvent;
|
||||||
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
|
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.RouteDefinition;
|
||||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||||
import org.springframework.cloud.gateway.support.ConfigurationUtils;
|
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.context.ApplicationEventPublisherAware;
|
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.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
@@ -39,27 +29,17 @@ import static java.util.Collections.synchronizedMap;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class GatewayRouteRepository implements ApplicationEventPublisherAware,
|
public class GatewayRouteRepository implements ApplicationEventPublisherAware,
|
||||||
RouteDefinitionRepository,
|
RouteDefinitionRepository,
|
||||||
BeanFactoryAware,
|
|
||||||
RouteRepository<GatewayTargetRoute> {
|
RouteRepository<GatewayTargetRoute> {
|
||||||
|
|
||||||
private final Map<String, GatewayTargetRoute> routes = synchronizedMap(new LinkedHashMap<>());
|
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 ApplicationEventPublisher publisher;
|
||||||
|
|
||||||
private BeanFactory beanFactory;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Flux<RouteDefinition> getRouteDefinitions() {
|
public Flux<RouteDefinition> getRouteDefinitions() {
|
||||||
List<RouteDefinition> list = routes.values().parallelStream()
|
List<RouteDefinition> list = routes.values().parallelStream()
|
||||||
.map(TargetRoute::getTargetRouteDefinition)
|
.map(TargetRoute::getTargetRouteDefinition)
|
||||||
|
.filter(routeDefinition -> !routeDefinition.getId().contains("_first.route_"))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return Flux.fromIterable(list);
|
return Flux.fromIterable(list);
|
||||||
}
|
}
|
||||||
@@ -97,7 +77,6 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
|
|||||||
public String add(GatewayTargetRoute targetRoute) {
|
public String add(GatewayTargetRoute targetRoute) {
|
||||||
GatewayRouteDefinition baseRouteDefinition = targetRoute.getRouteDefinition();
|
GatewayRouteDefinition baseRouteDefinition = targetRoute.getRouteDefinition();
|
||||||
routes.put(baseRouteDefinition.getId(), targetRoute);
|
routes.put(baseRouteDefinition.getId(), targetRoute);
|
||||||
this.initPredicateDefinition(targetRoute);
|
|
||||||
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||||
return "success";
|
return "success";
|
||||||
}
|
}
|
||||||
@@ -108,23 +87,6 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
|
|||||||
routes.put(baseRouteDefinition.getId(), targetRoute);
|
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;
|
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.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +45,7 @@ public class GatewayZookeeperRouteManager extends BaseRouteManager<GatewayServic
|
|||||||
routeDefinition.setUri(URI.create(gatewayRouteDefinition.getUri() + "#" + gatewayRouteDefinition.getPath()));
|
routeDefinition.setUri(URI.create(gatewayRouteDefinition.getUri() + "#" + gatewayRouteDefinition.getPath()));
|
||||||
routeDefinition.setOrder(gatewayRouteDefinition.getOrder());
|
routeDefinition.setOrder(gatewayRouteDefinition.getOrder());
|
||||||
List<FilterDefinition> filterDefinitionList = new ArrayList<>(gatewayRouteDefinition.getFilters().size());
|
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()) {
|
for (GatewayFilterDefinition filter : gatewayRouteDefinition.getFilters()) {
|
||||||
FilterDefinition filterDefinition = new FilterDefinition();
|
FilterDefinition filterDefinition = new FilterDefinition();
|
||||||
BeanUtils.copyProperties(filter, filterDefinition);
|
BeanUtils.copyProperties(filter, filterDefinition);
|
||||||
@@ -56,10 +57,28 @@ public class GatewayZookeeperRouteManager extends BaseRouteManager<GatewayServic
|
|||||||
BeanUtils.copyProperties(predicate, predicateDefinition);
|
BeanUtils.copyProperties(predicate, predicateDefinition);
|
||||||
predicateDefinitionList.add(predicateDefinition);
|
predicateDefinitionList.add(predicateDefinition);
|
||||||
}
|
}
|
||||||
|
this.addPredicate(predicateDefinitionList, "NameVersion", gatewayRouteDefinition.getId());
|
||||||
|
this.addPredicate(predicateDefinitionList, "ReadBody", "");
|
||||||
routeDefinition.setFilters(filterDefinitionList);
|
routeDefinition.setFilters(filterDefinitionList);
|
||||||
routeDefinition.setPredicates(predicateDefinitionList);
|
routeDefinition.setPredicates(predicateDefinitionList);
|
||||||
return new GatewayTargetRoute(serviceRouteInfo, gatewayRouteDefinition, routeDefinition);
|
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;
|
package com.gitee.sop.gatewaycommon.gateway.route;
|
||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
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.param.ParamNames;
|
||||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
|
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
@@ -15,17 +16,15 @@ import java.util.Map;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 此断言决定执行哪个路由
|
||||||
|
*
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFactory<NameVersionRoutePredicateFactory.Config> {
|
public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFactory<NameVersionRoutePredicateFactory.Config> {
|
||||||
|
|
||||||
public static final String PARAM_KEY = "param";
|
private static final String PARAM_KEY = "param";
|
||||||
public static final String REGEXP_KEY = "regexp";
|
private 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;
|
|
||||||
|
|
||||||
|
|
||||||
public NameVersionRoutePredicateFactory() {
|
public NameVersionRoutePredicateFactory() {
|
||||||
super(Config.class);
|
super(Config.class);
|
||||||
@@ -37,7 +36,7 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* config.param为nameVersion
|
* config.param为nameVersion,即路由id
|
||||||
*
|
*
|
||||||
* @param config
|
* @param config
|
||||||
* @return 返回断言
|
* @return 返回断言
|
||||||
@@ -46,21 +45,14 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
|
|||||||
public Predicate<ServerWebExchange> apply(Config config) {
|
public Predicate<ServerWebExchange> apply(Config config) {
|
||||||
|
|
||||||
return exchange -> {
|
return exchange -> {
|
||||||
String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
|
Map<String, String> params = GatewayContext.getRequestParams(exchange);
|
||||||
if (cachedBody == null) {
|
if (CollectionUtils.isEmpty(params)) {
|
||||||
return false;
|
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 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, "");
|
String version = params.getOrDefault(ParamNames.VERSION_NAME, "");
|
||||||
boolean match = (name + version).equals(nameVersion);
|
return (name + version).equals(nameVersion);
|
||||||
return match;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,19 +1,145 @@
|
|||||||
package com.gitee.sop.gatewaycommon.gateway.route;
|
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.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.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import static org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter.CACHED_REQUEST_BODY_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取form表单插件,使用方式:
|
* 获取请求参数插件,兼容get,post,使用方式:
|
||||||
* @Bean
|
* @Bean
|
||||||
* ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() {
|
* ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() {
|
||||||
* return new ReadBodyRoutePredicateFactory();
|
* return new ReadBodyRoutePredicateFactory();
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
* @see org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory
|
||||||
|
* 详见:https://blog.51cto.com/thinklili/2329184
|
||||||
* @author tanghc
|
* @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
|
@Override
|
||||||
public Config newConfig() {
|
public Config newConfig() {
|
||||||
@@ -22,4 +148,51 @@ public class ReadBodyRoutePredicateFactory extends ReadBodyPredicateFactory {
|
|||||||
config.setPredicate(Objects::nonNull);
|
config.setPredicate(Objects::nonNull);
|
||||||
return config;
|
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 = newRouteConfig();
|
||||||
routeConfig.setRouteId(routeId);
|
routeConfig.setRouteId(routeId);
|
||||||
routeConfigMap.put(routeId, routeConfig);
|
routeConfigMap.put(routeId, routeConfig);
|
||||||
} else {
|
|
||||||
MyBeanUtil.copyPropertiesIgnoreNull(res, routeConfig);
|
|
||||||
}
|
}
|
||||||
|
MyBeanUtil.copyPropertiesIgnoreNull(res, routeConfig);
|
||||||
routeConfig.initRateLimiter();
|
routeConfig.initRateLimiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,5 +42,8 @@ public class ParamNames {
|
|||||||
/** */
|
/** */
|
||||||
public static String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
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) {
|
protected ApiInfo getApiInfo(T request) {
|
||||||
Map<String, Object> params = this.getApiParam(request);
|
Map<String, Object> params = this.getApiParam(request);
|
||||||
String name = this.getParamValue(params, ParamNames.API_NAME, "method.unknown");
|
String name = this.getParamValue(params, ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD);
|
||||||
String version = this.getParamValue(params, ParamNames.VERSION_NAME, "version.unknown");
|
String version = this.getParamValue(params, ParamNames.VERSION_NAME, SopConstants.UNKNOWN_VERSION);
|
||||||
|
|
||||||
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(name + version);
|
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(name + version);
|
||||||
|
|
||||||
String serviceId = Optional.ofNullable(targetRoute)
|
String serviceId = Optional.ofNullable(targetRoute)
|
||||||
.flatMap(route -> Optional.ofNullable(route.getServiceRouteInfo()))
|
.flatMap(route -> Optional.ofNullable(route.getServiceRouteInfo()))
|
||||||
.map(BaseServiceRouteInfo::getServiceId)
|
.map(BaseServiceRouteInfo::getServiceId)
|
||||||
.orElse("serviceId.unknown");
|
.orElse(SopConstants.UNKNOWN_SERVICE);
|
||||||
|
|
||||||
BaseRouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute)
|
BaseRouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute)
|
||||||
.map(route -> route.getRouteDefinition())
|
.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) {
|
public String merge(T exchange, JSONObject responseData) {
|
||||||
JSONObject finalData = new JSONObject();
|
JSONObject finalData = new JSONObject(true);
|
||||||
Map<String, Object> params = this.getApiParam(exchange);
|
Map<String, Object> params = this.getApiParam(exchange);
|
||||||
String name = this.getParamValue(params, ParamNames.API_NAME, ERROR_METHOD);
|
String name = this.getParamValue(params, ParamNames.API_NAME, ERROR_METHOD);
|
||||||
ApiConfig apiConfig = ApiConfig.getInstance();
|
ApiConfig apiConfig = ApiConfig.getInstance();
|
||||||
@@ -200,9 +200,10 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
|
|||||||
if (apiConfig.isShowReturnSign() && !CollectionUtils.isEmpty(params)) {
|
if (apiConfig.isShowReturnSign() && !CollectionUtils.isEmpty(params)) {
|
||||||
// 添加try...catch,生成sign出错不影响结果正常返回
|
// 添加try...catch,生成sign出错不影响结果正常返回
|
||||||
try {
|
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)) {
|
if (StringUtils.hasLength(sign)) {
|
||||||
finalData.put(ParamNames.SIGN_NAME, sign);
|
finalData.put(ParamNames.RESPONSE_SIGN_NAME, sign);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("生成平台签名失败, params: {}, serviceResult:{}", JSON.toJSONString(params), responseData, 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();
|
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) {
|
protected String getParamValue(Map<String, Object> apiParam, String key, String defaultValue) {
|
||||||
return CollectionUtils.isEmpty(apiParam) ? defaultValue : (String) apiParam.getOrDefault(key, 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,需要配置两套公私钥。
|
* 这里需要使用平台的私钥生成一个sign,需要配置两套公私钥。
|
||||||
*
|
*
|
||||||
* @param apiConfig 配置
|
* @param apiConfig 配置
|
||||||
* @param params 请求参数
|
* @param params 请求参数
|
||||||
* @param serviceResult 业务返回结果
|
* @param responseSignContent 待签名内容
|
||||||
* @return 返回平台生成的签名
|
* @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();
|
IsvManager isvManager = apiConfig.getIsvManager();
|
||||||
// 根据appId获取秘钥
|
// 根据appId获取秘钥
|
||||||
String appKey = this.getParamValue(params, ParamNames.APP_KEY_NAME, "");
|
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)
|
.map(String::valueOf)
|
||||||
.orElse(SopConstants.UTF8);
|
.orElse(SopConstants.UTF8);
|
||||||
String signType = getParamValue(params, ParamNames.SIGN_TYPE_NAME, AlipayConstants.SIGN_TYPE_RSA2);
|
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
|
@Getter
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
@@ -6,11 +6,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>sop-service-common</name>
|
<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.ServiceApiInfo;
|
||||||
import com.gitee.sop.servercommon.bean.ServiceConstants;
|
import com.gitee.sop.servercommon.bean.ServiceConstants;
|
||||||
import com.gitee.sop.servercommon.bean.ZookeeperTool;
|
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.GatewayRouteDefinition;
|
||||||
import com.gitee.sop.servercommon.route.ServiceRouteInfo;
|
import com.gitee.sop.servercommon.route.ServiceRouteInfo;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -16,7 +15,6 @@ import org.springframework.core.env.Environment;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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 SOP_SERVICE_ROUTE_PATH = ServiceConstants.SOP_SERVICE_ROUTE_PATH;
|
||||||
public static final String PATH_START_CHAR = "/";
|
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 final String routeRootPath = SOP_SERVICE_ROUTE_PATH;
|
||||||
|
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
@@ -99,8 +89,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
*/
|
*/
|
||||||
protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
|
protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
|
||||||
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
|
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
|
||||||
List<GatewayRouteDefinition> routeDefinitionList = new ArrayList<>(apis.size() + 1);
|
List<GatewayRouteDefinition> routeDefinitionList = new ArrayList<>(apis.size());
|
||||||
routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
|
|
||||||
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
|
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
|
||||||
GatewayRouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
|
GatewayRouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
|
||||||
routeDefinitionList.add(gatewayRouteDefinition);
|
routeDefinitionList.add(gatewayRouteDefinition);
|
||||||
@@ -118,32 +107,12 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
return serviceRouteInfo;
|
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) {
|
protected GatewayRouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
|
||||||
GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
|
GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
|
||||||
// 唯一id规则:接口名 + 版本号
|
// 唯一id规则:接口名 + 版本号
|
||||||
BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
|
BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
|
||||||
gatewayRouteDefinition.setId(apiMeta.fetchNameVersion());
|
gatewayRouteDefinition.setId(apiMeta.fetchNameVersion());
|
||||||
gatewayRouteDefinition.setFilters(Collections.emptyList());
|
gatewayRouteDefinition.setFilters(Collections.emptyList());
|
||||||
List<GatewayPredicateDefinition> predicates = Arrays.asList(this.buildNameVersionPredicateDefinition(apiMeta));
|
|
||||||
gatewayRouteDefinition.setPredicates(predicates);
|
|
||||||
String uri = this.buildUri(serviceApiInfo, apiMeta);
|
String uri = this.buildUri(serviceApiInfo, apiMeta);
|
||||||
String path = this.buildServletPath(serviceApiInfo, apiMeta);
|
String path = this.buildServletPath(serviceApiInfo, apiMeta);
|
||||||
gatewayRouteDefinition.setUri(uri);
|
gatewayRouteDefinition.setUri(uri);
|
||||||
@@ -166,10 +135,6 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
return servletPath;
|
return servletPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
|
|
||||||
return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传接口信息到zookeeper
|
* 上传接口信息到zookeeper
|
||||||
*
|
*
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- eureka 服务发现 -->
|
<!-- eureka 服务发现 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-gateway-common</artifactId>
|
<artifactId>sop-gateway-common</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->
|
<!-- ↓↓↓ 使用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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
@@ -18,14 +21,15 @@ public class RedirectController {
|
|||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
@RequestMapping("/{method}/{version}/")
|
@RequestMapping("/{method}/{version}/")
|
||||||
public String redirect(
|
public void redirect(
|
||||||
@PathVariable("method") String method
|
@PathVariable("method") String method
|
||||||
, @PathVariable("version") String version
|
, @PathVariable("version") String version
|
||||||
, HttpServletRequest request
|
, HttpServletRequest request
|
||||||
) {
|
, HttpServletResponse response
|
||||||
|
) throws ServletException, IOException {
|
||||||
request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method);
|
request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method);
|
||||||
request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version);
|
request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version);
|
||||||
return "forward:" + path;
|
request.getRequestDispatcher(path).forward(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.12.0-SNAPSHOT</version>
|
<version>1.12.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
Reference in New Issue
Block a user