diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index fe6b0cc..e199f7c 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -12,13 +12,13 @@ com.fizzgate fizz-bootstrap - 2.3.3-beta6 + 2.3.4-beta1 1.8 5.2.18.RELEASE Dragonfruit-SR3 - Dysprosium-SR24 + Dysprosium-SR25 5.3.7.RELEASE 4.1.70.Final 4.4.14 diff --git a/fizz-bootstrap/src/main/resources/application.yml b/fizz-bootstrap/src/main/resources/application.yml index 1aa614c..f82b807 100644 --- a/fizz-bootstrap/src/main/resources/application.yml +++ b/fizz-bootstrap/src/main/resources/application.yml @@ -115,7 +115,7 @@ fizz: code-field: "msgCode" message-field: "message" - api.pairing: + dedicated-line: server: enable: false client: diff --git a/fizz-common/pom.xml b/fizz-common/pom.xml index 056ddc1..647de04 100644 --- a/fizz-common/pom.xml +++ b/fizz-common/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.3-beta6 + 2.3.4-beta1 ../pom.xml 4.0.0 diff --git a/fizz-core/pom.xml b/fizz-core/pom.xml index 39980eb..2444eca 100644 --- a/fizz-core/pom.xml +++ b/fizz-core/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.3-beta6 + 2.3.4-beta1 ../pom.xml 4.0.0 diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSet.java b/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSet.java deleted file mode 100644 index c62d820..0000000 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSet.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2020 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package we.api.pairing; - -import we.util.JacksonUtils; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -/** - * @author hongqiaowei - */ - -public class ApiPairingDocSet { - - public static final int DELETED = 1; - - public int isDeleted = 0; - - public long id; - - public String name; - - public String description; - - public List docs = Collections.emptyList(); - - public Set appIds = Collections.emptySet(); - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ApiPairingDocSet that = (ApiPairingDocSet) o; - return id == that.id; - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public String toString() { - return JacksonUtils.writeValueAsString(this); - } -} diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSetService.java b/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSetService.java deleted file mode 100644 index 2fe5b24..0000000 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingDocSetService.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2020 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package we.api.pairing; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.redis.core.ReactiveStringRedisTemplate; -import org.springframework.http.HttpMethod; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import we.config.AggregateRedisConfig; -import we.config.SystemConfig; -import we.plugin.auth.ApiConfig; -import we.util.JacksonUtils; -import we.util.Result; -import we.util.UrlTransformUtils; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import java.util.*; - -/** - * @author hongqiaowei - */ - -@ConditionalOnProperty(name = SystemConfig.FIZZ_API_PAIRING_SERVER_ENABLE, havingValue = "true") -@Service -public class ApiPairingDocSetService { - - private static final Logger log = LoggerFactory.getLogger(ApiPairingDocSetService.class); - - private Map docSetMap = new HashMap<>(64); - - private Map> appDocSetMap = new HashMap<>(64); - - private Map> serviceExistsInDocSetMap = new HashMap<>(64); - - private Map>> methodPathExistsInDocSetMap = new HashMap<>(); - - @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) - private ReactiveStringRedisTemplate rt; - - @PostConstruct - public void init() throws Throwable { - Result result = initApiPairingDocSet(); - if (result.code == Result.FAIL) { - throw new RuntimeException(result.msg, result.t); - } - result = lsnApiPairingDocSetChange(); - if (result.code == Result.FAIL) { - throw new RuntimeException(result.msg, result.t); - } - } - - private Result initApiPairingDocSet() { - Result result = Result.succ(); - Flux> resources = rt.opsForHash().entries("fizz_api_pairing_doc"); - resources.collectList() - .defaultIfEmpty(Collections.emptyList()) - .flatMap( - es -> { - if (!es.isEmpty()) { - String json = null; - try { - for (Map.Entry e : es) { - json = (String) e.getValue(); - ApiPairingDocSet docSet = JacksonUtils.readValue(json, ApiPairingDocSet.class); - updateDocSetDataStruct(docSet); - } - } catch (Throwable t) { - result.code = Result.FAIL; - result.msg = "init api pairing doc set error, doc set: " + json; - result.t = t; - } - } else { - log.info("no api pairing doc set"); - } - return Mono.empty(); - } - ) - .onErrorReturn( - throwable -> { - result.code = Result.FAIL; - result.msg = "init api pairing doc set error"; - result.t = throwable; - return true; - }, - result - ) - .block(); - return result; - } - - private Result lsnApiPairingDocSetChange() { - Result result = Result.succ(); - String channel = "fizz_api_pairing_doc_channel"; - rt.listenToChannel(channel) - .doOnError( - t -> { - result.code = Result.FAIL; - result.msg = "lsn error, channel: " + channel; - result.t = t; - log.error("lsn channel {} error", channel, t); - } - ) - .doOnSubscribe( - s -> { - log.info("success to lsn on {}", channel); - } - ) - .doOnNext( - msg -> { - String message = msg.getMessage(); - try { - ApiPairingDocSet docSet = JacksonUtils.readValue(message, ApiPairingDocSet.class); - updateDocSetDataStruct(docSet); - } catch (Throwable t) { - log.error("update api pairing doc set error, {}", message, t); - } - } - ) - .subscribe(); - return result; - } - - private void updateDocSetDataStruct(ApiPairingDocSet docSet) { - if (docSet.isDeleted == ApiPairingDocSet.DELETED) { - docSetMap.remove(docSet.id); - - for (String appId : docSet.appIds) { - Set dss = appDocSetMap.get(appId); - if (dss != null) { - dss.remove(docSet); - if (dss.isEmpty()) { - appDocSetMap.remove(appId); - } - } - } - - for (ApiPairingDoc doc : docSet.docs) { - Set dss = serviceExistsInDocSetMap.get(doc.service); - if (dss != null) { - dss.remove(docSet); - if (dss.isEmpty()) { - serviceExistsInDocSetMap.remove(doc.service); - } - } - for (Api api : doc.apis) { - Map> pathDocSetMap = methodPathExistsInDocSetMap.get(api.method); - if (pathDocSetMap != null) { - dss = pathDocSetMap.get(api.path); - if (dss != null) { - dss.remove(docSet); - if (dss.isEmpty()) { - pathDocSetMap.remove(api.path); - if (pathDocSetMap.isEmpty()) { - methodPathExistsInDocSetMap.remove(api.method); - } - } - } - } - } - } - - log.info("delete doc set: {}", docSet); - - } else { - docSetMap.put(docSet.id, docSet); - docSet.appIds.forEach( - appId -> { - Set dss = appDocSetMap.computeIfAbsent(appId, k -> new HashSet<>()); - dss.add(docSet); - } - ); - docSet.docs.forEach( - doc -> { - Set dss = serviceExistsInDocSetMap.computeIfAbsent(doc.service, k -> new HashSet<>()); - dss.add(docSet); - for (Api api : doc.apis) { - Map> pathDocSetMap = methodPathExistsInDocSetMap.computeIfAbsent(api.method, k -> new HashMap<>()); - dss = pathDocSetMap.computeIfAbsent(api.path, k -> new HashSet<>()); - dss.add(docSet); - } - } - ); - log.info("update doc set: {}", docSet); - } - } - - public Map getDocSetMap() { - return docSetMap; - } - - public ApiPairingDocSet get(long id) { - return docSetMap.get(id); - } - - public Map> getAppDocSetMap() { - return appDocSetMap; - } - - public Map> getServiceExistsInDocSetMap() { - return serviceExistsInDocSetMap; - } - - public Map>> getMethodPathExistsInDocSetMap() { - return methodPathExistsInDocSetMap; - } - - public boolean existsDocSetMatch(String appId, HttpMethod method, String service, String path) { - Set appDocSets = appDocSetMap.get(appId); - if (appDocSets == null) { - return false; - } - Set serviceDocSets = serviceExistsInDocSetMap.get(service); - if (serviceDocSets == null) { - return false; - } - - Set s = new HashSet<>(); - Map> pathDocSetMap = methodPathExistsInDocSetMap.get(method); - if (pathDocSetMap != null) { - checkPathPattern(pathDocSetMap, path, s); - } - pathDocSetMap = methodPathExistsInDocSetMap.get(ApiConfig.ALL_METHOD); - if (pathDocSetMap != null) { - checkPathPattern(pathDocSetMap, path, s); - } - if (s.isEmpty()) { - return false; - } - - s.retainAll(appDocSets); - if (s.isEmpty()) { - return false; - } - s.retainAll(serviceDocSets); - if (s.isEmpty()) { - return false; - } - - return true; - } - - private void checkPathPattern(Map> pathDocSetMap, String path, Set result) { - Set>> entries = pathDocSetMap.entrySet(); - for (Map.Entry> entry : entries) { - String pathPattern = entry.getKey(); - if (pathPattern.equals(path) || UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path)) { - result.addAll(entry.getValue()); - } - } - } -} diff --git a/fizz-core/src/main/java/we/api/pairing/AppApiPairingDocSet.java b/fizz-core/src/main/java/we/api/pairing/AppApiPairingDocSet.java deleted file mode 100644 index dda159c..0000000 --- a/fizz-core/src/main/java/we/api/pairing/AppApiPairingDocSet.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2020 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package we.api.pairing; - -import we.util.JacksonUtils; - -import java.util.Collections; -import java.util.Set; - -/** - * @author hongqiaowei - */ - -public class AppApiPairingDocSet { - - public long id; - - public String name; - - public String description; - - public Set services; - - public boolean enabled; - - @Override - public String toString() { - return JacksonUtils.writeValueAsString(this); - } -} diff --git a/fizz-core/src/main/java/we/config/FizzMangerConfig.java b/fizz-core/src/main/java/we/config/FizzMangerConfig.java index 50467b2..3df38a6 100644 --- a/fizz-core/src/main/java/we/config/FizzMangerConfig.java +++ b/fizz-core/src/main/java/we/config/FizzMangerConfig.java @@ -42,6 +42,8 @@ public class FizzMangerConfig { public String managerUrl; + public String pairPath = "/fizz-manager/dedicated-line/pair"; + public String docPathPrefix = "/fizz-manager/open-doc/open-doc-show/pair"; @PostConstruct diff --git a/fizz-core/src/main/java/we/config/RefreshLocalCacheConfig.java b/fizz-core/src/main/java/we/config/RefreshLocalCacheConfig.java index 80a37ca..0c3559d 100644 --- a/fizz-core/src/main/java/we/config/RefreshLocalCacheConfig.java +++ b/fizz-core/src/main/java/we/config/RefreshLocalCacheConfig.java @@ -22,7 +22,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Scheduled; import we.fizz.ConfigLoader; import we.plugin.auth.ApiConfigService; -import we.plugin.auth.ApiConifg2appsService; +import we.plugin.auth.ApiConfig2appsService; import we.plugin.auth.AppService; import we.plugin.auth.GatewayGroupService; import we.proxy.RpcInstanceService; @@ -33,7 +33,7 @@ import javax.annotation.Resource; /** * refresh config local cache config * @see ApiConfigService#refreshLocalCache() refresh api config local cache - * @see ApiConifg2appsService#refreshLocalCache() refresh api config to apps local cache + * @see ApiConfig2appsService#refreshLocalCache() refresh api config to apps local cache * @see ConfigLoader#refreshLocalCache() refresh aggregate config local cache * @see GatewayGroupService#refreshLocalCache() refresh gateway group local cache * @see AppService#refreshLocalCache() refresh app local cache @@ -56,7 +56,7 @@ public class RefreshLocalCacheConfig { private ApiConfigService apiConfigService; @Resource - private ApiConifg2appsService apiConifg2appsService; + private ApiConfig2appsService apiConfig2AppsService; @Resource private GatewayGroupService gatewayGroupService; @@ -88,7 +88,7 @@ public class RefreshLocalCacheConfig { if (refreshLocalCacheConfigProperties.isApiConfig2AppsCacheRefreshEnabled()) { LOGGER.debug("refresh api config to apps local cache"); try { - apiConifg2appsService.refreshLocalCache(); + apiConfig2AppsService.refreshLocalCache(); } catch (Throwable t) { LOGGER.warn("refresh api config to apps local cache exception", t); } diff --git a/fizz-core/src/main/java/we/config/SystemConfig.java b/fizz-core/src/main/java/we/config/SystemConfig.java index 3bc71aa..cb38349 100644 --- a/fizz-core/src/main/java/we/config/SystemConfig.java +++ b/fizz-core/src/main/java/we/config/SystemConfig.java @@ -42,22 +42,26 @@ public class SystemConfig { private static final Logger log = LoggerFactory.getLogger(SystemConfig.class); - public static final String DEFAULT_GATEWAY_PREFIX = "/proxy"; - public static final String DEFAULT_GATEWAY_TEST_PREFIX = "/_proxytest"; - public static final String DEFAULT_GATEWAY_TEST = "_proxytest"; - public static final String DEFAULT_GATEWAY_TEST_PREFIX0 = "/_proxytest/"; + public static final String DEFAULT_GATEWAY_PREFIX = "/proxy"; + public static final String DEFAULT_GATEWAY_TEST_PREFIX = "/_proxytest"; + public static final String DEFAULT_GATEWAY_TEST = "_proxytest"; + public static final String DEFAULT_GATEWAY_TEST_PREFIX0 = "/_proxytest/"; - public static boolean FIZZ_ERR_RESP_HTTP_STATUS_ENABLE = true; - public static String FIZZ_ERR_RESP_CODE_FIELD = "msgCode"; - public static String FIZZ_ERR_RESP_MSG_FIELD = "message"; + public static boolean FIZZ_ERR_RESP_HTTP_STATUS_ENABLE = true; + public static String FIZZ_ERR_RESP_CODE_FIELD = "msgCode"; + public static String FIZZ_ERR_RESP_MSG_FIELD = "message"; - public static final String FIZZ_APP_ID = "fizz-appid"; - public static final String FIZZ_SIGN = "fizz-sign"; - public static final String FIZZ_TIMESTAMP = "fizz-ts"; + public static final String FIZZ_DL_ID = "fizz-dl-id"; + public static final String FIZZ_DL_SIGN = "fizz-dl-sign"; + public static final String FIZZ_DL_TS = "fizz-dl-ts"; - public static final String FIZZ_API_PAIRING_SERVER_ENABLE = "fizz.api.pairing.server.enable"; - public static final String FIZZ_API_PAIRING_CLIENT_PREFIX = "fizz.api.pairing.client"; - public static final String FIZZ_API_PAIRING_CLIENT_ENABLE = "fizz.api.pairing.client.enable"; + public static final String FIZZ_APP_ID = "fizz-appid"; + public static final String FIZZ_SIGN = "fizz-sign"; + public static final String FIZZ_TIMESTAMP = "fizz-ts"; + + public static final String FIZZ_DEDICATED_LINE_SERVER_ENABLE = "fizz.dedicated-line.server.enable"; + public static final String FIZZ_DEDICATED_LINE_CLIENT_PREFIX = "fizz.dedicated-line.client"; + public static final String FIZZ_DEDICATED_LINE_CLIENT_ENABLE = "fizz.dedicated-line.client.enable"; private String gatewayPrefix = DEFAULT_GATEWAY_PREFIX; @@ -98,32 +102,32 @@ public class SystemConfig { - @Value("${fizz.api.pairing.client.request.timeliness:300}") - private int fizzApiPairingRequestTimeliness = 300; // unit: sec + @Value("${fizz.dedicated-line.client.request.timeliness:300}") + private int fizzDedicatedLineClientRequestTimeliness = 300; // unit: sec - @Value("${fizz.api.pairing.client.request.timeout:0}") - private int fizzApiPairingRequestTimeout = 0; // mills + @Value("${fizz.dedicated-line.client.request.timeout:0}") + private int fizzDedicatedLineClientRequestTimeout = 0; // mills - @Value("${fizz.api.pairing.client.request.retry-count:0}") - private int fizzApiPairingRequestRetryCount = 0; + @Value("${fizz.dedicated-line.client.request.retry-count:0}") + private int fizzDedicatedLineClientRequestRetryCount = 0; - @Value("${fizz.api.pairing.client.request.retry-interval:0}") - private int fizzApiPairingRequestRetryInterval = 0; // mills + @Value("${fizz.dedicated-line.client.request.retry-interval:0}") + private int fizzDedicatedLineClientRequestRetryInterval = 0; // mills - public int fizzApiPairingRequestTimeout() { - return fizzApiPairingRequestTimeout; + public int fizzDedicatedLineClientRequestTimeout() { + return fizzDedicatedLineClientRequestTimeout; } - public int fizzApiPairingRequestRetryCount() { - return fizzApiPairingRequestRetryCount; + public int fizzDedicatedLineClientRequestRetryCount() { + return fizzDedicatedLineClientRequestRetryCount; } - public int fizzApiPairingRequestRetryInterval() { - return fizzApiPairingRequestRetryInterval; + public int fizzDedicatedLineClientRequestRetryInterval() { + return fizzDedicatedLineClientRequestRetryInterval; } - public int fizzApiPairingRequestTimeliness() { - return fizzApiPairingRequestTimeliness; + public int fizzDedicatedLineClientRequestTimeliness() { + return fizzDedicatedLineClientRequestTimeliness; } diff --git a/fizz-core/src/main/java/we/controller/CacheCheckController.java b/fizz-core/src/main/java/we/controller/CacheCheckController.java index d5e7ce9..766d78b 100644 --- a/fizz-core/src/main/java/we/controller/CacheCheckController.java +++ b/fizz-core/src/main/java/we/controller/CacheCheckController.java @@ -23,8 +23,8 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import we.global_resource.GlobalResourceService; +import we.plugin.auth.ApiConfig2appsService; import we.plugin.auth.ApiConfigService; -import we.plugin.auth.ApiConifg2appsService; import we.plugin.auth.AppService; import we.plugin.auth.GatewayGroupService; import we.stats.ratelimit.ResourceRateLimitConfigService; @@ -53,7 +53,7 @@ public class CacheCheckController { private ResourceRateLimitConfigService resourceRateLimitConfigService; @Resource - private ApiConifg2appsService apiConifg2appsService; + private ApiConfig2appsService apiConfig2AppsService; @Resource private GlobalResourceService globalResourceService; @@ -74,7 +74,7 @@ public class CacheCheckController { } @GetMapping("/serviceConfigs") - public Mono apiConfigs(ServerWebExchange exchange) { + public Mono serviceConfigs(ServerWebExchange exchange) { return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.serviceConfigMap)); } @@ -85,11 +85,11 @@ public class CacheCheckController { @GetMapping("/apiConfig2appsConfigs") public Mono apiConfig2appsConfigs(ServerWebExchange exchange) { - return Mono.just(JacksonUtils.writeValueAsString(apiConifg2appsService.getApiConfig2appsMap())); + return Mono.just(JacksonUtils.writeValueAsString(apiConfig2AppsService.getApiConfig2appsMap())); } @GetMapping("/globalResources") - public Mono dicts(ServerWebExchange exchange) { + public Mono globalResources(ServerWebExchange exchange) { return Mono.just(JacksonUtils.writeValueAsString(globalResourceService.getResourceMap())); } } diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingDoc.java b/fizz-core/src/main/java/we/dedicated_line/ApiDoc.java similarity index 80% rename from fizz-core/src/main/java/we/api/pairing/ApiPairingDoc.java rename to fizz-core/src/main/java/we/dedicated_line/ApiDoc.java index c05a753..9630bc5 100644 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingDoc.java +++ b/fizz-core/src/main/java/we/dedicated_line/ApiDoc.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import we.util.JacksonUtils; @@ -26,11 +26,15 @@ import java.util.List; * @author hongqiaowei */ -public class ApiPairingDoc { +public class ApiDoc { public String service; - public List apis = Collections.emptyList(); + public List methodAndPaths = Collections.emptyList(); + + public void setApis(List methodAndPaths) { + this.methodAndPaths = methodAndPaths; + } @Override public String toString() { diff --git a/fizz-core/src/main/java/we/dedicated_line/DedicatedLine.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLine.java new file mode 100644 index 0000000..2fdb785 --- /dev/null +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLine.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2020 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package we.dedicated_line; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.CollectionUtils; +import we.util.JacksonUtils; + +import java.util.*; + +/** + * @author hongqiaowei + */ + +public class DedicatedLine { + + public boolean isDeleted = false; + + public String pairCodeId; + + public String secretKey; + + public String customConfig; + + public List apiDocs = Collections.emptyList(); + + @JsonIgnore + public Map> + > + apiDocMap = Collections.emptyMap(); + + public Set servicesWithoutApiDocs = Collections.emptySet(); + + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + + public void setDocs(List docs) { + apiDocs = docs; + if (CollectionUtils.isEmpty(apiDocs)) { + apiDocMap = Collections.emptyMap(); + } else { + apiDocMap = new HashMap<>(); + for (ApiDoc apiDoc : apiDocs) { + Map> methodPathsMap = apiDocMap.computeIfAbsent(apiDoc.service, k -> new HashMap<>()); + for (MethodAndPath methodAndPath : apiDoc.methodAndPaths) { + Set paths = methodPathsMap.computeIfAbsent(methodAndPath.method, k -> new HashSet<>()); + paths.add(methodAndPath.path); + } + } + } + } + + public void setServices(Set services) { + servicesWithoutApiDocs = services; + } + + @Override + public String toString() { + return JacksonUtils.writeValueAsString(this); + } +} diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingController.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineController.java similarity index 65% rename from fizz-core/src/main/java/we/api/pairing/ApiPairingController.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineController.java index cf44624..8a31391 100644 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingController.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineController.java @@ -15,15 +15,13 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.bind.annotation.GetMapping; @@ -36,37 +34,31 @@ import reactor.core.publisher.Mono; import we.config.FizzMangerConfig; import we.config.SystemConfig; import we.flume.clients.log4j2appender.LogService; -import we.plugin.auth.App; -import we.plugin.auth.AppService; import we.proxy.FizzWebClient; -import we.util.*; +import we.util.DateTimeUtils; +import we.util.Result; +import we.util.ThreadContext; +import we.util.WebUtils; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; /** * @author hongqiaowei */ -@ConditionalOnProperty(name = SystemConfig.FIZZ_API_PAIRING_SERVER_ENABLE, havingValue = "true") +@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_SERVER_ENABLE, havingValue = "true") @RestController -@RequestMapping(SystemConfig.DEFAULT_GATEWAY_PREFIX + "/_fizz-pairing") -public class ApiPairingController { +@RequestMapping(SystemConfig.DEFAULT_GATEWAY_PREFIX + "/_fizz-dedicated-line") +public class DedicatedLineController { - private static final Logger log = LoggerFactory.getLogger(ApiPairingController.class); + private static final Logger log = LoggerFactory.getLogger(DedicatedLineController.class); @Resource private SystemConfig systemConfig; @Resource - private AppService appService; - - @Resource - private ApiPairingDocSetService apiPairingDocSetService; + private DedicatedLineService dedicatedLineService; @Resource private FizzMangerConfig fizzMangerConfig; @@ -75,23 +67,19 @@ public class ApiPairingController { private FizzWebClient fizzWebClient; private Result auth(ServerWebExchange exchange) { - String appId = WebUtils.getAppId(exchange); - if (appId == null) { - return Result.fail("no app info in request"); - } - App app = appService.getApp(appId); - if (app == null) { - return Result.fail(appId + " not exists"); + String dedicatedLineId = WebUtils.getDedicatedLineId(exchange); + if (dedicatedLineId == null) { + return Result.fail("no dedicated line id in request"); } - String timestamp = WebUtils.getTimestamp(exchange); + String timestamp = WebUtils.getDedicatedLineTimestamp(exchange); if (timestamp == null) { return Result.fail("no timestamp in request"); } try { long ts = Long.parseLong(timestamp); LocalDateTime now = LocalDateTime.now(); - long timeliness = systemConfig.fizzApiPairingRequestTimeliness(); + long timeliness = systemConfig.fizzDedicatedLineClientRequestTimeliness(); long start = DateTimeUtils.toMillis(now.minusSeconds(timeliness)); long end = DateTimeUtils.toMillis(now.plusSeconds (timeliness)); if (start <= ts && ts <= end) { @@ -100,17 +88,19 @@ public class ApiPairingController { return Result.fail("request timestamp invalid"); } } catch (NumberFormatException e) { - return Result.fail("request timestamp invalid"); + return Result.fail("request timestamp format invalid"); } - String sign = WebUtils.getSign(exchange); + String sign = WebUtils.getDedicatedLineSign(exchange); if (sign == null) { return Result.fail("no sign in request"); } - boolean equals = ApiPairingUtils.checkSign(appId, timestamp, app.secretkey, sign); + + String pairCodeSecretKey = dedicatedLineService.getPairCodeSecretKey(dedicatedLineId); + boolean equals = DedicatedLineUtils.checkSign(dedicatedLineId, timestamp, pairCodeSecretKey, sign); if (!equals) { String traceId = WebUtils.getTraceId(exchange); - log.warn("{} request authority: app {}, timestamp {}, sign {} invalid", traceId, appId, timestamp, sign, LogService.BIZ_ID, traceId); + log.warn("{} request authority: dedicated line id {}, timestamp {}, sign {} invalid", traceId, dedicatedLineId, timestamp, sign, LogService.BIZ_ID, traceId); return Result.fail("request sign invalid"); } return Result.succ(); @@ -118,37 +108,33 @@ public class ApiPairingController { @GetMapping("/pair") public Mono pair(ServerWebExchange exchange) { + ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); - Result auth = auth(exchange); - if (auth.code == Result.SUCC) { - String appId = WebUtils.getAppId(exchange); - List docs = getAppDocSet(appId); - String docsJson = JacksonUtils.writeValueAsString(docs); - response.setStatusCode(HttpStatus.OK); - response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - return response.writeWith(Mono.just(response.bufferFactory().wrap(docsJson.getBytes()))); - } else { - return WebUtils.response(response, HttpStatus.FORBIDDEN, null, auth.msg); + String managerUrl = fizzMangerConfig.managerUrl; + if (managerUrl == null) { + return WebUtils.response(response, HttpStatus.INTERNAL_SERVER_ERROR, null, "no fizz manager url config"); } - } + String address = managerUrl + fizzMangerConfig.pairPath; - private List getAppDocSet(String appId) { - Map docSetMap = apiPairingDocSetService.getDocSetMap(); - ArrayList result = ThreadContext.getArrayList(); - for (Map.Entry entry : docSetMap.entrySet()) { - ApiPairingDocSet ds = entry.getValue(); - AppApiPairingDocSet appDocSet = new AppApiPairingDocSet(); - appDocSet.id = ds.id; - appDocSet.name = ds.name; - appDocSet.description = ds.description; - appDocSet.services = ds.docs.stream().map(d -> d.service).collect(Collectors.toSet()); - appDocSet.enabled = false; - if (ds.appIds.contains(appId)) { - appDocSet.enabled = true; - } - result.add(appDocSet); - } - return result; + String traceId = WebUtils.getTraceId(exchange); + Mono remoteResponseMono = fizzWebClient.send(traceId, request.getMethod(), address, request.getHeaders(), null); + return + remoteResponseMono.flatMap( + remoteResp -> { + response.setStatusCode(remoteResp.statusCode()); + HttpHeaders respHeaders = response.getHeaders(); + HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders(); + respHeaders.putAll(remoteRespHeaders); + if (log.isDebugEnabled()) { + StringBuilder sb = ThreadContext.getStringBuilder(); + WebUtils.response2stringBuilder(traceId, remoteResp, sb); + log.debug(sb.toString(), LogService.BIZ_ID, traceId); + } + return response.writeWith ( remoteResp.body(BodyExtractors.toDataBuffers()) ) + .doOnError ( throwable -> cleanup(remoteResp) ) + .doOnCancel( () -> cleanup(remoteResp) ); + } + ); } @GetMapping("/doc/**") @@ -166,7 +152,7 @@ public class ApiPairingController { String address = managerUrl + fizzMangerConfig.docPathPrefix + uri.substring(dp + 3); String traceId = WebUtils.getTraceId(exchange); - Mono remoteResponseMono = fizzWebClient.send(traceId, request.getMethod(), address, request.getHeaders(), request.getBody()); + Mono remoteResponseMono = fizzWebClient.send(traceId, request.getMethod(), address, request.getHeaders(), null); return remoteResponseMono.flatMap( remoteResp -> { diff --git a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingHttpHandler.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineHttpHandler.java similarity index 82% rename from fizz-core/src/main/java/we/api/pairing/FizzApiPairingHttpHandler.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineHttpHandler.java index 9a6abd2..ca7a692 100644 --- a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingHttpHandler.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineHttpHandler.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,11 +51,11 @@ import java.util.Set; * @author hongqiaowei */ -class FizzApiPairingHttpHandler implements HttpHandler { +class DedicatedLineHttpHandler implements HttpHandler { private static final String disconnected_client_log_category = "DisconnectedClient"; - private static final Logger log = LoggerFactory.getLogger(FizzApiPairingHttpHandler.class); + private static final Logger log = LoggerFactory.getLogger(DedicatedLineHttpHandler.class); private static final Logger lostClientLog = LoggerFactory.getLogger(disconnected_client_log_category); @@ -69,19 +69,19 @@ class FizzApiPairingHttpHandler implements HttpHandler { private SystemConfig systemConfig; private FizzWebClient fizzWebClient; - private ApiPairingInfoService apiPairingInfoService; + private DedicatedLineInfoService dedicatedLineInfoService; - public FizzApiPairingHttpHandler(ReactiveWebServerApplicationContext applicationContext, WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer, - LocaleContextResolver localeContextResolver, ForwardedHeaderTransformer forwardedHeaderTransformer) { + public DedicatedLineHttpHandler(ReactiveWebServerApplicationContext applicationContext, WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer, + LocaleContextResolver localeContextResolver, ForwardedHeaderTransformer forwardedHeaderTransformer) { this.sessionManager = sessionManager; this.serverCodecConfigurer = codecConfigurer; this.localeContextResolver = localeContextResolver; this.forwardedHeaderTransformer = forwardedHeaderTransformer; - systemConfig = applicationContext.getBean(SystemConfig.class); - fizzWebClient = applicationContext.getBean(FizzWebClient.class); - apiPairingInfoService = applicationContext.getBean(ApiPairingInfoService.class); + systemConfig = applicationContext.getBean(SystemConfig.class); + fizzWebClient = applicationContext.getBean(FizzWebClient.class); + dedicatedLineInfoService = applicationContext.getBean(DedicatedLineInfoService.class); } @Override @@ -105,14 +105,14 @@ class FizzApiPairingHttpHandler implements HttpHandler { String path = requestURI.getPath(); int secFS = path.indexOf(Consts.S.FORWARD_SLASH, 1); String service = path.substring(1, secFS); - ApiPairingInfo apiPairingInfo = apiPairingInfoService.get(service); - if (apiPairingInfo == null) { - log.warn("{}{} service no api pairing info", logPrefix, service); - return WebUtils.response(response, HttpStatus.FORBIDDEN, null, service + " service no api pairing info").then(response.setComplete()); + DedicatedLineInfo dedicatedLineInfo = dedicatedLineInfoService.get(service); + if (dedicatedLineInfo == null) { + log.warn("{}{} service no dedicated line info", logPrefix, service); + return WebUtils.response(response, HttpStatus.FORBIDDEN, null, service + " service no dedicated line info").then(response.setComplete()); } StringBuilder b = ThreadContext.getStringBuilder(); - b.append(apiPairingInfo.url).append(path); + b.append(dedicatedLineInfo.url).append(path); String qry = requestURI.getQuery(); if (StringUtils.hasText(qry)) { if (org.apache.commons.lang3.StringUtils.indexOfAny(qry, Consts.S.LEFT_BRACE, Consts.S.FORWARD_SLASH, Consts.S.HASH) > 0) { @@ -120,22 +120,23 @@ class FizzApiPairingHttpHandler implements HttpHandler { } b.append(Consts.S.QUESTION).append(qry); } - String targetUrl = b.toString(); - String appId = apiPairingInfo.appId; - String secretKey = apiPairingInfo.secretKey; - String timestamp = String.valueOf(System.currentTimeMillis()); - String sign = ApiPairingUtils.sign(appId, timestamp, secretKey); + String targetUrl = b.toString(); + String pairCodeId = dedicatedLineInfo.pairCodeId; + String secretKey = dedicatedLineInfo.secretKey; + String timestamp = String.valueOf(System.currentTimeMillis()); + String sign = DedicatedLineUtils.sign(pairCodeId, timestamp, secretKey); HttpHeaders writableHttpHeaders = HttpHeaders.writableHttpHeaders(request.getHeaders()); - writableHttpHeaders.set(SystemConfig.FIZZ_APP_ID, appId); - writableHttpHeaders.set(SystemConfig.FIZZ_TIMESTAMP, timestamp); - writableHttpHeaders.set(SystemConfig.FIZZ_SIGN, sign); + writableHttpHeaders.set(SystemConfig.FIZZ_DL_ID, pairCodeId); + writableHttpHeaders.set(SystemConfig.FIZZ_DL_TS, timestamp); + writableHttpHeaders.set(SystemConfig.FIZZ_DL_SIGN, sign); - int requestTimeout = systemConfig.fizzApiPairingRequestTimeout(); - int retryCount = systemConfig.fizzApiPairingRequestRetryCount(); - int retryInterval = systemConfig.fizzApiPairingRequestRetryInterval(); + int requestTimeout = systemConfig.fizzDedicatedLineClientRequestTimeout(); + int retryCount = systemConfig.fizzDedicatedLineClientRequestRetryCount(); + int retryInterval = systemConfig.fizzDedicatedLineClientRequestRetryInterval(); try { + // TODO: 如果有请求体,则对请求体加密 Mono remoteResponseMono = fizzWebClient.send( request.getId(), request.getMethod(), targetUrl, writableHttpHeaders, request.getBody(), requestTimeout, retryCount, retryInterval ); @@ -150,6 +151,7 @@ class FizzApiPairingHttpHandler implements HttpHandler { WebUtils.response2stringBuilder(logPrefix, remoteResp, sb); log.debug(sb.toString()); } + // TODO: 如果有响应体,则对响应体解密;响应可能是页面、表单、文件上传的结果、图片等 return response.writeWith ( remoteResp.body(BodyExtractors.toDataBuffers()) ) .doOnError ( throwable -> cleanup(remoteResp) ) .doOnCancel( () -> cleanup(remoteResp) ); diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingInfo.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfo.java similarity index 81% rename from fizz-core/src/main/java/we/api/pairing/ApiPairingInfo.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfo.java index b13bf25..7276955 100644 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingInfo.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfo.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import we.util.JacksonUtils; @@ -26,22 +26,26 @@ import java.util.List; * @author hongqiaowei */ -public class ApiPairingInfo { +public class DedicatedLineInfo { - public static final int DELETED = 1; - - public int isDeleted = 0; + public boolean isDeleted = false; public String id; // uuid public String url; - public String appId; + public String pairCodeId; public String secretKey; public List services = Collections.emptyList(); + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + @Override public String toString() { return JacksonUtils.writeValueAsString(this); diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingInfoService.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfoService.java similarity index 70% rename from fizz-core/src/main/java/we/api/pairing/ApiPairingInfoService.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfoService.java index a10ba8f..c0e1f51 100644 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingInfoService.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineInfoService.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,20 +39,20 @@ import java.util.Map; * @author hongqiaowei */ -@ConditionalOnProperty(name = SystemConfig.FIZZ_API_PAIRING_CLIENT_ENABLE, havingValue = "true") +@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_CLIENT_ENABLE, havingValue = "true") @Service -public class ApiPairingInfoService { +public class DedicatedLineInfoService { - private static final Logger log = LoggerFactory.getLogger(ApiPairingInfoService.class); + private static final Logger log = LoggerFactory.getLogger(DedicatedLineInfoService.class); - private Map serviceApiPairingInfoMap = new HashMap<>(64); + private Map serviceDedicatedLineInfoMap = new HashMap<>(32); @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) private ReactiveStringRedisTemplate rt; @PostConstruct public void init() throws Throwable { - Result result = initApiPairingInfo(); + Result result = initDedicatedLineInfo(); if (result.code == Result.FAIL) { throw new RuntimeException(result.msg, result.t); } @@ -62,9 +62,9 @@ public class ApiPairingInfoService { } } - private Result initApiPairingInfo() { + private Result initDedicatedLineInfo() { Result result = Result.succ(); - Flux> resources = rt.opsForHash().entries("fizz_api_pairing_info"); + Flux> resources = rt.opsForHash().entries("fizz_dedicated_line_info"); resources.collectList() .defaultIfEmpty(Collections.emptyList()) .flatMap( @@ -74,19 +74,19 @@ public class ApiPairingInfoService { try { for (Map.Entry e : es) { json = (String) e.getValue(); - ApiPairingInfo info = JacksonUtils.readValue(json, ApiPairingInfo.class); + DedicatedLineInfo info = JacksonUtils.readValue(json, DedicatedLineInfo.class); for (String service : info.services) { - serviceApiPairingInfoMap.put(service, info); + serviceDedicatedLineInfoMap.put(service, info); } - log.info("init api pairing info: {}", info); + log.info("init dedicated line info: {}", info); } } catch (Throwable t) { result.code = Result.FAIL; - result.msg = "init api pairing info error, info: " + json; + result.msg = "init dedicated line info error, info: " + json; result.t = t; } } else { - log.info("no api pairing info"); + log.info("no dedicated line info"); } return Mono.empty(); } @@ -94,7 +94,7 @@ public class ApiPairingInfoService { .onErrorReturn( throwable -> { result.code = Result.FAIL; - result.msg = "init api pairing info error"; + result.msg = "init dedicated line info error"; result.t = throwable; return true; }, @@ -106,7 +106,7 @@ public class ApiPairingInfoService { private Result lsnApiPairingInfoChange() { Result result = Result.succ(); - String channel = "fizz_api_pairing_info_channel"; + String channel = "fizz_dedicated_line_info_channel"; rt.listenToChannel(channel) .doOnError( t -> { @@ -125,20 +125,20 @@ public class ApiPairingInfoService { msg -> { String message = msg.getMessage(); try { - ApiPairingInfo info = JacksonUtils.readValue(message, ApiPairingInfo.class); - if (info.isDeleted == ApiPairingDocSet.DELETED) { + DedicatedLineInfo info = JacksonUtils.readValue(message, DedicatedLineInfo.class); + if (info.isDeleted) { for (String service : info.services) { - serviceApiPairingInfoMap.remove(service); + serviceDedicatedLineInfoMap.remove(service); } - log.info("remove api pairing info: {}", info); + log.info("remove dedicated line info: {}", info); } else { for (String service : info.services) { - serviceApiPairingInfoMap.put(service, info); + serviceDedicatedLineInfoMap.put(service, info); } - log.info("update api pairing info: {}", info); + log.info("update dedicated line info: {}", info); } } catch (Throwable t) { - log.error("update api pairing info error, {}", message, t); + log.error("update dedicated line info error, {}", message, t); } } ) @@ -146,11 +146,7 @@ public class ApiPairingInfoService { return result; } - public Map getServiceApiPairingInfoMap() { - return serviceApiPairingInfoMap; - } - - public ApiPairingInfo get(String service) { - return serviceApiPairingInfoMap.get(service); + public DedicatedLineInfo get(String service) { + return serviceDedicatedLineInfoMap.get(service); } } diff --git a/fizz-core/src/main/java/we/dedicated_line/DedicatedLineService.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineService.java new file mode 100644 index 0000000..2bd38ea --- /dev/null +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineService.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2020 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package we.dedicated_line; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.redis.core.ReactiveStringRedisTemplate; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import we.config.AggregateRedisConfig; +import we.config.SystemConfig; +import we.plugin.auth.ApiConfig; +import we.util.JacksonUtils; +import we.util.Result; +import we.util.UrlTransformUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * @author hongqiaowei + */ + +@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_SERVER_ENABLE, havingValue = "true") +@Service +public class DedicatedLineService { + + private static final Logger log = LoggerFactory.getLogger(DedicatedLineService.class); + + private Map dedicatedLineMap = new HashMap<>(32); + + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) + private ReactiveStringRedisTemplate rt; + + @PostConstruct + public void init() throws Throwable { + Result result = initDedicatedLine(); + if (result.code == Result.FAIL) { + throw new RuntimeException(result.msg, result.t); + } + result = lsnDedicatedLineChange(); + if (result.code == Result.FAIL) { + throw new RuntimeException(result.msg, result.t); + } + } + + private Result initDedicatedLine() { + Result result = Result.succ(); + Flux> resources = rt.opsForHash().entries("fizz_dedicated_line"); + resources.collectList() + .defaultIfEmpty(Collections.emptyList()) + .flatMap( + es -> { + if (!es.isEmpty()) { + String json = null; + try { + for (Map.Entry e : es) { + json = (String) e.getValue(); + DedicatedLine dl = JacksonUtils.readValue(json, DedicatedLine.class); + dedicatedLineMap.put(dl.pairCodeId, dl); + } + } catch (Throwable t) { + result.code = Result.FAIL; + result.msg = "init dedicated line error, json: " + json; + result.t = t; + } + } else { + log.info("no dedicated line"); + } + return Mono.empty(); + } + ) + .onErrorReturn( + throwable -> { + result.code = Result.FAIL; + result.msg = "init dedicated line error"; + result.t = throwable; + return true; + }, + result + ) + .block(); + return result; + } + + private Result lsnDedicatedLineChange() { + Result result = Result.succ(); + String channel = "fizz_dedicated_line_channel"; + rt.listenToChannel(channel) + .doOnError( + t -> { + result.code = Result.FAIL; + result.msg = "lsn error, channel: " + channel; + result.t = t; + log.error("lsn channel {} error", channel, t); + } + ) + .doOnSubscribe( + s -> { + log.info("success to lsn on {}", channel); + } + ) + .doOnNext( + msg -> { + String message = msg.getMessage(); + try { + DedicatedLine dl = JacksonUtils.readValue(message, DedicatedLine.class); + if (dl.isDeleted) { + dedicatedLineMap.remove(dl.pairCodeId); + } else { + dedicatedLineMap.put(dl.pairCodeId, dl); + } + } catch (Throwable t) { + log.error("update dedicated line error, {}", message, t); + } + } + ) + .subscribe(); + return result; + } + + public boolean auth(String pairCodeId, HttpMethod method, String service, String path) { + DedicatedLine dedicatedLine = dedicatedLineMap.get(pairCodeId); + if (dedicatedLine == null) { + return false; + } + if (dedicatedLine.servicesWithoutApiDocs.contains(service)) { + return true; + } + Map> methodPathsMap = dedicatedLine.apiDocMap.get(service); + if (methodPathsMap == null) { + return false; + } + Set pathPatterns = methodPathsMap.get(method); + if (pathPatterns != null) { + if (pathPatternMatch(path, pathPatterns)) { + return true; + } + } + pathPatterns = methodPathsMap.get(ApiConfig.ALL_METHOD); + if (pathPatterns != null) { + return pathPatternMatch(path, pathPatterns); + } + return false; + } + + private boolean pathPatternMatch(String path, Set pathPatterns) { + if (pathPatterns.contains(path)) { + return true; + } + for (String pathPattern : pathPatterns) { + if (UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path)) { + return true; + } + } + return false; + } + + public String getPairCodeSecretKey(String pairCodeId) { + DedicatedLine dedicatedLine = dedicatedLineMap.get(pairCodeId); + if (dedicatedLine != null) { + return dedicatedLine.secretKey; + } + return null; + } +} diff --git a/fizz-core/src/main/java/we/api/pairing/ApiPairingServiceRegistration.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java similarity index 93% rename from fizz-core/src/main/java/we/api/pairing/ApiPairingServiceRegistration.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java index b5abfd9..a474b6b 100644 --- a/fizz-core/src/main/java/we/api/pairing/ApiPairingServiceRegistration.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration; import lombok.SneakyThrows; @@ -47,9 +47,9 @@ import javax.annotation.PreDestroy; @Configuration @ConditionalOnDiscoveryEnabled -@ConditionalOnProperty(name = SystemConfig.FIZZ_API_PAIRING_CLIENT_ENABLE, havingValue = "true") +@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_CLIENT_ENABLE, havingValue = "true") @AutoConfigureAfter({EurekaClientAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class}) -public class ApiPairingServiceRegistration implements ApplicationListener { +public class DedicatedLineServiceRegistration implements ApplicationListener { private ServiceRegistry serviceRegistry; @@ -57,12 +57,12 @@ public class ApiPairingServiceRegistration implements ApplicationListener. */ -package we.api.pairing; +package we.dedicated_line; import we.util.Consts; import we.util.ThreadContext; @@ -24,29 +24,29 @@ import we.util.ThreadContext; * @author hongqiaowei */ -public abstract class ApiPairingUtils extends org.apache.commons.codec.digest.DigestUtils { +public abstract class DedicatedLineUtils extends org.apache.commons.codec.digest.DigestUtils { - private ApiPairingUtils() { + private DedicatedLineUtils() { } - public static String sign(String app, String timestamp, String secretKey) { + public static String sign(String pairCodeId, String timestamp, String secretKey) { StringBuilder b = ThreadContext.getStringBuilder(ThreadContext.sb0); - b.append(app) .append(Consts.S.UNDER_LINE) - .append(timestamp).append(Consts.S.UNDER_LINE) + b.append(pairCodeId).append(Consts.S.UNDER_LINE) + .append(timestamp) .append(Consts.S.UNDER_LINE) .append(secretKey); return sha256Hex(b.toString()); } - public static String sign(String app, long timestamp, String secretKey) { - return sign(app, String.valueOf(timestamp), secretKey); + public static String sign(String pairCodeId, long timestamp, String secretKey) { + return sign(pairCodeId, String.valueOf(timestamp), secretKey); } - public static boolean checkSign(String app, String timestamp, String secretKey, String sign) { - String s = sign(app, timestamp, secretKey); + public static boolean checkSign(String pairCodeId, String timestamp, String secretKey, String sign) { + String s = sign(pairCodeId, timestamp, secretKey); return s.equals(sign); } - public static boolean checkSign(String app, long timestamp, String secretKey, String sign) { - return checkSign(app, String.valueOf(timestamp), secretKey, sign); + public static boolean checkSign(String pairCodeId, long timestamp, String secretKey, String sign) { + return checkSign(pairCodeId, String.valueOf(timestamp), secretKey, sign); } } diff --git a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServer.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServer.java similarity index 83% rename from fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServer.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServer.java index e2a0eac..f99601d 100644 --- a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServer.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServer.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,12 +40,12 @@ import javax.annotation.Resource; * @author hongqiaowei */ -@ConditionalOnProperty(name = SystemConfig.FIZZ_API_PAIRING_CLIENT_ENABLE, havingValue = "true") +@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_CLIENT_ENABLE, havingValue = "true") @Configuration @AutoConfigureAfter({HttpHandlerAutoConfiguration.class}) -public class FizzApiPairingWebServer { +public class DedicatedLineWebServer { - private static final Logger log = LoggerFactory.getLogger(FizzApiPairingWebServer.class); + private static final Logger log = LoggerFactory.getLogger(DedicatedLineWebServer.class); @Resource private ReactiveWebServerApplicationContext applicationContext; @@ -55,7 +55,7 @@ public class FizzApiPairingWebServer { private WebServer server; - @Value("${fizz.api.pairing.client.port:8601}") + @Value("${fizz.dedicated-line.client.port:8601}") private int port = 8601; @PostConstruct @@ -63,7 +63,7 @@ public class FizzApiPairingWebServer { HttpWebHandlerAdapter adapter = (HttpWebHandlerAdapter) httpHandler; NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory(port); server = factory.getWebServer( - new FizzApiPairingHttpHandler( + new DedicatedLineHttpHandler( applicationContext, new DefaultWebSessionManager(), adapter.getCodecConfigurer(), @@ -72,8 +72,8 @@ public class FizzApiPairingWebServer { ) ); server.start(); - log.info("fizz api pairing web server listen on {}", port); - applicationContext.publishEvent(new FizzApiPairingWebServerInitializedEvent(server, applicationContext)); + log.info("fizz dedicated line web server listen on {}", port); + applicationContext.publishEvent(new DedicatedLineWebServerInitializedEvent(server, applicationContext)); } @PreDestroy diff --git a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServerInitializedEvent.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServerInitializedEvent.java similarity index 84% rename from fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServerInitializedEvent.java rename to fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServerInitializedEvent.java index d572dd0..8cb00fd 100644 --- a/fizz-core/src/main/java/we/api/pairing/FizzApiPairingWebServerInitializedEvent.java +++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineWebServerInitializedEvent.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; import org.springframework.boot.web.server.WebServer; @@ -25,11 +25,11 @@ import org.springframework.context.ApplicationEvent; * @author hongqiaowei */ -public class FizzApiPairingWebServerInitializedEvent extends ApplicationEvent { +public class DedicatedLineWebServerInitializedEvent extends ApplicationEvent { private final ReactiveWebServerApplicationContext applicationContext; - public FizzApiPairingWebServerInitializedEvent(WebServer webServer, ReactiveWebServerApplicationContext applicationContext) { + public DedicatedLineWebServerInitializedEvent(WebServer webServer, ReactiveWebServerApplicationContext applicationContext) { super(webServer); this.applicationContext = applicationContext; } diff --git a/fizz-core/src/main/java/we/api/pairing/Api.java b/fizz-core/src/main/java/we/dedicated_line/MethodAndPath.java similarity index 95% rename from fizz-core/src/main/java/we/api/pairing/Api.java rename to fizz-core/src/main/java/we/dedicated_line/MethodAndPath.java index 42bc3cb..a236bd0 100644 --- a/fizz-core/src/main/java/we/api/pairing/Api.java +++ b/fizz-core/src/main/java/we/dedicated_line/MethodAndPath.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.api.pairing; +package we.dedicated_line; import org.springframework.http.HttpMethod; import we.plugin.auth.ApiConfig; @@ -25,7 +25,7 @@ import we.util.JacksonUtils; * @author hongqiaowei */ -public class Api { +public class MethodAndPath { public Object method; diff --git a/fizz-core/src/main/java/we/filter/FilterExceptionHandlerConfig.java b/fizz-core/src/main/java/we/filter/FilterExceptionHandlerConfig.java index ead83d8..82149fa 100644 --- a/fizz-core/src/main/java/we/filter/FilterExceptionHandlerConfig.java +++ b/fizz-core/src/main/java/we/filter/FilterExceptionHandlerConfig.java @@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; -import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -38,7 +37,9 @@ import we.exception.StopAndResponseException; import we.fizz.exception.FizzRuntimeException; import we.flume.clients.log4j2appender.LogService; import we.legacy.RespEntity; -import we.util.*; +import we.util.JacksonUtils; +import we.util.ThreadContext; +import we.util.WebUtils; import java.net.URI; @@ -92,7 +93,7 @@ public class FilterExceptionHandlerConfig { RespEntity rs = null; if (ex.getStepContext() != null && ex.getStepContext().returnContext()) { rs = new RespEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), tMsg, traceId, ex.getStepContext()); - return resp.writeWith(Mono.just(resp.bufferFactory().wrap(JacksonUtils.writeValueAsString(rs).getBytes()))); + return resp.writeWith(Mono.just(resp.bufferFactory().wrap(JacksonUtils.writeValueAsBytes(rs)))); } else { rs = new RespEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), tMsg, traceId); return resp.writeWith(Mono.just(resp.bufferFactory().wrap(rs.toString().getBytes()))); diff --git a/fizz-core/src/main/java/we/filter/FizzWebFilter.java b/fizz-core/src/main/java/we/filter/FizzWebFilter.java index 664fd68..c348584 100644 --- a/fizz-core/src/main/java/we/filter/FizzWebFilter.java +++ b/fizz-core/src/main/java/we/filter/FizzWebFilter.java @@ -31,7 +31,7 @@ public abstract class FizzWebFilter implements WebFilter { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - if (WebUtils.isAdminReq(exchange) || WebUtils.isFizzApiReq(exchange)) { + if (WebUtils.isAdminReq(exchange) || WebUtils.isFizzReq(exchange)) { return chain.filter(exchange); } else { return doFilter(exchange, chain); diff --git a/fizz-core/src/main/java/we/filter/FlowControlFilter.java b/fizz-core/src/main/java/we/filter/FlowControlFilter.java index 01c18df..97f4880 100644 --- a/fizz-core/src/main/java/we/filter/FlowControlFilter.java +++ b/fizz-core/src/main/java/we/filter/FlowControlFilter.java @@ -32,7 +32,6 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.SignalType; import we.config.SystemConfig; import we.flume.clients.log4j2appender.LogService; -import we.legacy.RespEntity; import we.plugin.auth.ApiConfigService; import we.plugin.auth.AppService; import we.stats.BlockType; @@ -71,7 +70,7 @@ public class FlowControlFilter extends FizzWebFilter { @Resource - private FlowControlFilterProperties flowControlFilterProperties; + private FlowControlFilterProperties flowControlFilterProperties; @Resource private ResourceRateLimitConfigService resourceRateLimitConfigService; @@ -83,10 +82,10 @@ public class FlowControlFilter extends FizzWebFilter { private ApiConfigService apiConfigService; @Resource - private AppService appService; + private AppService appService; @Resource - private SystemConfig systemConfig; + private SystemConfig systemConfig; @Override public Mono doFilter(ServerWebExchange exchange, WebFilterChain chain) { @@ -107,7 +106,7 @@ public class FlowControlFilter extends FizzWebFilter { service = WebUtils.getClientService(exchange); if (service.startsWith(_fizz)) { fizzApiReq = true; - exchange.getAttributes().put(WebUtils.FIZZ_API_REQUEST, Consts.S.EMPTY); + exchange.getAttributes().put(WebUtils.FIZZ_REQUEST, Consts.S.EMPTY); } } diff --git a/fizz-core/src/main/java/we/global_resource/GlobalResource.java b/fizz-core/src/main/java/we/global_resource/GlobalResource.java index db900b4..f4a44d4 100644 --- a/fizz-core/src/main/java/we/global_resource/GlobalResource.java +++ b/fizz-core/src/main/java/we/global_resource/GlobalResource.java @@ -37,9 +37,7 @@ public class GlobalResource { public static final int NUMBER = 3; public static final int JSON = 4; - public static final int DELETED = 1; - - public int isDeleted = 0; + public boolean isDeleted = false; public int id; @@ -86,7 +84,9 @@ public class GlobalResource { @JsonProperty("update") long update ) { - this.isDeleted = isDeleted; + if (isDeleted == 1) { + this.isDeleted = true; + } this.id = id; this.key = key; this.type = type; diff --git a/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java b/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java index 83f717f..6aab182 100644 --- a/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java +++ b/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java @@ -134,7 +134,7 @@ public class GlobalResourceService { String message = msg.getMessage(); try { GlobalResource r = JacksonUtils.readValue(message, GlobalResource.class); - if (r.isDeleted == GlobalResource.DELETED) { + if (r.isDeleted) { resourceMap.remove(r.key); objectMap.remove(r.key); log.info("remove global resource {}", r.key); diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java index 5bc4099..e992875 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java +++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java @@ -27,7 +27,6 @@ import we.plugin.PluginConfig; import we.proxy.Route; import we.util.JacksonUtils; import we.util.UrlTransformUtils; -import we.util.WebUtils; import javax.annotation.Nullable; import java.util.*; @@ -49,15 +48,9 @@ public class ApiConfig { static final byte DUBBO = 5; } - public static final int DELETED = 1; + public static final String ALL_METHOD = "AM"; - public static final char ALLOW = 'a'; - - public static final String ALL_METHOD = "AM"; - - private static final String match_all = "/**"; - - private static final int ENABLE = 1; + private static final String match_all = "/**"; @JsonProperty( access = JsonProperty.Access.WRITE_ONLY @@ -67,7 +60,7 @@ public class ApiConfig { @JsonProperty( access = JsonProperty.Access.WRITE_ONLY ) - public int isDeleted = 0; + public boolean isDeleted = false; public Set gatewayGroups = Stream.of(GatewayGroup.DEFAULT).collect(Collectors.toCollection(LinkedHashSet::new)); @@ -80,11 +73,6 @@ public class ApiConfig { public String backendService; - @JsonProperty( - access = JsonProperty.Access.WRITE_ONLY - ) - public HttpMethod method; - public Object fizzMethod = ALL_METHOD; public String path = match_all; @@ -96,6 +84,8 @@ public class ApiConfig { public String backendPath; + public boolean dedicatedLine = false; + @JsonProperty("proxyMode") public byte type = Type.SERVICE_DISCOVERY; @@ -103,7 +93,7 @@ public class ApiConfig { public List httpHostPorts; - public char access = ALLOW; + public boolean allowAccess = true; public List pluginConfigs = Collections.emptyList(); @@ -125,6 +115,18 @@ public class ApiConfig { public long retryInterval = 0; + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + + public void setAccess(char c) { + if (c != 'a') { + allowAccess = false; + } + } + public void setGatewayGroup(String ggs) { gatewayGroups.remove(GatewayGroup.DEFAULT); if (StringUtils.isBlank(ggs)) { @@ -155,19 +157,21 @@ public class ApiConfig { } public void setMethod(String m) { - method = HttpMethod.resolve(m); - if (method == null) { + fizzMethod = HttpMethod.resolve(m); + if (fizzMethod == null) { fizzMethod = ALL_METHOD; - } else { - fizzMethod = method; } } public void setAppEnable(int v) { - if (v == ENABLE) { + if (v == 1) { checkApp = true; - } else { - checkApp = false; + } + } + + public void setDedicatedLine(int v) { + if (v == 1) { + dedicatedLine = true; } } @@ -205,7 +209,8 @@ public class ApiConfig { public Route getRoute(ServerWebExchange exchange, @Nullable List gatewayGroupPluginConfigs) { ServerHttpRequest request = exchange.getRequest(); - Route r = new Route().type( this.type) + Route r = new Route().dedicatedLine( this.dedicatedLine) + .type( this.type) .method( request.getMethod()) .backendService(this.backendService) .backendPath( this.backendPath) diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConfig2apps.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfig2apps.java index 453d1e6..870c06b 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ApiConfig2apps.java +++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfig2apps.java @@ -27,14 +27,18 @@ import java.util.List; public class ApiConfig2apps { - public static final int DELETED = 1; - public int id; - public int isDeleted = 0; + public boolean isDeleted = false; public List apps; + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + @Override public String toString() { return JacksonUtils.writeValueAsString(this); diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConifg2appsService.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfig2appsService.java similarity index 94% rename from fizz-core/src/main/java/we/plugin/auth/ApiConifg2appsService.java rename to fizz-core/src/main/java/we/plugin/auth/ApiConfig2appsService.java index ecb9db6..16d4b14 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ApiConifg2appsService.java +++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfig2appsService.java @@ -38,9 +38,9 @@ import java.util.*; */ @Service -public class ApiConifg2appsService { +public class ApiConfig2appsService { - private static final Logger log = LoggerFactory.getLogger(ApiConifg2appsService.class); + private static final Logger log = LoggerFactory.getLogger(ApiConfig2appsService.class); private static final String fizzApiConfigAppSetSize = "fizz_api_config_app_set_size"; @@ -120,11 +120,7 @@ public class ApiConifg2appsService { } private void save(Integer apiConfigId, List as, Map> apiConfig2appsMap) { - Set appSet = apiConfig2appsMap.get(apiConfigId); - if (appSet == null) { - appSet = new HashSet<>(); - apiConfig2appsMap.put(apiConfigId, appSet); - } + Set appSet = apiConfig2appsMap.computeIfAbsent(apiConfigId, k -> new HashSet<>()); appSet.addAll(as); log(apiConfigId, as); } @@ -168,9 +164,9 @@ public class ApiConifg2appsService { private void updateApiConfig2appsMap(ApiConfig2apps data) { Set apps = apiConfig2appsMap.get(data.id); - if (data.isDeleted == ApiConfig2apps.DELETED) { + if (data.isDeleted) { if (apps != null) { - apps.removeAll(data.apps); + data.apps.forEach(apps::remove); log.info("remove " + data); } } else { diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConfigService.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfigService.java index e0431ea..50fd0ba 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ApiConfigService.java +++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfigService.java @@ -25,7 +25,6 @@ import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicatio import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.redis.core.ReactiveStringRedisTemplate; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.lang.Nullable; @@ -54,7 +53,7 @@ import java.util.regex.Pattern; @Service public class ApiConfigService implements ApplicationListener { - private static final Logger log = LoggerFactory.getLogger(ApiConfigService.class); + private static final Logger log = LoggerFactory.getLogger(ApiConfigService.class); public Map serviceConfigMap = new HashMap<>(128); @@ -75,7 +74,7 @@ public class ApiConfigService implements ApplicationListener serviceConfigMap) { ServiceConfig sc = serviceConfigMap.get(ac.service); - if (ac.isDeleted == ApiConfig.DELETED) { + if (ac.isDeleted) { if (sc != null) { sc.remove(ac); if (sc.apiConfigMap.isEmpty()) { @@ -353,26 +351,26 @@ public class ApiConfigService implements ApplicationListener result = get(null, app, service, method, path); + Result result = get(false, null, app, service, method, path); if (result.code == Result.SUCC) { return result.data; } return null; } - public Result get(String app, String service, HttpMethod method, String path) { - return get(null, app, service, method, path); + public Result get(boolean dedicatedLineRequest, String app, String service, HttpMethod method, String path) { + return get(dedicatedLineRequest, null, app, service, method, path); } public ApiConfig getApiConfig(Set gatewayGroups, String app, String service, HttpMethod method, String path) { - Result result = get(null, app, service, method, path); + Result result = get(false, null, app, service, method, path); if (result.code == Result.SUCC) { return result.data; } return null; } - public Result get(Set gatewayGroups, String app, String service, HttpMethod method, String path) { + public Result get(boolean dedicatedLineRequest, Set gatewayGroups, String app, String service, HttpMethod method, String path) { ServiceConfig sc = serviceConfigMap.get(service); if (sc == null) { return Result.fail("no " + service + " service api config"); @@ -380,34 +378,34 @@ public class ApiConfigService implements ApplicationListener apiConfigs = sc.getApiConfigs(gatewayGroups, method, path); + List apiConfigs = sc.getApiConfigs(dedicatedLineRequest, gatewayGroups, method, path); if (apiConfigs.isEmpty()) { StringBuilder b = ThreadContext.getStringBuilder(); b.append(service).append(" don't have api config matching ").append(gatewayGroups).append(" group ").append(method).append(" method ").append(path).append(" path"); return Result.fail(b.toString()); } - List appCanAccess = ThreadContext.getArrayList(); + List clientCanAccess = ThreadContext.getArrayList(); for (int i = 0; i < apiConfigs.size(); i++) { ApiConfig ac = apiConfigs.get(i); - if (ac.checkApp) { - if (StringUtils.isNotBlank(app) && apiConifg2appsService.contains(ac.id, app)) { - appCanAccess.add(ac); + if (!dedicatedLineRequest && ac.checkApp) { + if (StringUtils.isNotBlank(app) && apiConfig2AppsService.contains(ac.id, app)) { + clientCanAccess.add(ac); } } else { - appCanAccess.add(ac); + clientCanAccess.add(ac); } } - if (appCanAccess.isEmpty()) { + if (clientCanAccess.isEmpty()) { StringBuilder b = ThreadContext.getStringBuilder(); b.append("app ").append(app).append(" can't access ").append(JacksonUtils.writeValueAsString(apiConfigs)); return Result.fail(b.toString()); } - ApiConfig bestOne = appCanAccess.get(0); - if (appCanAccess.size() != 1) { - appCanAccess.sort(new ApiConfigPathPatternComparator(path)); // singleton ? - ApiConfig ac0 = appCanAccess.get(0); + ApiConfig bestOne = clientCanAccess.get(0); + if (clientCanAccess.size() != 1) { + clientCanAccess.sort(new ApiConfigPathPatternComparator(path)); // singleton ? + ApiConfig ac0 = clientCanAccess.get(0); bestOne = ac0; - ApiConfig ac1 = appCanAccess.get(1); + ApiConfig ac1 = clientCanAccess.get(1); if (ac0.path.equals(ac1.path)) { if (ac0.fizzMethod == ac1.fizzMethod) { if (StringUtils.isNotBlank(app)) { @@ -428,11 +426,14 @@ public class ApiConfigService implements ApplicationListener> auth(ServerWebExchange exchange) { ServerHttpRequest req = exchange.getRequest(); LogService.setBizId(WebUtils.getTraceId(exchange)); - return auth(exchange, WebUtils.getAppId(exchange), WebUtils.getOriginIp(exchange), WebUtils.getTimestamp(exchange), WebUtils.getSign(exchange), - WebUtils.getClientService(exchange), req.getMethod(), WebUtils.getClientReqPath(exchange)); + boolean dedicatedLineRequest = WebUtils.isDedicatedLineRequest(exchange); + return auth(exchange, dedicatedLineRequest, + WebUtils.getAppId(exchange), WebUtils.getOriginIp(exchange), WebUtils.getTimestamp(exchange), WebUtils.getSign(exchange), + WebUtils.getClientService(exchange), req.getMethod(), WebUtils.getClientReqPath(exchange)); } - private Mono> auth(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String service, HttpMethod method, String path) { + private Mono> auth(ServerWebExchange exchange, boolean dedicatedLineRequest, + String app, String ip, String timestamp, String sign, String service, HttpMethod method, String path) { if (!systemConfig.isAggregateTestAuth()) { if (SystemConfig.DEFAULT_GATEWAY_TEST_PREFIX0.equals(WebUtils.getClientReqPathPrefix(exchange))) { @@ -440,7 +441,7 @@ public class ApiConfigService implements ApplicationListener r = get(app, service, method, path); + Result r = get(dedicatedLineRequest, app, service, method, path); if (r.code == Result.FAIL) { if (apiConfigServiceProperties.isNeedAuth()) { return Mono.just(r); @@ -450,7 +451,7 @@ public class ApiConfigService implements ApplicationListener> ips = new HashMap<>(); + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + public void setUseAuth(int i) { if (i == AUTH_TYPE.SIGN || i == AUTH_TYPE.SECRET_KEY || i == AUTH_TYPE.CUSTOM) { useAuth = true; diff --git a/fizz-core/src/main/java/we/plugin/auth/AppService.java b/fizz-core/src/main/java/we/plugin/auth/AppService.java index 3584c42..7a5d332 100644 --- a/fizz-core/src/main/java/we/plugin/auth/AppService.java +++ b/fizz-core/src/main/java/we/plugin/auth/AppService.java @@ -23,9 +23,8 @@ import org.springframework.data.redis.core.ReactiveStringRedisTemplate; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import we.flume.clients.log4j2appender.LogService; import we.config.AggregateRedisConfig; -import we.util.Consts; +import we.flume.clients.log4j2appender.LogService; import we.util.JacksonUtils; import we.util.ReactorUtils; @@ -80,9 +79,8 @@ public class AppService { if (k == ReactorUtils.OBJ) { return Flux.just(e); } - Object v = e.getValue(); - log.info("init app: {}", v.toString(), LogService.BIZ_ID, k.toString()); - String json = (String) v; + String json = (String) e.getValue(); + log.info("init app: {}", json, LogService.BIZ_ID, k.toString()); try { App app = JacksonUtils.readValue(json, App.class); oldAppMapTmp.put(app.id, app); @@ -127,15 +125,15 @@ public class AppService { } ).doOnNext(msg -> { String json = msg.getMessage(); - log.info(json, LogService.BIZ_ID, "ac" + System.currentTimeMillis()); + log.info("app change: " + json, LogService.BIZ_ID, "ac" + System.currentTimeMillis()); try { App app = JacksonUtils.readValue(json, App.class); App r = oldAppMap.remove(app.id); - if (app.isDeleted != App.DELETED && r != null) { + if (!app.isDeleted && r != null) { appMap.remove(r.app); } updateAppMap(app, appMap); - if (app.isDeleted != App.DELETED) { + if (!app.isDeleted) { oldAppMap.put(app.id, app); } } catch (Throwable t) { @@ -158,7 +156,7 @@ public class AppService { } private void updateAppMap(App app, Map appMap) { - if (app.isDeleted == App.DELETED) { + if (app.isDeleted) { App removedApp = appMap.remove(app.app); log.info("remove " + removedApp); } else { diff --git a/fizz-core/src/main/java/we/plugin/auth/GatewayGroup.java b/fizz-core/src/main/java/we/plugin/auth/GatewayGroup.java index cee86ca..c8b933f 100644 --- a/fizz-core/src/main/java/we/plugin/auth/GatewayGroup.java +++ b/fizz-core/src/main/java/we/plugin/auth/GatewayGroup.java @@ -35,11 +35,9 @@ public class GatewayGroup { public static final String DEFAULT = "default"; - public static final int DELETED = 1; - public int id; - public int isDeleted = 0; + public boolean isDeleted = false; public String group; @@ -49,6 +47,12 @@ public class GatewayGroup { public List pluginConfigs = Collections.emptyList(); + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + public void setGateways(String gateways) { if (StringUtils.isNotBlank(gateways)) { Arrays.stream(StringUtils.split(gateways, ',')).forEach( diff --git a/fizz-core/src/main/java/we/plugin/auth/GatewayGroupService.java b/fizz-core/src/main/java/we/plugin/auth/GatewayGroupService.java index d3726c9..e57dadf 100644 --- a/fizz-core/src/main/java/we/plugin/auth/GatewayGroupService.java +++ b/fizz-core/src/main/java/we/plugin/auth/GatewayGroupService.java @@ -26,7 +26,6 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import we.config.AggregateRedisConfig; import we.flume.clients.log4j2appender.LogService; -import we.util.Consts; import we.util.JacksonUtils; import we.util.NetworkUtils; import we.util.ReactorUtils; @@ -87,9 +86,8 @@ public class GatewayGroupService { if (k == ReactorUtils.OBJ) { return Flux.just(e); } - Object v = e.getValue(); - log.info(k.toString() + Consts.S.COLON + v.toString(), LogService.BIZ_ID, k.toString()); - String json = (String) v; + String json = (String) e.getValue(); + log.info(json, LogService.BIZ_ID, k.toString()); try { GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class); oldGatewayGroupMapTmp.put(gg.id, gg); @@ -139,11 +137,11 @@ public class GatewayGroupService { try { GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class); GatewayGroup r = oldGatewayGroupMap.remove(gg.id); - if (gg.isDeleted != GatewayGroup.DELETED && r != null) { + if (!gg.isDeleted && r != null) { gatewayGroupMap.remove(r.group); } updateGatewayGroupMap(gg, gatewayGroupMap, currentGatewayGroupSet); - if (gg.isDeleted != GatewayGroup.DELETED) { + if (!gg.isDeleted) { oldGatewayGroupMap.put(gg.id, gg); } } catch (Throwable t) { @@ -166,7 +164,7 @@ public class GatewayGroupService { } private void updateGatewayGroupMap(GatewayGroup gg, Map gatewayGroupMap, Set currentGatewayGroupSet) { - if (gg.isDeleted == GatewayGroup.DELETED) { + if (gg.isDeleted) { GatewayGroup r = gatewayGroupMap.remove(gg.group); log.info("remove " + r); } else { diff --git a/fizz-core/src/main/java/we/plugin/auth/ServiceConfig.java b/fizz-core/src/main/java/we/plugin/auth/ServiceConfig.java index 49c797b..159e8f4 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ServiceConfig.java +++ b/fizz-core/src/main/java/we/plugin/auth/ServiceConfig.java @@ -94,17 +94,17 @@ public class ServiceConfig { } @JsonIgnore - public List getApiConfigs(Set gatewayGroups, HttpMethod method, String path) { + public List getApiConfigs(boolean dedicatedLineRequest, Set gatewayGroups, HttpMethod method, String path) { ArrayList result = ThreadContext.getArrayList(ThreadContext.arrayList0); for (String gatewayGroup : gatewayGroups) { - List apiConfigs = getApiConfigs(gatewayGroup, method, path); + List apiConfigs = getApiConfigs(dedicatedLineRequest, gatewayGroup, method, path); result.addAll(apiConfigs); } return result; } @JsonIgnore - public List getApiConfigs(String gatewayGroup, HttpMethod method, String path) { + public List getApiConfigs(boolean dedicatedLineRequest, String gatewayGroup, HttpMethod method, String path) { Map>> method2pathPattenMap = apiConfigMap.get(gatewayGroup); if (method2pathPattenMap == null) { return Collections.emptyList(); @@ -112,42 +112,50 @@ public class ServiceConfig { ArrayList result = ThreadContext.getArrayList(); Map> pathPattern2apiConfigsMap = method2pathPattenMap.get(method); if (pathPattern2apiConfigsMap != null) { - checkPathPattern(pathPattern2apiConfigsMap, path, result); + checkPathPattern(pathPattern2apiConfigsMap, dedicatedLineRequest, path, result); } pathPattern2apiConfigsMap = method2pathPattenMap.get(ApiConfig.ALL_METHOD); if (pathPattern2apiConfigsMap != null) { - checkPathPattern(pathPattern2apiConfigsMap, path, result); + checkPathPattern(pathPattern2apiConfigsMap, dedicatedLineRequest, path, result); } return result; } } - private void checkPathPattern(Map> pathPattern2apiConfigMap, String path, ArrayList result) { - Set>> entries = pathPattern2apiConfigMap.entrySet(); - boolean clear = false; - for (Map.Entry> entry : entries) { - String pathPattern = entry.getKey(); - Set apiConfigs = entry.getValue(); - if (pathPattern.equals(path)) { - for (ApiConfig ac : apiConfigs) { - if (ac.access == ApiConfig.ALLOW) { - if (!clear && !result.isEmpty()) { - result.clear(); - clear = true; + private void checkPathPattern(Map> pathPattern2apiConfigMap, boolean dedicatedLineRequest, String path, ArrayList result) { + Set>> entries = pathPattern2apiConfigMap.entrySet(); + boolean clear = false; + for (Map.Entry> entry : entries) { + String pathPattern = entry.getKey(); + Set apiConfigs = entry.getValue(); + if (pathPattern.equals(path)) { + for (ApiConfig ac : apiConfigs) { + if (ac.allowAccess) { + if (!clear && !result.isEmpty()) { + result.clear(); + clear = true; + } + result.add(ac); + } + } + if (clear && !result.isEmpty()) { + return; + } + } else if (UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path)) { + for (ApiConfig ac : apiConfigs) { + if (ac.allowAccess) { + if (dedicatedLineRequest) { + if (ac.dedicatedLine) { + result.add(ac); + } + } else { + if (!ac.dedicatedLine) { + result.add(ac); + } + } } - result.add(ac); } } - if (clear && !result.isEmpty()) { - return; - } - } else if (UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path)) { - for (ApiConfig ac : apiConfigs) { - if (ac.access == ApiConfig.ALLOW) { - result.add(ac); - } - } - } + } // end for } - } } diff --git a/fizz-core/src/main/java/we/proxy/CallbackService.java b/fizz-core/src/main/java/we/proxy/CallbackService.java index 9ceecbe..3b0f6f7 100644 --- a/fizz-core/src/main/java/we/proxy/CallbackService.java +++ b/fizz-core/src/main/java/we/proxy/CallbackService.java @@ -95,45 +95,45 @@ public class CallbackService { ServiceInstance si = service2instMap.get(r.service); if (si == null) { send = fizzWebClient.send2service(traceId, method, r.service, r.path, headers, body) - .onErrorResume( crError(exchange, r, method, headers, body) ); + .onErrorResume( crError(exchange, r, method, headers, body) ); } else { String uri = buildUri(req, si, r.path); send = fizzWebClient.send(traceId, method, uri, headers, body) - .onErrorResume( crError(exchange, r, method, headers, body) ); + .onErrorResume( crError(exchange, r, method, headers, body) ); } } else { send = aggregateService.request(WebUtils.getTraceId(exchange), WebUtils.getClientReqPathPrefix(exchange), method.name(), r.service, r.path, req.getQueryParams(), headers, body) - .onErrorResume( arError(exchange, r, method, headers, body) ); + .onErrorResume( arError(exchange, r, method, headers, body) ); } sends[i] = send; } return Flux.mergeSequential(sends) - .collectList() - .flatMap( - sendResults -> { - Object r = null; - for (int i = 1; i < sendResults.size(); i++) { - r = sendResults.get(i); - if (r instanceof ClientResponse && !(r instanceof FizzFailClientResponse)) { - clean((ClientResponse) r); - } - } - r = sendResults.get(0); - Throwable t = null; - if (r instanceof FizzFailClientResponse) { - t = ((FizzFailClientResponse) r).throwable; - return Mono.error(Utils.runtimeExceptionWithoutStack(t.getMessage())); - } if (r instanceof FailAggregateResult) { - t = ((FailAggregateResult) r).throwable; - return Mono.error(Utils.runtimeExceptionWithoutStack(t.getMessage())); - } else if (r instanceof ClientResponse) { - return genServerResponse(exchange, (ClientResponse) r); - } else { - return aggregateService.genAggregateResponse(exchange, (AggregateResult) r); - } - } - ) - ; + .collectList() + .flatMap( + sendResults -> { + Object r = null; + for (int i = 1; i < sendResults.size(); i++) { + r = sendResults.get(i); + if (r instanceof ClientResponse && !(r instanceof FizzFailClientResponse)) { + clean((ClientResponse) r); + } + } + r = sendResults.get(0); + Throwable t = null; + if (r instanceof FizzFailClientResponse) { + t = ((FizzFailClientResponse) r).throwable; + return Mono.error(Utils.runtimeExceptionWithoutStack(t.getMessage())); + } if (r instanceof FailAggregateResult) { + t = ((FailAggregateResult) r).throwable; + return Mono.error(Utils.runtimeExceptionWithoutStack(t.getMessage())); + } else if (r instanceof ClientResponse) { + return genServerResponse(exchange, (ClientResponse) r); + } else { + return aggregateService.genAggregateResponse(exchange, (AggregateResult) r); + } + } + ) + ; } private Function> crError(ServerWebExchange exchange, Receiver r, HttpMethod method, HttpHeaders headers, DataBuffer body) { @@ -201,14 +201,14 @@ public class CallbackService { log.debug(b.toString(), LogService.BIZ_ID, traceId); } return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers())) - .doOnError(throwable -> clean(remoteResp)).doOnCancel(() -> clean(remoteResp)); + .doOnError(throwable -> clean(remoteResp)).doOnCancel(() -> clean(remoteResp)); } public Mono replay(CallbackReplayReq req) { HashSet gatewayGroups = new HashSet<>(); gatewayGroups.add(req.gatewayGroup); - Result result = apiConfigService.get(gatewayGroups, req.app, req.service, req.method, req.path); + Result result = apiConfigService.get(false, gatewayGroups, req.app, req.service, req.method, req.path); ApiConfig ac = result.data; if (ac == null) { return Mono.just(Result.fail("no api config for " + req.path)); @@ -227,13 +227,13 @@ public class CallbackService { if (si != null) { String uri = buildUri("http", si, r.path); send = fizzWebClient.send(req.id, req.method, uri, req.headers, req.body) - .onErrorResume( crError(req, r.service, r.path) ); + .onErrorResume( crError(req, r.service, r.path) ); sends.add(send); } } else { String traceId = CommonConstants.TRACE_ID_PREFIX + req.id; send = aggregateService.request(traceId, aggrConfigPrefix, req.method.name(), r.service, r.path, null, req.headers, req.body) - .onErrorResume( arError(req, r.service, r.path) ); + .onErrorResume( arError(req, r.service, r.path) ); sends.add(send); } } @@ -243,11 +243,11 @@ public class CallbackService { for (ServiceTypePath stp : req.assignServices) { if (stp.type == ApiConfig.Type.SERVICE_DISCOVERY) { send = fizzWebClient.send2service(req.id, req.method, stp.service, stp.path, req.headers, req.body) - .onErrorResume( crError(req, stp.service, stp.path) ); + .onErrorResume( crError(req, stp.service, stp.path) ); } else { String traceId = CommonConstants.TRACE_ID_PREFIX + req.id; send = aggregateService.request(traceId, aggrConfigPrefix, req.method.name(), stp.service, stp.path, null, req.headers, req.body) - .onErrorResume( arError(req, stp.service, stp.path) ); + .onErrorResume( arError(req, stp.service, stp.path) ); } sends.add(send); } @@ -256,27 +256,27 @@ public class CallbackService { int ss = sends.size(); Mono[] sendArr = sends.toArray(new Mono[ss]); return Flux.mergeSequential(sendArr) - .collectList() - .map( - sendResults -> { - int c = Result.SUCC; - Throwable t = null; - for (int i = 0; i < sendResults.size(); i++) { - Object r = sendResults.get(i); - if (r instanceof FizzFailClientResponse) { - c = Result.FAIL; - t = ((FizzFailClientResponse) r).throwable; - } else if (r instanceof FailAggregateResult) { - c = Result.FAIL; - t = ((FailAggregateResult) r).throwable; - } else if (r instanceof ClientResponse) { - clean((ClientResponse) r); - } - } - return Result.with(c, t); - } - ) - ; + .collectList() + .map( + sendResults -> { + int c = Result.SUCC; + Throwable t = null; + for (int i = 0; i < sendResults.size(); i++) { + Object r = sendResults.get(i); + if (r instanceof FizzFailClientResponse) { + c = Result.FAIL; + t = ((FizzFailClientResponse) r).throwable; + } else if (r instanceof FailAggregateResult) { + c = Result.FAIL; + t = ((FailAggregateResult) r).throwable; + } else if (r instanceof ClientResponse) { + clean((ClientResponse) r); + } + } + return Result.with(c, t); + } + ) + ; } private Function> arError(CallbackReplayReq req, String service, String path) { @@ -304,5 +304,4 @@ public class CallbackService { private void clean(ClientResponse cr) { cr.bodyToMono(Void.class).subscribe(); } - } diff --git a/fizz-core/src/main/java/we/proxy/Route.java b/fizz-core/src/main/java/we/proxy/Route.java index 7d43b1a..5dbb7fb 100644 --- a/fizz-core/src/main/java/we/proxy/Route.java +++ b/fizz-core/src/main/java/we/proxy/Route.java @@ -30,6 +30,8 @@ import java.util.List; public class Route { + public boolean dedicatedLine = false; + public byte type; public HttpMethod method; @@ -64,6 +66,11 @@ public class Route { public long retryInterval = 0; + public Route dedicatedLine(boolean b) { + dedicatedLine = b; + return this; + } + public Route type(int t) { type = (byte) t; return this; diff --git a/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java b/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java index ed1e52b..2c921b2 100644 --- a/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java +++ b/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java @@ -292,7 +292,7 @@ public class RpcInstanceServiceImpl implements RpcInstanceService { return isDeleted; } - public void setIsDeleted(Integer isDeleted) { + public void setDeleted(Integer isDeleted) { this.isDeleted = isDeleted; } diff --git a/fizz-core/src/main/java/we/service_registry/eureka/FizzEurekaHelper.java b/fizz-core/src/main/java/we/service_registry/eureka/FizzEurekaHelper.java index a78bdf8..c814c22 100644 --- a/fizz-core/src/main/java/we/service_registry/eureka/FizzEurekaHelper.java +++ b/fizz-core/src/main/java/we/service_registry/eureka/FizzEurekaHelper.java @@ -39,6 +39,9 @@ import java.util.Map; public abstract class FizzEurekaHelper { + private FizzEurekaHelper() { + } + public static FizzEurekaServiceRegistration getServiceRegistration(FizzEurekaProperties fizzEurekaProperties) { InetUtils inetUtils = fizzEurekaProperties.applicationContext.getBean(InetUtils.class); diff --git a/fizz-core/src/main/java/we/service_registry/nacos/FizzNacosHelper.java b/fizz-core/src/main/java/we/service_registry/nacos/FizzNacosHelper.java index 4949a8e..f7e6871 100644 --- a/fizz-core/src/main/java/we/service_registry/nacos/FizzNacosHelper.java +++ b/fizz-core/src/main/java/we/service_registry/nacos/FizzNacosHelper.java @@ -33,6 +33,9 @@ import java.util.Map; public abstract class FizzNacosHelper { + private FizzNacosHelper() { + } + public static FizzNacosServiceRegistration getServiceRegistration(FizzNacosProperties fizzNacosProperties) { fizzNacosProperties.init(); NacosServiceRegistry nacosServiceRegistry = new NacosServiceRegistry(fizzNacosProperties); diff --git a/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfig.java b/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfig.java index 5b5e0b5..92ead99 100644 --- a/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfig.java +++ b/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfig.java @@ -39,8 +39,6 @@ public class ResourceRateLimitConfig { static final byte IP = 7; } - public static final int DELETED = 1; - public static final String NODE = "_global"; public static final String NODE_RESOURCE = buildResourceId(null, null, NODE, null, null); @@ -53,11 +51,7 @@ public class ResourceRateLimitConfig { public static final String APP_DEFAULT_RESOURCE = buildResourceId(APP_DEFAULT, null, null, null, null); - private static final int ENABLE = 1; - - private static final int UNABLE = 0; - - public int isDeleted = 0; + public boolean isDeleted = false; public int id; @@ -89,8 +83,14 @@ public class ResourceRateLimitConfig { return enable; } + public void setDeleted(int v) { + if (v == 1) { + isDeleted = true; + } + } + public void setEnable(int v) { - if (v == ENABLE) { + if (v == 1) { enable = true; } else { enable = false; diff --git a/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfigService.java b/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfigService.java index 9cb0b08..8e30ebe 100644 --- a/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfigService.java +++ b/fizz-core/src/main/java/we/stats/ratelimit/ResourceRateLimitConfigService.java @@ -77,9 +77,8 @@ public class ResourceRateLimitConfigService { if (k == ReactorUtils.OBJ) { return Flux.just(e); } - Object v = e.getValue(); - log.info("rateLimitConfig: " + v.toString(), LogService.BIZ_ID, k.toString()); - String json = (String) v; + String json = (String) e.getValue(); + log.info("rateLimitConfig: " + json, LogService.BIZ_ID, k.toString()); try { ResourceRateLimitConfig rrlc = JacksonUtils.readValue(json, ResourceRateLimitConfig.class); oldResourceRateLimitConfigMapTmp.put(rrlc.id, rrlc); @@ -127,11 +126,11 @@ public class ResourceRateLimitConfigService { try { ResourceRateLimitConfig rrlc = JacksonUtils.readValue(json, ResourceRateLimitConfig.class); ResourceRateLimitConfig r = oldResourceRateLimitConfigMap.remove(rrlc.id); - if (rrlc.isDeleted != ResourceRateLimitConfig.DELETED && r != null) { + if (!rrlc.isDeleted && r != null) { resourceRateLimitConfigMap.remove(r.getResourceId()); } updateResourceRateLimitConfigMap(rrlc, resourceRateLimitConfigMap); - if (rrlc.isDeleted != ResourceRateLimitConfig.DELETED) { + if (!rrlc.isDeleted) { oldResourceRateLimitConfigMap.put(rrlc.id, rrlc); } } catch (Throwable t) { @@ -155,7 +154,7 @@ public class ResourceRateLimitConfigService { private void updateResourceRateLimitConfigMap(ResourceRateLimitConfig rrlc, Map resourceRateLimitConfigMap) { - if (rrlc.isDeleted == ResourceRateLimitConfig.DELETED) { + if (rrlc.isDeleted) { ResourceRateLimitConfig removedRrlc = resourceRateLimitConfigMap.remove(rrlc.getResourceId()); log.info("remove " + removedRrlc); } else { diff --git a/fizz-core/src/main/java/we/util/WebUtils.java b/fizz-core/src/main/java/we/util/WebUtils.java index b3a4d1a..557c8e4 100644 --- a/fizz-core/src/main/java/we/util/WebUtils.java +++ b/fizz-core/src/main/java/we/util/WebUtils.java @@ -111,7 +111,7 @@ public abstract class WebUtils { public static final String ADMIN_REQUEST = "ar@"; - public static final String FIZZ_API_REQUEST = "far@"; + public static final String FIZZ_REQUEST = "fr@"; private WebUtils() { @@ -121,8 +121,8 @@ public abstract class WebUtils { return exchange.getAttribute(ADMIN_REQUEST) != null; } - public static boolean isFizzApiReq(ServerWebExchange exchange) { - return exchange.getAttribute(FIZZ_API_REQUEST) != null; + public static boolean isFizzReq(ServerWebExchange exchange) { + return exchange.getAttribute(FIZZ_REQUEST) != null; } public static void setGatewayPrefix(String p) { @@ -149,6 +149,11 @@ public abstract class WebUtils { return exchange.getRequest().getHeaders().get(header); } + public static boolean isDedicatedLineRequest(ServerWebExchange exchange) { + String v = exchange.getRequest().getHeaders().getFirst(SystemConfig.FIZZ_DL_ID); + return v != null; + } + public static String getAppId(ServerWebExchange exchange) { HttpHeaders headers = exchange.getRequest().getHeaders(); for (int i = 0; i < appHeaders.size(); i++) { @@ -181,6 +186,18 @@ public abstract class WebUtils { } return null; } + + public static String getDedicatedLineId(ServerWebExchange exchange) { + return getHeaderValue(exchange, SystemConfig.FIZZ_DL_ID); + } + + public static String getDedicatedLineTimestamp(ServerWebExchange exchange) { + return getHeaderValue(exchange, SystemConfig.FIZZ_DL_TS); + } + + public static String getDedicatedLineSign(ServerWebExchange exchange) { + return getHeaderValue(exchange, SystemConfig.FIZZ_DL_SIGN); + } public static String getClientService(ServerWebExchange exchange) { String svc = exchange.getAttribute(clientService); diff --git a/fizz-core/src/test/java/we/api/pairing/ApiPairingDocSetServiceTests.java b/fizz-core/src/test/java/we/api/pairing/ApiPairingDocSetServiceTests.java deleted file mode 100644 index d387b82..0000000 --- a/fizz-core/src/test/java/we/api/pairing/ApiPairingDocSetServiceTests.java +++ /dev/null @@ -1,72 +0,0 @@ -package we.api.pairing; - -import org.junit.Assert; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.data.redis.core.ReactiveStringRedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.http.HttpMethod; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import we.Fizz; -import we.redis.RedisProperties; -import we.redis.RedisServerConfiguration; -import we.redis.RedisTemplateConfiguration; -import we.util.JacksonUtils; -import we.util.ReflectionUtils; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * @author hongqiaowei - */ - -@TestPropertySource("/application.properties") -@SpringJUnitConfig(classes = {RedisProperties.class, RedisTemplateConfiguration.class, RedisServerConfiguration.class}) -public class ApiPairingDocSetServiceTests { - - @Resource - StringRedisTemplate stringRedisTemplate; - - @Resource - ReactiveStringRedisTemplate reactiveStringRedisTemplate; - - ApiPairingDocSetService apiPairingDocSetService; - - @BeforeEach - void beforeEach() throws NoSuchFieldException { - apiPairingDocSetService = new ApiPairingDocSetService(); - ReflectionUtils.set(apiPairingDocSetService, "rt", reactiveStringRedisTemplate); - } - - @Test - void initTest() throws Throwable { - - Fizz.context = new GenericApplicationContext(); - Fizz.context.refresh(); - - Map hash = new HashMap<>(); - hash.put("c", "{\"id\":1,\"name\":\"DocSet1\",\"docs\":[{\"service\":\"we-meb\",\"apis\":[{\"method\":\"GET\",\"path\":\"/getMebInfo\"}]}],\"appIds\":[\"app1\"]}"); - hash.put("d", "{\"id\":2,\"name\":\"DocSet2\",\"docs\":[{\"service\":\"we-meb\",\"apis\":[{\"method\":\"GET\",\"path\":\"/getMebInfo\"}]}],\"appIds\":[\"app1\"]}"); -// hash.put("a", "{\"isDeleted\":1,\"id\":1,\"name\":\"DocSet1\",\"docs\":[{\"service\":\"we-meb\",\"apis\":[{\"method\":\"GET\",\"path\":\"/getMebInfo\"}]}],\"appIds\":[\"app1\"]}"); -// hash.put("b", "{\"isDeleted\":1,\"id\":2,\"name\":\"DocSet2\",\"docs\":[{\"service\":\"we-meb\",\"apis\":[{\"method\":\"GET\",\"path\":\"/getMebInfo\"}]}],\"appIds\":[\"app1\"]}"); - stringRedisTemplate.opsForHash().putAll("fizz_api_pairing_doc", hash); - - apiPairingDocSetService.init(); - Map docSetMap = apiPairingDocSetService.getDocSetMap(); - Map> appDocSetMap = apiPairingDocSetService.getAppDocSetMap(); - Map> serviceExistsInDocSetMap = apiPairingDocSetService.getServiceExistsInDocSetMap(); - Map>> methodPathExistsInDocSetMap = apiPairingDocSetService.getMethodPathExistsInDocSetMap(); -// System.err.println("docSetMap: " + JacksonUtils.writeValueAsString(docSetMap)); -// System.err.println("appDocSetMap: " + JacksonUtils.writeValueAsString(appDocSetMap)); -// System.err.println("serviceExistsInDocSetMap: " + JacksonUtils.writeValueAsString(serviceExistsInDocSetMap)); -// System.err.println("methodPathExistsInDocSetMap: " + JacksonUtils.writeValueAsString(methodPathExistsInDocSetMap)); - - boolean b = apiPairingDocSetService.existsDocSetMatch("app1", HttpMethod.GET, "we-meb", "/getMebInfo"); - Assert.assertTrue(b); - } -} diff --git a/fizz-core/src/test/java/we/dedicated_line/DedicatedLineServiceTests.java b/fizz-core/src/test/java/we/dedicated_line/DedicatedLineServiceTests.java new file mode 100644 index 0000000..5b6d95e --- /dev/null +++ b/fizz-core/src/test/java/we/dedicated_line/DedicatedLineServiceTests.java @@ -0,0 +1,45 @@ +package we.dedicated_line; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.data.redis.core.ReactiveStringRedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import we.Fizz; +import we.redis.RedisProperties; +import we.redis.RedisServerConfiguration; +import we.redis.RedisTemplateConfiguration; +import we.util.ReflectionUtils; + +import javax.annotation.Resource; + +/** + * @author hongqiaowei + */ + +@TestPropertySource("/application.properties") +@SpringJUnitConfig(classes = {RedisProperties.class, RedisTemplateConfiguration.class, RedisServerConfiguration.class}) +public class DedicatedLineServiceTests { + + @Resource + StringRedisTemplate stringRedisTemplate; + + @Resource + ReactiveStringRedisTemplate reactiveStringRedisTemplate; + + DedicatedLineService dedicatedLineService; + + @BeforeEach + void beforeEach() throws NoSuchFieldException { + dedicatedLineService = new DedicatedLineService(); + ReflectionUtils.set(dedicatedLineService, "rt", reactiveStringRedisTemplate); + } + + @Test + void initTest() throws Throwable { + Fizz.context = new GenericApplicationContext(); + Fizz.context.refresh(); + } +} diff --git a/fizz-core/src/test/java/we/plugin/auth/ApiConfig2appsServiceTests.java b/fizz-core/src/test/java/we/plugin/auth/ApiConfig2appsServiceTests.java index 511877e..b20d25c 100644 --- a/fizz-core/src/test/java/we/plugin/auth/ApiConfig2appsServiceTests.java +++ b/fizz-core/src/test/java/we/plugin/auth/ApiConfig2appsServiceTests.java @@ -9,17 +9,13 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import we.redis.RedisProperties; import we.redis.RedisServerConfiguration; import we.redis.RedisTemplateConfiguration; -import we.stats.ratelimit.ResourceRateLimitConfigService; -import we.util.JacksonUtils; import we.util.ReflectionUtils; import javax.annotation.Resource; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -31,17 +27,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class ApiConfig2appsServiceTests { @Resource - StringRedisTemplate stringRedisTemplate; + StringRedisTemplate stringRedisTemplate; @Resource ReactiveStringRedisTemplate reactiveStringRedisTemplate; - ApiConifg2appsService apiConifg2appsService; + ApiConfig2appsService apiConfig2AppsService; @BeforeEach void beforeEach() throws NoSuchFieldException { - apiConifg2appsService = new ApiConifg2appsService(); - ReflectionUtils.set(apiConifg2appsService, "rt", reactiveStringRedisTemplate); + apiConfig2AppsService = new ApiConfig2appsService(); + ReflectionUtils.set(apiConfig2AppsService, "rt", reactiveStringRedisTemplate); } @Test @@ -55,10 +51,10 @@ public class ApiConfig2appsServiceTests { stringRedisTemplate.opsForSet().add("fizz_api_config_app:61_0", "app_b", "app_c"); stringRedisTemplate.opsForSet().add("fizz_api_config_app:61_1", "app_d"); - apiConifg2appsService.init(); + apiConfig2AppsService.init(); Thread.sleep(4000); - Map> apiConfig2appsMap = apiConifg2appsService.getApiConfig2appsMap(); + Map> apiConfig2appsMap = apiConfig2AppsService.getApiConfig2appsMap(); // System.err.println("r: " + JacksonUtils.writeValueAsString(apiConfig2appsMap)); assertTrue(apiConfig2appsMap.get(61).contains("app_c")); } diff --git a/fizz-plugin/pom.xml b/fizz-plugin/pom.xml index ed5b322..29773a6 100644 --- a/fizz-plugin/pom.xml +++ b/fizz-plugin/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.3-beta6 + 2.3.4-beta1 ../pom.xml 4.0.0 @@ -258,7 +258,7 @@ commons-codec commons-codec - + cn.hutool hutool-crypto diff --git a/fizz-plugin/src/main/java/we/plugin/dedicatedline/auth/DedicatedLineApiAuthPluginFilter.java b/fizz-plugin/src/main/java/we/plugin/dedicatedline/auth/DedicatedLineApiAuthPluginFilter.java index db4ec69..962fa16 100644 --- a/fizz-plugin/src/main/java/we/plugin/dedicatedline/auth/DedicatedLineApiAuthPluginFilter.java +++ b/fizz-plugin/src/main/java/we/plugin/dedicatedline/auth/DedicatedLineApiAuthPluginFilter.java @@ -19,15 +19,19 @@ package we.plugin.dedicatedline.auth; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import we.api.pairing.ApiPairingDocSetService; -import we.config.SystemConfig; + +import we.dedicated_line.DedicatedLineService; + + import we.plugin.FizzPluginFilter; import we.plugin.FizzPluginFilterChain; import we.util.ReactorUtils; @@ -46,21 +50,27 @@ public class DedicatedLineApiAuthPluginFilter implements FizzPluginFilter { private static final Logger log = LoggerFactory.getLogger(DedicatedLineApiAuthPluginFilter.class); - public static final String DEDICATED_LINE_API_AUTH_PLUGIN_FILTER = "dedicatedLineCodecPlugin"; + @Resource - private ApiPairingDocSetService apiPairingDocSetService; + private DedicatedLineService dedicatedLineService; + + public static final String DEDICATED_LINE_API_AUTH_PLUGIN_FILTER = "dedicatedLineCodecPlugin"; + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Mono filter(ServerWebExchange exchange, Map config) { String traceId = WebUtils.getTraceId(exchange); try { - String appId = WebUtils.getAppId(exchange); + + String dedicatedLineId = WebUtils.getDedicatedLineId(exchange); String service = WebUtils.getClientService(exchange); String path = WebUtils.getClientReqPath(exchange); HttpMethod method = exchange.getRequest().getMethod(); - if (apiPairingDocSetService.existsDocSetMatch(appId, method, service, path)) { + if (dedicatedLineService.auth(dedicatedLineId, method, service, path)) { + // Go to next plugin Mono next = FizzPluginFilterChain.next(exchange); return next.defaultIfEmpty(ReactorUtils.NULL).flatMap(nil -> { diff --git a/fizz-spring-boot-starter/pom.xml b/fizz-spring-boot-starter/pom.xml index 3b9ef5c..fc74eef 100644 --- a/fizz-spring-boot-starter/pom.xml +++ b/fizz-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.3-beta6 + 2.3.4-beta1 ../pom.xml 4.0.0 diff --git a/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories b/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories index ee8ee28..2a375f2 100644 --- a/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -26,7 +26,7 @@ we.fizz.AggregateService,\ we.fizz.ConfigLoader,\ we.listener.AggregateChannelListener,\ we.plugin.auth.ApiConfigService,\ -we.plugin.auth.ApiConifg2appsService,\ +we.plugin.auth.ApiConfig2appsService,\ we.plugin.auth.AppService,\ we.plugin.auth.AuthPluginFilter,\ we.plugin.auth.GatewayGroupService,\ @@ -46,4 +46,4 @@ we.proxy.NacosUriSelector,\ we.proxy.RpcInstanceServiceImpl,\ we.stats.ratelimit.ResourceRateLimitConfigService,\ we.global_resource.GlobalResourceService,\ -we.api.pairing.FizzApiPairingWebServer +we.dedicated_line.DedicatedLineWebServer diff --git a/pom.xml b/pom.xml index ae33119..b4cea25 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 2.2.13.RELEASE 5.2.18.RELEASE - Dysprosium-SR24 + Dysprosium-SR25 5.3.7.RELEASE 2.2.6.RELEASE 4.1.70.Final @@ -37,7 +37,7 @@ fizz-gateway-community ${project.artifactId} fizz gateway community - 2.3.3-beta6 + 2.3.4-beta1 pom fizz-common @@ -433,13 +433,13 @@ netty-tcnative-boringssl-static ${netty-tcnative.version} - + cn.hutool hutool-crypto 5.7.16 - + @@ -596,16 +596,4 @@ - - - nexus-releases - local private nexus - http://gzmaven.bestwehotel.com/nexus/content/repositories/releases/ - - - nexus-snapshots - local private nexus - http://gzmaven.bestwehotel.com/nexus/content/repositories/snapshots/ - -