feat:
1. 服务编排调试模式开关从接口配置抽出来独立控制 2. 新增网关分组管理 3. 新增插件管理 4. appid管理新增自定义配置和IP段配置 5. 路由管理展示优化 6. 接口统计新增统计数据和图表展示
This commit is contained in:
9
src/main/java/we/FizzAppContext.java
Normal file
9
src/main/java/we/FizzAppContext.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package we;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
public class FizzAppContext {
|
||||||
|
|
||||||
|
public static ConfigurableApplicationContext appContext;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,20 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package we;
|
package we;
|
||||||
|
|
||||||
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
|
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
|
||||||
@@ -24,20 +7,16 @@ import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
|||||||
import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
|
import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
/**
|
@SpringBootApplication(
|
||||||
* @author lancer
|
exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class},
|
||||||
* @author francis
|
scanBasePackages = {"we", "com.wh"}
|
||||||
*/
|
)
|
||||||
@SpringBootApplication(exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class})
|
@EnableApolloConfig
|
||||||
// @EnableApolloConfig
|
|
||||||
@EnableDiscoveryClient
|
@EnableDiscoveryClient
|
||||||
public class FizzGatewayApplication {
|
public class FizzGatewayApplication {
|
||||||
|
|
||||||
public static ConfigurableApplicationContext appContext;
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
FizzGatewayApplication.appContext = SpringApplication.run(FizzGatewayApplication.class, args);
|
FizzAppContext.appContext = SpringApplication.run(FizzGatewayApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ import org.apache.logging.log4j.core.LoggerContext;
|
|||||||
import org.apache.logging.log4j.core.config.Configuration;
|
import org.apache.logging.log4j.core.config.Configuration;
|
||||||
import org.apache.logging.log4j.core.config.ConfigurationFactory;
|
import org.apache.logging.log4j.core.config.ConfigurationFactory;
|
||||||
import org.apache.logging.log4j.core.config.ConfigurationSource;
|
import org.apache.logging.log4j.core.config.ConfigurationSource;
|
||||||
import org.apache.logging.log4j.core.config.Order;
|
|
||||||
import org.apache.logging.log4j.core.config.plugins.Plugin;
|
|
||||||
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder;
|
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = AggrWebClientConfig.prefix)
|
@ConfigurationProperties(prefix = AggrWebClientConfig.prefix)
|
||||||
public class AggrWebClientConfig extends WebClientConfig {
|
public class AggrWebClientConfig extends WebClientConfig {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
/**
|
/**
|
||||||
* @author unknown
|
* @author unknown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AppConfigProperties {
|
public class AppConfigProperties {
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = ProxyWebClientConfig.prefix)
|
@ConfigurationProperties(prefix = ProxyWebClientConfig.prefix)
|
||||||
public class ProxyWebClientConfig extends WebClientConfig {
|
public class ProxyWebClientConfig extends WebClientConfig {
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ import org.springframework.data.redis.connection.lettuce.LettucePoolingClientCon
|
|||||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class RedisReactiveConfig {
|
public abstract class RedisReactiveConfig {
|
||||||
|
|
||||||
protected static final Logger log = LoggerFactory.getLogger(RedisReactiveConfig.class);
|
protected static final Logger log = LoggerFactory.getLogger(RedisReactiveConfig.class);
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ import we.util.Constants;
|
|||||||
import we.util.Utils;
|
import we.util.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class RedisReactiveProperties {
|
public abstract class RedisReactiveProperties {
|
||||||
|
|
||||||
private String host = "127.0.0.1";
|
private String host = "127.0.0.1";
|
||||||
private int port = 6379;
|
private int port = 6379;
|
||||||
private String password;
|
private String password;
|
||||||
private int database = 0;
|
private int database = 0;
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return host;
|
return host;
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ package we.config;
|
|||||||
import com.ctrip.framework.apollo.model.ConfigChange;
|
import com.ctrip.framework.apollo.model.ConfigChange;
|
||||||
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
||||||
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
||||||
|
|
||||||
import we.plugin.auth.GatewayGroup;
|
import we.plugin.auth.GatewayGroup;
|
||||||
import we.util.Constants;
|
import we.util.Constants;
|
||||||
import we.util.JacksonUtils;
|
import we.util.JacksonUtils;
|
||||||
import we.util.NetworkUtils;
|
import we.util.NetworkUtils;
|
||||||
import we.util.WebUtils;
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -36,8 +38,9 @@ import javax.management.RuntimeErrorException;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SystemConfig {
|
public class SystemConfig {
|
||||||
|
|
||||||
@@ -51,19 +54,19 @@ public class SystemConfig {
|
|||||||
|
|
||||||
private Set<String> logHeaderSet = new HashSet<>();
|
private Set<String> logHeaderSet = new HashSet<>();
|
||||||
|
|
||||||
@Value("${gateway-group:}")
|
// @Value("${gateway-group:}")
|
||||||
private String gatewayGroup;
|
// private String gatewayGroup;
|
||||||
|
//
|
||||||
private Map<String, Set<Character>> server2gatewayGroupSetMap = new HashMap<>();
|
// private Map<String, Set<Character>> server2gatewayGroupSetMap = new HashMap<>();
|
||||||
|
//
|
||||||
private Set<Character> currentServerGatewayGroupSet;
|
// private Set<Character> currentServerGatewayGroupSet;
|
||||||
|
|
||||||
@Value("${spring.profiles.active}")
|
@Value("${spring.profiles.active}")
|
||||||
private String profile;
|
private String profile;
|
||||||
|
|
||||||
public Set<Character> getCurrentServerGatewayGroupSet() {
|
// public Set<Character> getCurrentServerGatewayGroupSet() {
|
||||||
return currentServerGatewayGroupSet;
|
// return currentServerGatewayGroupSet;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public Set<String> getLogHeaderSet() {
|
public Set<String> getLogHeaderSet() {
|
||||||
return logHeaderSet;
|
return logHeaderSet;
|
||||||
@@ -73,7 +76,7 @@ public class SystemConfig {
|
|||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
afterLogResponseBodySet();
|
afterLogResponseBodySet();
|
||||||
afterLogHeadersSet();
|
afterLogHeadersSet();
|
||||||
afterGatewayGroupSet();
|
// afterGatewayGroupSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afterLogResponseBodySet() {
|
private void afterLogResponseBodySet() {
|
||||||
@@ -90,42 +93,42 @@ public class SystemConfig {
|
|||||||
log.info("log header list: " + logHeaderSet.toString());
|
log.info("log header list: " + logHeaderSet.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afterGatewayGroupSet() {
|
// private void afterGatewayGroupSet() {
|
||||||
server2gatewayGroupSetMap.clear();
|
// server2gatewayGroupSetMap.clear();
|
||||||
if (StringUtils.isNotBlank(gatewayGroup)) {
|
// if (StringUtils.isNotBlank(gatewayGroup)) {
|
||||||
Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach(
|
// Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach(
|
||||||
gg -> {
|
// gg -> {
|
||||||
Character group = Character.valueOf(gg.charAt(0));
|
// Character group = Character.valueOf(gg.charAt(0));
|
||||||
String servers = gg.substring(gg.indexOf(':') + 1);
|
// String servers = gg.substring(gg.indexOf(':') + 1);
|
||||||
Arrays.stream(StringUtils.split(servers, ',')).forEach(
|
// Arrays.stream(StringUtils.split(servers, ',')).forEach(
|
||||||
s -> {
|
// s -> {
|
||||||
Set<Character> gs = server2gatewayGroupSetMap.get(s);
|
// Set<Character> gs = server2gatewayGroupSetMap.get(s);
|
||||||
if (gs == null) {
|
// if (gs == null) {
|
||||||
gs = new HashSet<>();
|
// gs = new HashSet<>();
|
||||||
server2gatewayGroupSetMap.put(s, gs);
|
// server2gatewayGroupSetMap.put(s, gs);
|
||||||
}
|
// }
|
||||||
gs.add(group);
|
// gs.add(group);
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap));
|
// log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap));
|
||||||
String serverIp = NetworkUtils.getServerIp();
|
// String serverIp = NetworkUtils.getServerIp();
|
||||||
currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp);
|
// currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp);
|
||||||
if (currentServerGatewayGroupSet == null) {
|
// if (currentServerGatewayGroupSet == null) {
|
||||||
if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
|
// if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
|
||||||
currentServerGatewayGroupSet = new HashSet<>();
|
// currentServerGatewayGroupSet = new HashSet<>();
|
||||||
currentServerGatewayGroupSet.add(GatewayGroup.C);
|
// currentServerGatewayGroupSet.add(GatewayGroup.C);
|
||||||
currentServerGatewayGroupSet.add(GatewayGroup.B);
|
// currentServerGatewayGroupSet.add(GatewayGroup.B);
|
||||||
currentServerGatewayGroupSet.add(GatewayGroup.T);
|
// currentServerGatewayGroupSet.add(GatewayGroup.T);
|
||||||
server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet);
|
// server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet);
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("no gateway group config for " + serverIp);
|
// throw new RuntimeException("no gateway group config for " + serverIp);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet);
|
// log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@ApolloConfigChangeListener
|
@ApolloConfigChangeListener
|
||||||
private void configChangeListter(ConfigChangeEvent cce) {
|
private void configChangeListter(ConfigChangeEvent cce) {
|
||||||
@@ -142,10 +145,10 @@ public class SystemConfig {
|
|||||||
} else if (p.equals("log.headers")) {
|
} else if (p.equals("log.headers")) {
|
||||||
logHeaders = nv;
|
logHeaders = nv;
|
||||||
afterLogHeadersSet();
|
afterLogHeadersSet();
|
||||||
} else if (p.equals("gateway-group")) {
|
} /*else if (p.equals("gateway-group")) {
|
||||||
gatewayGroup = nv;
|
gatewayGroup = nv;
|
||||||
afterGatewayGroupSet();
|
afterGatewayGroupSet();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,31 +39,32 @@ import java.time.Duration;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class WebClientConfig {
|
public abstract class WebClientConfig {
|
||||||
|
|
||||||
protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
|
protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private int maxConnections = 2_000;
|
private int maxConnections = 2_000;
|
||||||
|
|
||||||
private Duration maxIdleTime = Duration.ofMillis(40_000);
|
private Duration maxIdleTime = Duration.ofMillis(40_000);
|
||||||
|
|
||||||
private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
|
private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
|
||||||
|
|
||||||
private long connReadTimeout = 20_000;
|
private long connReadTimeout = 20_000;
|
||||||
|
|
||||||
private long connWriteTimeout = 20_000;
|
private long connWriteTimeout = 20_000;
|
||||||
|
|
||||||
private int chConnTimeout = 20_000;
|
private int chConnTimeout = 20_000;
|
||||||
|
|
||||||
private boolean chTcpNodelay = true;
|
private boolean chTcpNodelay = true;
|
||||||
|
|
||||||
private boolean chSoKeepAlive = true;
|
private boolean chSoKeepAlive = true;
|
||||||
|
|
||||||
private boolean compress = false;
|
private boolean compress = false;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@@ -148,7 +149,9 @@ public abstract class WebClientConfig {
|
|||||||
private ConnectionProvider getConnectionProvider() {
|
private ConnectionProvider getConnectionProvider() {
|
||||||
String cpName = name + "-cp";
|
String cpName = name + "-cp";
|
||||||
ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections)
|
ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections)
|
||||||
.pendingAcquireTimeout(pendingAcquireTimeout).maxIdleTime(maxIdleTime).build();
|
.pendingAcquireTimeout(pendingAcquireTimeout)
|
||||||
|
.maxIdleTime(maxIdleTime)
|
||||||
|
.build();
|
||||||
log.info(cpName + ' ' + cp);
|
log.info(cpName + ' ' + cp);
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ import reactor.netty.resources.LoopResources;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "server")
|
@ConfigurationProperties(prefix = "server")
|
||||||
@EnableConfigurationProperties(ServerProperties.class)
|
@EnableConfigurationProperties(ServerProperties.class)
|
||||||
@@ -124,9 +125,9 @@ public class WebFluxConfig {
|
|||||||
// .channel(NioServerSocketChannel.class)
|
// .channel(NioServerSocketChannel.class)
|
||||||
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
|
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
|
||||||
// .option(ChannelOption.SO_BACKLOG, 8192)
|
// .option(ChannelOption.SO_BACKLOG, 8192)
|
||||||
.childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
|
.childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
|
|
||||||
package we.controller;
|
package we.controller;
|
||||||
|
|
||||||
import we.fizz.ConfigLoader;
|
|
||||||
import we.util.ScriptUtils;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.fizz.ConfigLoader;
|
||||||
|
import we.util.ScriptUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
/**
|
/**
|
||||||
* @author unknown
|
* @author unknown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/config")
|
@RequestMapping(value = "/config")
|
||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
@@ -45,7 +46,7 @@ public class ConfigController {
|
|||||||
return Mono.just("ok");
|
return Mono.just("ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
// add by lancer
|
// add by hongqiaowei
|
||||||
@PostMapping(value = "/fullUpdCommonJs", consumes = MediaType.TEXT_PLAIN_VALUE)
|
@PostMapping(value = "/fullUpdCommonJs", consumes = MediaType.TEXT_PLAIN_VALUE)
|
||||||
public Mono<String> fullUpdCommonJs(ServerWebExchange exchange, @RequestBody String js) {
|
public Mono<String> fullUpdCommonJs(ServerWebExchange exchange, @RequestBody String js) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -18,50 +18,64 @@
|
|||||||
package we.controller;
|
package we.controller;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import we.plugin.auth.ApiConfigService;
|
import com.alibaba.fastjson.JSON;
|
||||||
import we.plugin.auth.AppService;
|
|
||||||
import we.util.JacksonUtils;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.plugin.auth.ApiConfigService;
|
||||||
|
import we.plugin.auth.AppService;
|
||||||
|
import we.plugin.auth.GatewayGroupService;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author unknown
|
* @author unknown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class HealthController {
|
public class HealthController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private GatewayGroupService gatewayGroupService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AppService appService;
|
private AppService appService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiConfigService apiConfigService;
|
private ApiConfigService apiConfigService;
|
||||||
|
|
||||||
@GetMapping("/time")
|
// add by hongqiaowei
|
||||||
public Mono<String> time(ServerWebExchange exchange) throws Exception{
|
|
||||||
Date d = new Date();
|
|
||||||
return Mono.just("Time: " + d.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// add by lancer
|
|
||||||
@GetMapping("/sysgc")
|
@GetMapping("/sysgc")
|
||||||
public Mono<String> sysgc(ServerWebExchange exchange) throws Exception {
|
public Mono<String> sysgc(ServerWebExchange exchange) throws Exception {
|
||||||
System.gc();
|
System.gc();
|
||||||
return Mono.just("sysgc done");
|
return Mono.just("sysgc done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/gatewayGroups")
|
||||||
|
public Mono<String> gatewayGroups(ServerWebExchange exchange) throws Exception {
|
||||||
|
return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.gatewayGroupMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/currentGatewayGroups")
|
||||||
|
public Mono<String> currentGatewayGroups(ServerWebExchange exchange) throws Exception {
|
||||||
|
return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.currentGatewayGroupSet));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/apps")
|
@GetMapping("/apps")
|
||||||
public Mono<String> apps(ServerWebExchange exchange) throws Exception {
|
public Mono<String> apps(ServerWebExchange exchange) throws Exception {
|
||||||
return Mono.just(JacksonUtils.writeValueAsString(appService.getAppMap()));
|
return Mono.just(JacksonUtils.writeValueAsString(appService.getAppMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/apiConfigs")
|
@GetMapping("/serviceConfigs")
|
||||||
public Mono<String> apiConfigs(ServerWebExchange exchange) throws Exception {
|
public Mono<String> apiConfigs(ServerWebExchange exchange) throws Exception {
|
||||||
return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.getApp2gatewayGroupMap()));
|
return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.serviceConfigMap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,6 @@
|
|||||||
|
|
||||||
package we.controller;
|
package we.controller;
|
||||||
|
|
||||||
import we.controller.req.BaseManagerConfigReq;
|
|
||||||
import we.controller.req.GetConfigStrReq;
|
|
||||||
import we.controller.req.GetConfigReq;
|
|
||||||
import we.controller.resp.ConfigStrResp;
|
|
||||||
import we.controller.resp.ConfigResp;
|
|
||||||
import we.fizz.ConfigLoader;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -30,6 +24,12 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.controller.req.BaseManagerConfigReq;
|
||||||
|
import we.controller.req.GetConfigReq;
|
||||||
|
import we.controller.req.GetConfigStrReq;
|
||||||
|
import we.controller.resp.ConfigResp;
|
||||||
|
import we.controller.resp.ConfigStrResp;
|
||||||
|
import we.fizz.ConfigLoader;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
package we.controller.resp;
|
package we.controller.resp;
|
||||||
|
|
||||||
import we.fizz.ConfigLoader;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import we.fizz.ConfigLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合配置响应实体类
|
* 聚合配置响应实体类
|
||||||
* @author zhongjie
|
* @author zhongjie
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.config.SystemConfig;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@@ -27,11 +26,14 @@ import org.springframework.web.cors.CorsConfiguration;
|
|||||||
import org.springframework.web.cors.reactive.CorsWebFilter;
|
import org.springframework.web.cors.reactive.CorsWebFilter;
|
||||||
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
||||||
|
|
||||||
|
import we.config.SystemConfig;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CorsFilterConfig {
|
public class CorsFilterConfig {
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.exception.StopAndResponseException;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
@@ -29,10 +27,13 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
|
|||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebExceptionHandler;
|
import org.springframework.web.server.WebExceptionHandler;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.exception.StopAndResponseException;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class FilterExceptionHandlerConfig {
|
public class FilterExceptionHandlerConfig {
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ package we.filter;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class FilterResult {
|
public class FilterResult {
|
||||||
|
|
||||||
public String id;
|
public String id;
|
||||||
|
|||||||
@@ -38,24 +38,24 @@ import org.springframework.web.server.WebFilter;
|
|||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.core.scheduler.Schedulers;
|
||||||
import we.constants.CommonConstants;
|
import we.constants.CommonConstants;
|
||||||
import we.fizz.AggregateResource;
|
import we.fizz.AggregateResource;
|
||||||
import we.fizz.AggregateResult;
|
import we.fizz.AggregateResult;
|
||||||
import we.fizz.ConfigLoader;
|
import we.fizz.ConfigLoader;
|
||||||
import we.fizz.Pipeline;
|
import we.fizz.Pipeline;
|
||||||
import we.fizz.input.Input;
|
import we.fizz.input.Input;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
import we.util.Constants;
|
import we.util.Constants;
|
||||||
import we.util.MapUtil;
|
import we.util.MapUtil;
|
||||||
import we.util.WebUtils;
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
import reactor.core.scheduler.Schedulers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author francis
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Order(2)
|
@Order(2)
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
@@ -27,10 +25,14 @@ import org.springframework.web.server.ServerWebExchange;
|
|||||||
import org.springframework.web.server.WebFilter;
|
import org.springframework.web.server.WebFilter;
|
||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Order(0)
|
@Order(0)
|
||||||
public class FizzLogFilter implements WebFilter {
|
public class FizzLogFilter implements WebFilter {
|
||||||
@@ -46,7 +48,7 @@ public class FizzLogFilter implements WebFilter {
|
|||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
return chain.filter(exchange).doAfterTerminate(
|
return chain.filter(exchange).doAfterTerminate(
|
||||||
() -> {
|
() -> {
|
||||||
StringBuilder b = new StringBuilder(160);
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
WebUtils.request2stringBuilder(exchange, b);
|
WebUtils.request2stringBuilder(exchange, b);
|
||||||
b.append(resp).append(exchange.getResponse().getStatusCode())
|
b.append(resp).append(exchange.getResponse().getStatusCode())
|
||||||
.append(in) .append(System.currentTimeMillis() - startTime);
|
.append(in) .append(System.currentTimeMillis() - startTime);
|
||||||
|
|||||||
@@ -17,15 +17,6 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.config.SystemConfig;
|
|
||||||
import we.plugin.FixedPluginFilter;
|
|
||||||
import we.plugin.PluginConfig;
|
|
||||||
import we.plugin.PluginFilter;
|
|
||||||
import we.plugin.auth.*;
|
|
||||||
import we.plugin.stat.StatPluginFilter;
|
|
||||||
import we.util.Constants;
|
|
||||||
import we.util.ReactorUtils;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -37,15 +28,24 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.plugin.FixedPluginFilter;
|
||||||
|
import we.plugin.PluginConfig;
|
||||||
|
import we.plugin.PluginFilter;
|
||||||
|
import we.plugin.auth.ApiConfig;
|
||||||
|
import we.plugin.auth.ApiConfigService;
|
||||||
|
import we.plugin.auth.AuthPluginFilter;
|
||||||
|
import we.plugin.stat.StatPluginFilter;
|
||||||
|
import we.util.ReactorUtils;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component(PreFilter.PRE_FILTER)
|
@Component(PreFilter.PRE_FILTER)
|
||||||
@Order(1)
|
@Order(1)
|
||||||
public class PreFilter extends ProxyAggrFilter {
|
public class PreFilter extends ProxyAggrFilter {
|
||||||
@@ -62,25 +62,12 @@ public class PreFilter extends ProxyAggrFilter {
|
|||||||
@Value("${b-services:x}")
|
@Value("${b-services:x}")
|
||||||
private Set<String> bServices = new HashSet<>();
|
private Set<String> bServices = new HashSet<>();
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SystemConfig systemConfig;
|
|
||||||
|
|
||||||
@Resource(name = StatPluginFilter.STAT_PLUGIN_FILTER)
|
@Resource(name = StatPluginFilter.STAT_PLUGIN_FILTER)
|
||||||
private StatPluginFilter statPluginFilter;
|
private StatPluginFilter statPluginFilter;
|
||||||
|
|
||||||
@Resource(name = AuthPluginFilter.AUTH_PLUGIN_FILTER)
|
@Resource(name = AuthPluginFilter.AUTH_PLUGIN_FILTER)
|
||||||
private AuthPluginFilter authPluginFilter;
|
private AuthPluginFilter authPluginFilter;
|
||||||
|
|
||||||
private char currentGatewayGroup;
|
|
||||||
@PostConstruct
|
|
||||||
public void setCurrentGatewayGroup() {
|
|
||||||
for (Character gg : systemConfig.getCurrentServerGatewayGroupSet()) {
|
|
||||||
currentGatewayGroup = gg.charValue();
|
|
||||||
log.info("current gateway group is " + currentGatewayGroup);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> doFilter(ServerWebExchange exchange, WebFilterChain chain) {
|
public Mono<Void> doFilter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
|
|
||||||
@@ -88,24 +75,11 @@ public class PreFilter extends ProxyAggrFilter {
|
|||||||
Map<String, String> appendHdrs = new HashMap<>(6, 1.0f);
|
Map<String, String> appendHdrs = new HashMap<>(6, 1.0f);
|
||||||
Map<String, Object> eas = exchange.getAttributes(); eas.put(WebUtils.FILTER_CONTEXT, fc);
|
Map<String, Object> eas = exchange.getAttributes(); eas.put(WebUtils.FILTER_CONTEXT, fc);
|
||||||
eas.put(WebUtils.APPEND_HEADERS, appendHdrs);
|
eas.put(WebUtils.APPEND_HEADERS, appendHdrs);
|
||||||
eas.put(WebUtils.CGG, currentGatewayGroup);
|
|
||||||
|
|
||||||
String app = WebUtils.getHeaderValue(exchange, WebUtils.APP_HEADER);
|
String app = WebUtils.getHeaderValue(exchange, WebUtils.APP_HEADER);
|
||||||
if (StringUtils.isBlank(app)) {
|
if (StringUtils.isNotBlank(app)) {
|
||||||
if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
|
eas.put(WebUtils.APP_HEADER, app);
|
||||||
String service = WebUtils.getServiceId(exchange);
|
|
||||||
if (bServices.contains(service)) {
|
|
||||||
app = App.TO_B;
|
|
||||||
} else {
|
|
||||||
app = App.TO_C;
|
|
||||||
}
|
|
||||||
} else if (currentGatewayGroup == GatewayGroup.B) {
|
|
||||||
app = App.TO_B;
|
|
||||||
} else {
|
|
||||||
app = App.TO_C;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
eas.put(WebUtils.APP_HEADER, app);
|
|
||||||
|
|
||||||
Mono vm = statPluginFilter.filter(exchange, null, null);
|
Mono vm = statPluginFilter.filter(exchange, null, null);
|
||||||
return chain(exchange, vm, authPluginFilter).defaultIfEmpty(ReactorUtils.NULL)
|
return chain(exchange, vm, authPluginFilter).defaultIfEmpty(ReactorUtils.NULL)
|
||||||
@@ -120,11 +94,7 @@ public class PreFilter extends ProxyAggrFilter {
|
|||||||
if (ac.pluginConfigs == null || ac.pluginConfigs.isEmpty()) {
|
if (ac.pluginConfigs == null || ac.pluginConfigs.isEmpty()) {
|
||||||
return m.flatMap(func(exchange, chain));
|
return m.flatMap(func(exchange, chain));
|
||||||
} else {
|
} else {
|
||||||
return m.flatMap(
|
return m.flatMap(e -> {return executeManagedPluginFilters(exchange, ac.pluginConfigs);})
|
||||||
e -> {
|
|
||||||
return executeManagedPluginFilters(exchange, ac.pluginConfigs);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.defaultIfEmpty(ReactorUtils.NULL).flatMap(func(exchange, chain));
|
.defaultIfEmpty(ReactorUtils.NULL).flatMap(func(exchange, chain));
|
||||||
}
|
}
|
||||||
} else if (authRes == ApiConfigService.Access.YES) {
|
} else if (authRes == ApiConfigService.Access.YES) {
|
||||||
|
|||||||
@@ -17,15 +17,16 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebFilter;
|
import org.springframework.web.server.WebFilter;
|
||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO 类名调整
|
// TODO 类名调整
|
||||||
public abstract class ProxyAggrFilter implements WebFilter {
|
public abstract class ProxyAggrFilter implements WebFilter {
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package we.filter;
|
package we.filter;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.legacy.RespEntity;
|
|
||||||
import we.proxy.FizzWebClient;
|
|
||||||
import we.util.ThreadContext;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@@ -36,14 +31,23 @@ import org.springframework.web.reactive.function.client.ClientResponse;
|
|||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.legacy.RespEntity;
|
||||||
|
import we.plugin.auth.ApiConfig;
|
||||||
|
import we.plugin.auth.AuthPluginFilter;
|
||||||
|
import we.proxy.FizzWebClient;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
public class RouteFilter extends ProxyAggrFilter {
|
public class RouteFilter extends ProxyAggrFilter {
|
||||||
@@ -79,7 +83,6 @@ public class RouteFilter extends ProxyAggrFilter {
|
|||||||
private Mono<Void> doFilter0(ServerWebExchange exchange, WebFilterChain chain) {
|
private Mono<Void> doFilter0(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
|
|
||||||
ServerHttpRequest clientReq = exchange.getRequest();
|
ServerHttpRequest clientReq = exchange.getRequest();
|
||||||
String rid = clientReq.getId();
|
|
||||||
HttpHeaders hdrs = new HttpHeaders();
|
HttpHeaders hdrs = new HttpHeaders();
|
||||||
clientReq.getHeaders().forEach(
|
clientReq.getHeaders().forEach(
|
||||||
(h, vs) -> {
|
(h, vs) -> {
|
||||||
@@ -101,37 +104,65 @@ public class RouteFilter extends ProxyAggrFilter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fizzWebClient.proxySend2service(rid, clientReq.getMethod(), WebUtils.getServiceId(exchange), WebUtils.getRelativeUri(exchange), hdrs, exchange.getRequest().getBody()).flatMap(
|
ApiConfig ac = null;
|
||||||
remoteResp -> {
|
Object authRes = WebUtils.getFilterResultDataItem(exchange, AuthPluginFilter.AUTH_PLUGIN_FILTER, AuthPluginFilter.RESULT);
|
||||||
ServerHttpResponse clientResp = exchange.getResponse();
|
if (authRes instanceof ApiConfig) {
|
||||||
clientResp.setStatusCode(remoteResp.statusCode());
|
ac = (ApiConfig) authRes;
|
||||||
HttpHeaders clientRespHeaders = clientResp.getHeaders();
|
}
|
||||||
HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
|
|
||||||
remoteRespHeaders.entrySet().forEach(
|
String relativeUri = WebUtils.getRelativeUri(exchange);
|
||||||
h -> {
|
if (ac == null || ac.proxyMode == ApiConfig.DIRECT_PROXY_MODE) {
|
||||||
String k = h.getKey();
|
return send(exchange, WebUtils.getServiceId(exchange), relativeUri, hdrs);
|
||||||
if (clientRespHeaders.containsKey(k)) {
|
} else {
|
||||||
if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
|
String realUri;
|
||||||
|| k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) {
|
String backendUrl = ac.getNextBackendUrl();
|
||||||
} else {
|
int acpLen = ac.path.length();
|
||||||
clientRespHeaders.put(k, h.getValue());
|
if (acpLen == 1) {
|
||||||
}
|
realUri = backendUrl + relativeUri;
|
||||||
} else {
|
} else {
|
||||||
clientRespHeaders.put(k, h.getValue());
|
realUri = backendUrl + relativeUri.substring(acpLen);
|
||||||
}
|
}
|
||||||
}
|
relativeUri.substring(acpLen);
|
||||||
);
|
return fizzWebClient.send(clientReq.getId(), clientReq.getMethod(), realUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange));
|
||||||
if (log.isDebugEnabled()) {
|
}
|
||||||
StringBuilder b = ThreadContext.getStringBuilder();
|
|
||||||
WebUtils.response2stringBuilder(rid, remoteResp, b);
|
|
||||||
log.debug(b.toString(), LogService.BIZ_ID, rid);
|
|
||||||
}
|
|
||||||
return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers()))
|
|
||||||
.doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<Void> send(ServerWebExchange exchange, String service, String relativeUri, HttpHeaders hdrs) {
|
||||||
|
ServerHttpRequest clientReq = exchange.getRequest();
|
||||||
|
return fizzWebClient.proxySend2service(clientReq.getId(), clientReq.getMethod(), service, relativeUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Function<ClientResponse, Mono<? extends Void>> genServerResponse(ServerWebExchange exchange) {
|
||||||
|
return remoteResp -> {
|
||||||
|
ServerHttpResponse clientResp = exchange.getResponse();
|
||||||
|
clientResp.setStatusCode(remoteResp.statusCode());
|
||||||
|
HttpHeaders clientRespHeaders = clientResp.getHeaders();
|
||||||
|
HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
|
||||||
|
remoteRespHeaders.entrySet().forEach(
|
||||||
|
h -> {
|
||||||
|
String k = h.getKey();
|
||||||
|
if (clientRespHeaders.containsKey(k)) {
|
||||||
|
if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
|
||||||
|
|| k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) {
|
||||||
|
} else {
|
||||||
|
clientRespHeaders.put(k, h.getValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clientRespHeaders.put(k, h.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
|
String rid = exchange.getRequest().getId();
|
||||||
|
WebUtils.response2stringBuilder(rid, remoteResp, b);
|
||||||
|
log.debug(b.toString(), LogService.BIZ_ID, rid);
|
||||||
|
}
|
||||||
|
return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers()))
|
||||||
|
.doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void cleanup(ClientResponse clientResponse) {
|
private void cleanup(ClientResponse clientResponse) {
|
||||||
if (clientResponse != null) {
|
if (clientResponse != null) {
|
||||||
clientResponse.bodyToMono(Void.class).subscribe();
|
clientResponse.bodyToMono(Void.class).subscribe();
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ package we.fizz;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
|
||||||
import we.config.AppConfigProperties;
|
import we.config.AppConfigProperties;
|
||||||
import we.fizz.input.ClientInputConfig;
|
import we.fizz.input.ClientInputConfig;
|
||||||
import we.fizz.input.Input;
|
import we.fizz.input.Input;
|
||||||
import we.fizz.input.InputType;
|
import we.fizz.input.InputType;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.noear.snack.ONode;
|
import org.noear.snack.ONode;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -32,6 +34,10 @@ import org.springframework.util.CollectionUtils;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE;
|
||||||
|
import static we.util.Constants.Symbol.FORWARD_SLASH;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -41,9 +47,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE;
|
|
||||||
import static we.util.Constants.Symbol.FORWARD_SLASH;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author francis
|
* @author francis
|
||||||
@@ -56,7 +59,7 @@ public class ConfigLoader {
|
|||||||
* 聚合配置存放Hash的Key
|
* 聚合配置存放Hash的Key
|
||||||
*/
|
*/
|
||||||
private static final String AGGREGATE_HASH_KEY = "fizz_aggregate_config";
|
private static final String AGGREGATE_HASH_KEY = "fizz_aggregate_config";
|
||||||
|
|
||||||
private static Map<String, String> aggregateResources = null;
|
private static Map<String, String> aggregateResources = null;
|
||||||
private static Map<String, ConfigInfo> resourceKey2ConfigInfoMap = null;
|
private static Map<String, ConfigInfo> resourceKey2ConfigInfoMap = null;
|
||||||
private static Map<String, String> aggregateId2ResourceKeyMap = null;
|
private static Map<String, String> aggregateId2ResourceKeyMap = null;
|
||||||
@@ -80,8 +83,13 @@ public class ConfigLoader {
|
|||||||
clientInputConfig.setHeaders(cfgNode.select("$.headers").toObject(Map.class));
|
clientInputConfig.setHeaders(cfgNode.select("$.headers").toObject(Map.class));
|
||||||
clientInputConfig.setMethod(cfgNode.select("$.method").getString());
|
clientInputConfig.setMethod(cfgNode.select("$.method").getString());
|
||||||
clientInputConfig.setPath(cfgNode.select("$.path").getString());
|
clientInputConfig.setPath(cfgNode.select("$.path").getString());
|
||||||
if(cfgNode.select("$.debug") != null) {
|
if(clientInputConfig.getPath().startsWith(TEST_PATH_PREFIX)) {
|
||||||
clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean());
|
// always enable debug for testing
|
||||||
|
clientInputConfig.setDebug(true);
|
||||||
|
}else {
|
||||||
|
if(cfgNode.select("$.debug") != null) {
|
||||||
|
clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clientInputConfig.setType(InputType.valueOf(cfgNode.select("$.type").getString()));
|
clientInputConfig.setType(InputType.valueOf(cfgNode.select("$.type").getString()));
|
||||||
clientInputConfig.setLangDef(cfgNode.select("$.langDef").toObject(Map.class));
|
clientInputConfig.setLangDef(cfgNode.select("$.langDef").toObject(Map.class));
|
||||||
|
|||||||
@@ -25,11 +25,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
|
||||||
import we.fizz.input.ClientInputConfig;
|
|
||||||
import we.fizz.input.InputConfig;
|
|
||||||
import we.schema.util.I18nUtils;
|
import we.schema.util.I18nUtils;
|
||||||
import we.util.JsonSchemaUtils;
|
|
||||||
|
|
||||||
import org.noear.snack.ONode;
|
import org.noear.snack.ONode;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -37,14 +33,17 @@ import org.springframework.util.CollectionUtils;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.fizz.input.Input;
|
|
||||||
import we.fizz.input.PathMapping;
|
|
||||||
import we.fizz.input.ScriptHelper;
|
|
||||||
import we.util.MapUtil;
|
|
||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.fizz.input.ClientInputConfig;
|
||||||
|
import we.fizz.input.Input;
|
||||||
|
import we.fizz.input.InputConfig;
|
||||||
|
import we.fizz.input.PathMapping;
|
||||||
|
import we.fizz.input.ScriptHelper;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.util.JsonSchemaUtils;
|
||||||
|
import we.util.MapUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ import org.springframework.web.reactive.function.BodyInserters;
|
|||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
import we.fizz.input.Input;
|
import we.fizz.input.Input;
|
||||||
import we.fizz.input.InputConfig;
|
import we.fizz.input.InputConfig;
|
||||||
import we.fizz.input.InputContext;
|
import we.fizz.input.InputContext;
|
||||||
import we.fizz.input.InputFactory;
|
import we.fizz.input.InputFactory;
|
||||||
import we.fizz.input.InputType;
|
import we.fizz.input.InputType;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author linwaiwai
|
* @author linwaiwai
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ package we.fizz.input;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
import we.fizz.StepContext;
|
import we.fizz.StepContext;
|
||||||
import we.fizz.StepResponse;
|
import we.fizz.StepResponse;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author linwaiwai
|
* @author linwaiwai
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ import org.springframework.web.util.UriComponents;
|
|||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.FizzGatewayApplication;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.FizzAppContext;
|
||||||
import we.constants.CommonConstants;
|
import we.constants.CommonConstants;
|
||||||
import we.fizz.StepContext;
|
import we.fizz.StepContext;
|
||||||
import we.fizz.StepResponse;
|
import we.fizz.StepResponse;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
import we.proxy.FizzWebClient;
|
import we.proxy.FizzWebClient;
|
||||||
import we.util.MapUtil;
|
import we.util.MapUtil;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author linwaiwai
|
* @author linwaiwai
|
||||||
@@ -222,7 +222,7 @@ public class RequestInput extends Input {
|
|||||||
String aggrPath = (String)inputContext.getStepContext().getInputReqAttr("path");
|
String aggrPath = (String)inputContext.getStepContext().getInputReqAttr("path");
|
||||||
String aggrService = aggrPath.split("\\/")[2];
|
String aggrService = aggrPath.split("\\/")[2];
|
||||||
|
|
||||||
FizzWebClient client = FizzGatewayApplication.appContext.getBean(FizzWebClient.class);
|
FizzWebClient client = FizzAppContext.appContext.getBean(FizzWebClient.class);
|
||||||
return client.aggrSend(aggrService, aggrMethod, aggrPath, null, method, url,
|
return client.aggrSend(aggrService, aggrMethod, aggrPath, null, method, url,
|
||||||
MapUtil.toHttpHeaders(headers), request.get("body"), (long)timeout);
|
MapUtil.toHttpHeaders(headers), request.get("body"), (long)timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.ctrip.framework.apollo.core.utils.StringUtils;
|
import com.ctrip.framework.apollo.core.utils.StringUtils;
|
||||||
|
|
||||||
import we.constants.CommonConstants;
|
import we.constants.CommonConstants;
|
||||||
import we.exception.StopAndResponseException;
|
import we.exception.StopAndResponseException;
|
||||||
import we.fizz.StepContext;
|
import we.fizz.StepContext;
|
||||||
|
|||||||
@@ -1,33 +1,31 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package we.flume.clients.log4j2appender;
|
package we.flume.clients.log4j2appender;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lancer
|
|
||||||
*/
|
|
||||||
public enum LogService {
|
public enum LogService {
|
||||||
|
|
||||||
BIZ_ID, HANDLE_STGY;
|
BIZ_ID, HANDLE_STGY, APP;
|
||||||
|
|
||||||
|
public static void cleanBizId() {
|
||||||
|
setBizId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getBizId() {
|
||||||
|
return ThreadContext.get(Constants.BIZ_ID);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setBizId(Object bizId) {
|
public static void setBizId(Object bizId) {
|
||||||
|
ThreadContext.set(Constants.BIZ_ID, bizId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toKF(String topic) {
|
public static String toKF(String topic) {
|
||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toESaKF(String topic) {
|
||||||
|
return Constants.AND + topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Constants {
|
||||||
|
static final String BIZ_ID = "bizId";
|
||||||
|
static final char AND = '&';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package we.flume.clients.log4j2appender;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/** for internal use */
|
||||||
|
public abstract class ThreadContext {
|
||||||
|
|
||||||
|
private static ThreadLocal<Map<String, Object>> tl = new ThreadLocal<>();
|
||||||
|
private static final int mapCap = 16;
|
||||||
|
private static final float mapLoadFactor = 1.0f;
|
||||||
|
|
||||||
|
private static final String sb = "sb";
|
||||||
|
private static final int sbCap = 256;
|
||||||
|
|
||||||
|
public static StringBuilder getStringBuilder() {
|
||||||
|
return getStringBuilder(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringBuilder getStringBuilder(boolean clean) {
|
||||||
|
Map<String, Object> m = getMap();
|
||||||
|
StringBuilder b = (StringBuilder) m.get(sb);
|
||||||
|
if (b == null) {
|
||||||
|
b = new StringBuilder(sbCap);
|
||||||
|
m.put(sb, b);
|
||||||
|
} else {
|
||||||
|
if (clean) {
|
||||||
|
b.delete(0, b.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleDateFormat getSimpleDateFormat(String pattern) {
|
||||||
|
Map<String, Object> m = getMap();
|
||||||
|
SimpleDateFormat sdf = (SimpleDateFormat) m.get(pattern);
|
||||||
|
if (sdf == null) {
|
||||||
|
sdf = new SimpleDateFormat(pattern);
|
||||||
|
m.put(pattern, sdf);
|
||||||
|
}
|
||||||
|
return sdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object get(String key, Class<?> clz) {
|
||||||
|
Object obj = get(key);
|
||||||
|
if (obj == null) {
|
||||||
|
try {
|
||||||
|
obj = clz.newInstance();
|
||||||
|
set(key, obj);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> getMap() {
|
||||||
|
Map<String, Object> m = tl.get();
|
||||||
|
if (m == null) {
|
||||||
|
m = new HashMap<>(mapCap, mapLoadFactor);
|
||||||
|
tl.set(m);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object get(String key) {
|
||||||
|
return getMap().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void set(String key, Object obj) {
|
||||||
|
getMap().put(key, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,13 +17,15 @@
|
|||||||
|
|
||||||
package we.legacy;
|
package we.legacy;
|
||||||
|
|
||||||
import we.util.Constants;
|
|
||||||
import we.util.ThreadContext;
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import we.util.Constants;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RespEntity {
|
public class RespEntity {
|
||||||
|
|
||||||
private static final String f0 = "{\"msgCode\":";
|
private static final String f0 = "{\"msgCode\":";
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package we.listener;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import we.fizz.ConfigLoader;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -31,14 +31,16 @@ import org.springframework.util.StringUtils;
|
|||||||
import reactor.core.Disposable;
|
import reactor.core.Disposable;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
import we.fizz.ConfigLoader;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_MESSAGE_LISTENER_CONTAINER;
|
import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_MESSAGE_LISTENER_CONTAINER;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合Channel监听器
|
* 聚合Channel监听器
|
||||||
* @author zhongjie
|
* @author zhongjie
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package we.listener;
|
package we.listener;
|
||||||
|
|
||||||
import we.config.RedisReactiveConfig;
|
|
||||||
import we.config.RedisReactiveProperties;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -27,6 +25,9 @@ import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
|||||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
import org.springframework.data.redis.listener.ReactiveRedisMessageListenerContainer;
|
import org.springframework.data.redis.listener.ReactiveRedisMessageListenerContainer;
|
||||||
|
|
||||||
|
import we.config.RedisReactiveConfig;
|
||||||
|
import we.config.RedisReactiveProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合配置Redis配置
|
* 聚合配置Redis配置
|
||||||
* @author zhongjie
|
* @author zhongjie
|
||||||
|
|||||||
@@ -14,16 +14,19 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin;
|
package we.plugin;
|
||||||
|
|
||||||
import we.FizzGatewayApplication;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import we.FizzAppContext;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class FixedPluginFilter extends PluginFilter {
|
public abstract class FixedPluginFilter extends PluginFilter {
|
||||||
@@ -56,7 +59,7 @@ public abstract class FixedPluginFilter extends PluginFilter {
|
|||||||
);
|
);
|
||||||
String fid = pf.getId();
|
String fid = pf.getId();
|
||||||
fixedPluginFilterMap.put(fid, pf);
|
fixedPluginFilterMap.put(fid, pf);
|
||||||
StringBuilder b = new StringBuilder(256);
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
b.append("add ").append(fid).append('\n');
|
b.append("add ").append(fid).append('\n');
|
||||||
b.append("fixed plugin filters: \n");
|
b.append("fixed plugin filters: \n");
|
||||||
filters2sb(b);
|
filters2sb(b);
|
||||||
@@ -67,7 +70,7 @@ public abstract class FixedPluginFilter extends PluginFilter {
|
|||||||
if (fixedPluginFilterList == null) {
|
if (fixedPluginFilterList == null) {
|
||||||
synchronized (fixedPluginFilterMap) {
|
synchronized (fixedPluginFilterMap) {
|
||||||
if (fixedPluginFilterList == null) {
|
if (fixedPluginFilterList == null) {
|
||||||
Map<String, FixedPluginFilter> beansOfType = FizzGatewayApplication.appContext.getBeansOfType(FixedPluginFilter.class);
|
Map<String, FixedPluginFilter> beansOfType = FizzAppContext.appContext.getBeansOfType(FixedPluginFilter.class);
|
||||||
if (beansOfType == null || beansOfType.isEmpty()) {
|
if (beansOfType == null || beansOfType.isEmpty()) {
|
||||||
fixedPluginFilterList = Collections.EMPTY_LIST;
|
fixedPluginFilterList = Collections.EMPTY_LIST;
|
||||||
} else {
|
} else {
|
||||||
@@ -82,7 +85,7 @@ public abstract class FixedPluginFilter extends PluginFilter {
|
|||||||
fixedPluginFilterMap.put(f.getId(), f);
|
fixedPluginFilterMap.put(f.getId(), f);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
StringBuilder b = new StringBuilder(256);
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
b.append("fixed plugin filters: \n");
|
b.append("fixed plugin filters: \n");
|
||||||
filters2sb(b);
|
filters2sb(b);
|
||||||
log.info(b.toString());
|
log.info(b.toString());
|
||||||
|
|||||||
@@ -14,17 +14,17 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin;
|
package we.plugin;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import we.util.JacksonUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PluginConfig {
|
public class PluginConfig {
|
||||||
|
|||||||
@@ -14,23 +14,24 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin;
|
package we.plugin;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.filter.FilterResult;
|
|
||||||
import we.legacy.RespEntity;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.filter.FilterResult;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.legacy.RespEntity;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class PluginFilter {
|
public abstract class PluginFilter {
|
||||||
|
|||||||
@@ -14,66 +14,90 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
import we.plugin.PluginConfig;
|
import we.plugin.PluginConfig;
|
||||||
import we.util.Constants;
|
import we.util.Constants;
|
||||||
import we.util.JacksonUtils;
|
import we.util.JacksonUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ApiConfig {
|
public class ApiConfig {
|
||||||
|
|
||||||
public static final int DELETED = 1;
|
public static final int DELETED = 1;
|
||||||
|
|
||||||
public static final char ALLOW = 'a';
|
public static final char ALLOW = 'a';
|
||||||
|
|
||||||
public static final char FORBID = 'f';
|
public static final char FORBID = 'f';
|
||||||
|
|
||||||
public int id; // tb_api_auth.id
|
public static final byte DIRECT_PROXY_MODE = 1;
|
||||||
|
|
||||||
public int isDeleted = 0; // tb_api_auth.is_deleted
|
public static final byte PREFIX_REWRITE_PROXY_MODE = 2;
|
||||||
|
|
||||||
public char gatewayGroup; // tb_api_auth.gateway_group
|
@JsonIgnore
|
||||||
|
public int id; // tb_api_auth.id
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public int isDeleted = 0; // tb_api_auth.is_deleted
|
||||||
|
|
||||||
|
public Set<String> gatewayGroups = new HashSet<>(6);
|
||||||
|
|
||||||
public String service;
|
public String service;
|
||||||
|
|
||||||
public HttpMethod method = HttpMethod.X;
|
public HttpMethod method = HttpMethod.X;
|
||||||
|
|
||||||
public String path = String.valueOf(Constants.Symbol.FORWARD_SLASH);
|
public String path = String.valueOf(Constants.Symbol.FORWARD_SLASH);
|
||||||
|
|
||||||
private String app;
|
public Set<String> apps = new HashSet<>(6);
|
||||||
|
|
||||||
public char access = ALLOW;
|
public byte proxyMode = DIRECT_PROXY_MODE;
|
||||||
|
|
||||||
|
private AtomicInteger counter = new AtomicInteger(-1);
|
||||||
|
|
||||||
|
public List<String> backendUrls;
|
||||||
|
|
||||||
|
public char access = ALLOW;
|
||||||
|
|
||||||
public List<PluginConfig> pluginConfigs;
|
public List<PluginConfig> pluginConfigs;
|
||||||
|
|
||||||
public void setApp(String a) {
|
public void setGatewayGroup(String ggs) {
|
||||||
app = a;
|
if (StringUtils.isBlank(ggs)) {
|
||||||
|
gatewayGroups.add("*");
|
||||||
|
} else {
|
||||||
|
Arrays.stream(StringUtils.split(ggs, ',')).forEach(
|
||||||
|
gg -> {
|
||||||
|
gatewayGroups.add(gg.trim());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String app() {
|
public void setApp(String as) {
|
||||||
if (StringUtils.isBlank(app)) {
|
if (StringUtils.isBlank(as)) {
|
||||||
if (gatewayGroup == GatewayGroup.C) {
|
apps.add("*");
|
||||||
app = App.TO_C;
|
} else {
|
||||||
} else if (gatewayGroup == GatewayGroup.B) {
|
Arrays.stream(StringUtils.split(as, ',')).forEach(
|
||||||
app = App.TO_B;
|
a -> {
|
||||||
} else {
|
apps.add(a.trim());
|
||||||
throw new RuntimeException(toString() + " no app", null, false, false) {};
|
}
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
return app;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPath(String p) {
|
public void setPath(String p) {
|
||||||
if (StringUtils.isNotBlank(p)) {
|
if (StringUtils.isNotBlank(p)) {
|
||||||
path = p;
|
path = p.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +108,16 @@ public class ApiConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public String getNextBackendUrl() {
|
||||||
|
int idx = counter.incrementAndGet();
|
||||||
|
if (idx < 0) {
|
||||||
|
counter.set(0);
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
return backendUrls.get(idx % backendUrls.size());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JacksonUtils.writeValueAsString(this);
|
return JacksonUtils.writeValueAsString(this);
|
||||||
|
|||||||
@@ -14,15 +14,12 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import com.ctrip.framework.apollo.model.ConfigChange;
|
import com.ctrip.framework.apollo.model.ConfigChange;
|
||||||
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
||||||
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.config.SystemConfig;
|
|
||||||
import we.listener.AggregateRedisConfig;
|
|
||||||
import we.util.*;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -36,6 +33,9 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.listener.AggregateRedisConfig;
|
||||||
|
import we.util.*;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -43,7 +43,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -61,9 +61,9 @@ public class ApiConfigService {
|
|||||||
|
|
||||||
private static final String secretKeyHeader = "fizz-secretkey";
|
private static final String secretKeyHeader = "fizz-secretkey";
|
||||||
|
|
||||||
private Map<String, GatewayGroup> app2gatewayGroupMap = new HashMap<>(32);
|
public Map<String, ServiceConfig> serviceConfigMap = new HashMap<>(128);
|
||||||
|
|
||||||
private Map<Integer, ApiConfig> apiConfigMap = new HashMap<>(128);
|
private Map<Integer, ApiConfig> apiConfigMap = new HashMap<>(128);
|
||||||
|
|
||||||
// TODO XXX
|
// TODO XXX
|
||||||
@Value("${serviceWhiteList:x}")
|
@Value("${serviceWhiteList:x}")
|
||||||
@@ -94,14 +94,17 @@ public class ApiConfigService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Value("${auth.compatible-wh:false}")
|
||||||
|
private boolean compatibleWh;
|
||||||
|
|
||||||
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
|
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
|
||||||
private ReactiveStringRedisTemplate rt;
|
private ReactiveStringRedisTemplate rt;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SystemConfig systemConfig;
|
private AppService appService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AppService appService;
|
private GatewayGroupService gatewayGroupService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private CustomAuth customAuth;
|
private CustomAuth customAuth;
|
||||||
@@ -127,7 +130,7 @@ public class ApiConfigService {
|
|||||||
try {
|
try {
|
||||||
ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class);
|
ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class);
|
||||||
apiConfigMap.put(ac.id, ac);
|
apiConfigMap.put(ac.id, ac);
|
||||||
updateApp2gatewayGroupMap(ac);
|
updateServiceConfigMap(ac);
|
||||||
return Flux.just(e);
|
return Flux.just(e);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throwable[0] = t;
|
throwable[0] = t;
|
||||||
@@ -167,9 +170,9 @@ public class ApiConfigService {
|
|||||||
ApiConfig r = apiConfigMap.remove(ac.id);
|
ApiConfig r = apiConfigMap.remove(ac.id);
|
||||||
if (ac.isDeleted != ApiConfig.DELETED && r != null) {
|
if (ac.isDeleted != ApiConfig.DELETED && r != null) {
|
||||||
r.isDeleted = ApiConfig.DELETED;
|
r.isDeleted = ApiConfig.DELETED;
|
||||||
updateApp2gatewayGroupMap(r);
|
updateServiceConfigMap(r);
|
||||||
}
|
}
|
||||||
updateApp2gatewayGroupMap(ac);
|
updateServiceConfigMap(ac);
|
||||||
if (ac.isDeleted != ApiConfig.DELETED) {
|
if (ac.isDeleted != ApiConfig.DELETED) {
|
||||||
apiConfigMap.put(ac.id, ac);
|
apiConfigMap.put(ac.id, ac);
|
||||||
}
|
}
|
||||||
@@ -192,24 +195,21 @@ public class ApiConfigService {
|
|||||||
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
|
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateApp2gatewayGroupMap(ApiConfig ac) {
|
private void updateServiceConfigMap(ApiConfig ac) {
|
||||||
GatewayGroup gg = app2gatewayGroupMap.get(ac.app());
|
ServiceConfig sc = serviceConfigMap.get(ac.service);
|
||||||
if (ac.isDeleted == ApiConfig.DELETED) {
|
if (ac.isDeleted == ApiConfig.DELETED) {
|
||||||
if (gg == null) {
|
if (sc == null) {
|
||||||
log.info("no gateway group for " + ac.app());
|
log.info("no " + ac.service + " config to delete");
|
||||||
} else {
|
} else {
|
||||||
gg.remove(ac);
|
sc.remove(ac);
|
||||||
if (gg.getServiceConfigMap().isEmpty()) {
|
|
||||||
app2gatewayGroupMap.remove(ac.app());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (gg == null) {
|
if (sc == null) {
|
||||||
gg = new GatewayGroup(ac.gatewayGroup);
|
sc = new ServiceConfig(ac.service);
|
||||||
app2gatewayGroupMap.put(ac.app(), gg);
|
serviceConfigMap.put(ac.service, sc);
|
||||||
gg.add(ac);
|
sc.add(ac);
|
||||||
} else {
|
} else {
|
||||||
gg.update(ac);
|
sc.update(ac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,13 +218,15 @@ public class ApiConfigService {
|
|||||||
|
|
||||||
YES (null),
|
YES (null),
|
||||||
|
|
||||||
CANT_ACCESS_CURRENT_GATEWAY_GROUP ("cant access current gateway group"),
|
NO_SERVICE_CONFIG ("no service config"),
|
||||||
|
|
||||||
NO_GATEWAY_GROUP_FOR_APP ("no gateway group for app"),
|
NO_API_CONFIG ("no api config"),
|
||||||
|
|
||||||
NO_APP_CONFIG_FOR_APP ("no app config for app"),
|
GATEWAY_GROUP_CANT_PROXY_API ("gateway group cant proxy api"),
|
||||||
|
|
||||||
ORIGIN_IP_NOT_IN_WHITE_LIST ("origin ip not in white list"),
|
APP_NOT_IN_API_LEGAL_APPS ("app not in api legal apps"),
|
||||||
|
|
||||||
|
IP_NOT_IN_WHITE_LIST ("ip not in white list"),
|
||||||
|
|
||||||
NO_TIMESTAMP_OR_SIGN ("no timestamp or sign"),
|
NO_TIMESTAMP_OR_SIGN ("no timestamp or sign"),
|
||||||
|
|
||||||
@@ -236,10 +238,6 @@ public class ApiConfigService {
|
|||||||
|
|
||||||
SERVICE_NOT_OPEN ("service not open"),
|
SERVICE_NOT_OPEN ("service not open"),
|
||||||
|
|
||||||
NO_SERVICE_EXPOSE_TO_APP ("no service expose to app"),
|
|
||||||
|
|
||||||
SERVICE_API_NOT_EXPOSE_TO_APP ("service api not expose to app"),
|
|
||||||
|
|
||||||
CANT_ACCESS_SERVICE_API ("cant access service api");
|
CANT_ACCESS_SERVICE_API ("cant access service api");
|
||||||
|
|
||||||
private String reason;
|
private String reason;
|
||||||
@@ -254,7 +252,6 @@ public class ApiConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Mono<Object> canAccess(ServerWebExchange exchange) {
|
public Mono<Object> canAccess(ServerWebExchange exchange) {
|
||||||
|
|
||||||
ServerHttpRequest req = exchange.getRequest();
|
ServerHttpRequest req = exchange.getRequest();
|
||||||
HttpHeaders hdrs = req.getHeaders();
|
HttpHeaders hdrs = req.getHeaders();
|
||||||
LogService.setBizId(req.getId());
|
LogService.setBizId(req.getId());
|
||||||
@@ -262,56 +259,83 @@ public class ApiConfigService {
|
|||||||
WebUtils.getServiceId(exchange), req.getMethod(), WebUtils.getReqPath(exchange));
|
WebUtils.getServiceId(exchange), req.getMethod(), WebUtils.getReqPath(exchange));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Object> canAccess(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String secretKey,
|
private Mono<Object> canAccess(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String secretKey,
|
||||||
String service, HttpMethod method, String path) {
|
String service, HttpMethod method, String path) {
|
||||||
|
|
||||||
GatewayGroup gg = app2gatewayGroupMap.get(app); boolean toCorBapp = App.TO_C.equals(app) || App.TO_B.equals(app);
|
if (!whiteListSet.contains(service)) { // TODO XXX
|
||||||
|
return Mono.just(Access.SERVICE_NOT_OPEN);
|
||||||
if (gg == null) {
|
}
|
||||||
if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult("no gateway group for " + app, Access.NO_GATEWAY_GROUP_FOR_APP); }
|
ServiceConfig sc = serviceConfigMap.get(service);
|
||||||
|
if (sc == null) {
|
||||||
|
if (compatibleWh) {
|
||||||
|
return Mono.just(Access.YES);
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult(service + Constants.Symbol.BLANK + Access.NO_SERVICE_CONFIG.getReason(), Access.NO_SERVICE_CONFIG);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Set<Character> currentServerGatewayGroupSet = systemConfig.getCurrentServerGatewayGroupSet();
|
String api = ThreadContext.getStringBuilder().append(service).append(Constants.Symbol.BLANK).append(method.name()).append(Constants.Symbol.BLANK + path).toString();
|
||||||
if (currentServerGatewayGroupSet.contains(gg.id)) {
|
ApiConfig ac0 = null;
|
||||||
Mono<Access> am = Mono.just(Access.YES);
|
for (String g : gatewayGroupService.currentGatewayGroupSet) { // compatible
|
||||||
App a = appService.getApp(app);
|
ac0 = sc.getApiConfig(method, path, g, app);
|
||||||
if (a == null) {
|
if (ac0 != null) {
|
||||||
if (!toCorBapp) { return logWarnAndResult("no app config for " + app, Access.NO_APP_CONFIG_FOR_APP); }
|
break;
|
||||||
} else if (a.useWhiteList && !a.ips.contains(ip)) {
|
|
||||||
return logWarnAndResult(ip + " not in " + app + " white list", Access.ORIGIN_IP_NOT_IN_WHITE_LIST);
|
|
||||||
} else if (a.useAuth) {
|
|
||||||
if (a.authType == App.SIGN_AUTH) {
|
|
||||||
if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(sign)) { return logWarnAndResult(app + " lack timestamp " + timestamp + " or sign " + sign, Access.NO_TIMESTAMP_OR_SIGN); }
|
|
||||||
else if (!validate(app, timestamp, a.secretkey, sign)) { return logWarnAndResult(app + " sign " + sign + " invalid", Access.SIGN_INVALID); }
|
|
||||||
} else if (customAuth == null) {
|
|
||||||
return logWarnAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH);
|
|
||||||
} else {
|
|
||||||
am = customAuth.auth(exchange, app, ip, timestamp, sign, secretKey, a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return am.flatMap(
|
|
||||||
v -> {
|
|
||||||
LogService.setBizId(exchange.getRequest().getId());
|
|
||||||
if (v == Access.CUSTOM_AUTH_REJECT || v != Access.YES) { return Mono.just(Access.CUSTOM_AUTH_REJECT); }
|
|
||||||
if (!whiteListSet.contains(service)) { return Mono.just(Access.SERVICE_NOT_OPEN); } // TODO XXX
|
|
||||||
ServiceConfig sc = gg.getServiceConfig(service);
|
|
||||||
if (sc == null) {
|
|
||||||
if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult("no service expose to " + app, Access.NO_SERVICE_EXPOSE_TO_APP); }
|
|
||||||
} else {
|
|
||||||
ApiConfig ac = sc.getApiConfig(method, path);
|
|
||||||
if (ac == null) {
|
|
||||||
if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult(service + ' ' + method.name() + ' ' + path + " not expose to " + app, Access.SERVICE_API_NOT_EXPOSE_TO_APP); }
|
|
||||||
} else if (ac.access == ApiConfig.ALLOW) {
|
|
||||||
return Mono.just(ac);
|
|
||||||
} else {
|
|
||||||
return logWarnAndResult(app + " cant access " + service + ' ' + method.name() + ' ' + path, Access.CANT_ACCESS_SERVICE_API);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return logWarnAndResult(app + " cant access " + currentServerGatewayGroupSet, Access.CANT_ACCESS_CURRENT_GATEWAY_GROUP);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ApiConfig ac = ac0;
|
||||||
|
if (ac == null) {
|
||||||
|
if (compatibleWh) {
|
||||||
|
return Mono.just(Access.YES);
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult(api + " no api config", Access.NO_API_CONFIG);
|
||||||
|
}
|
||||||
|
} else if (gatewayGroupService.currentGatewayGroupIn(ac.gatewayGroups)) {
|
||||||
|
if (ac.apps.contains(App.ALL_APP)) {
|
||||||
|
return allow(api, ac);
|
||||||
|
} else if (app != null && ac.apps.contains(app)) {
|
||||||
|
if (ac.access == ApiConfig.ALLOW) {
|
||||||
|
App a = appService.getApp(app);
|
||||||
|
if (a.useWhiteList && !a.allow(ip)) {
|
||||||
|
return logWarnAndResult(ip + " not in " + app + " white list", Access.IP_NOT_IN_WHITE_LIST);
|
||||||
|
} else if (a.useAuth) {
|
||||||
|
if (a.authType == App.SIGN_AUTH) {
|
||||||
|
if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(sign)) {
|
||||||
|
return logWarnAndResult(app + " lack timestamp " + timestamp + " or sign " + sign, Access.NO_TIMESTAMP_OR_SIGN);
|
||||||
|
} else if (!validate(app, timestamp, a.secretkey, sign)) {
|
||||||
|
return logWarnAndResult(app + " sign " + sign + " invalid", Access.SIGN_INVALID);
|
||||||
|
} else {
|
||||||
|
return Mono.just(ac);
|
||||||
|
}
|
||||||
|
} else if (customAuth == null) {
|
||||||
|
return logWarnAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH);
|
||||||
|
} else {
|
||||||
|
return customAuth.auth(exchange, app, ip, timestamp, sign, secretKey, a).flatMap(v -> {
|
||||||
|
if (v == Access.YES) {
|
||||||
|
return Mono.just(ac);
|
||||||
|
} else {
|
||||||
|
return Mono.just(Access.CUSTOM_AUTH_REJECT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Mono.just(ac);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult("cant access " + api, Access.CANT_ACCESS_SERVICE_API);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult(app + " not in " + api + " legal apps", Access.APP_NOT_IN_API_LEGAL_APPS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult(gatewayGroupService.currentGatewayGroupSet + " cant proxy " + api, Access.GATEWAY_GROUP_CANT_PROXY_API);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mono<Object> allow(String api, ApiConfig ac) {
|
||||||
|
if (ac.access == ApiConfig.ALLOW) {
|
||||||
|
return Mono.just(ac);
|
||||||
|
} else {
|
||||||
|
return logWarnAndResult("cant access " + api, Access.CANT_ACCESS_SERVICE_API);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,12 +345,8 @@ public class ApiConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean validate(String app, String timestamp, String secretKey, String sign) {
|
private static boolean validate(String app, String timestamp, String secretKey, String sign) {
|
||||||
StringBuilder b = new StringBuilder(128);
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
b.append(app).append(Constants.Symbol.UNDERLINE).append(timestamp).append(Constants.Symbol.UNDERLINE).append(secretKey);
|
b.append(app).append(Constants.Symbol.UNDERLINE).append(timestamp).append(Constants.Symbol.UNDERLINE).append(secretKey);
|
||||||
return sign.equals(DigestUtils.md532(b.toString()));
|
return sign.equals(DigestUtils.md532(b.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, GatewayGroup> getApp2gatewayGroupMap() {
|
|
||||||
return app2gatewayGroupMap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,25 +14,24 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import we.util.JacksonUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import we.util.Constants;
|
||||||
import java.util.Collections;
|
import we.util.JacksonUtils;
|
||||||
import java.util.Set;
|
|
||||||
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
public static final String TO_C = "2c";
|
public static final String ALL_APP = "*";
|
||||||
|
|
||||||
public static final String TO_B = "2b";
|
|
||||||
|
|
||||||
public static final int DELETED = 1;
|
public static final int DELETED = 1;
|
||||||
|
|
||||||
@@ -56,7 +55,9 @@ public class App {
|
|||||||
|
|
||||||
public boolean useWhiteList = false;
|
public boolean useWhiteList = false;
|
||||||
|
|
||||||
public Set<String> ips = Collections.emptySet();
|
public String config;
|
||||||
|
|
||||||
|
private Map<String, String[]> ips = new HashMap<>(6);
|
||||||
|
|
||||||
public void setUseAuth(int i) {
|
public void setUseAuth(int i) {
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
@@ -72,10 +73,69 @@ public class App {
|
|||||||
|
|
||||||
public void setIps(String ips) {
|
public void setIps(String ips) {
|
||||||
if (StringUtils.isNotBlank(ips)) {
|
if (StringUtils.isNotBlank(ips)) {
|
||||||
this.ips = Arrays.stream(StringUtils.split(ips, ',')).collect(Collectors.toSet());
|
Arrays.stream(StringUtils.split(ips, ',')).forEach(
|
||||||
|
ip -> {
|
||||||
|
ip = ip.trim();
|
||||||
|
int i = ip.lastIndexOf('.');
|
||||||
|
String subnet = ip.substring(0, i).trim();
|
||||||
|
String addrSeg = ip.substring(i + 1).trim();
|
||||||
|
if ("*".equals(addrSeg)) {
|
||||||
|
this.ips.put(subnet, new String[]{"2", "254"});
|
||||||
|
} else if (addrSeg.indexOf('-') > 0) {
|
||||||
|
String[] a = StringUtils.split(addrSeg, '-');
|
||||||
|
String beg = a[0].trim();
|
||||||
|
String end = a[1].trim();
|
||||||
|
this.ips.put(subnet, new String[]{beg, end});
|
||||||
|
} else {
|
||||||
|
this.ips.put(subnet, new String[]{addrSeg, addrSeg});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean allow(String ip) {
|
||||||
|
int originSubnetLen = ip.lastIndexOf(Constants.Symbol.DOT);
|
||||||
|
for (Map.Entry<String, String[]> e : ips.entrySet()) {
|
||||||
|
String subnet = e.getKey();
|
||||||
|
int subnetLen = subnet.length();
|
||||||
|
byte i = 0;
|
||||||
|
if (subnetLen == originSubnetLen) {
|
||||||
|
for (; i < subnetLen; i++) {
|
||||||
|
if (subnet.charAt(i) != ip.charAt(i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == subnetLen) {
|
||||||
|
int originAddrLen = ip.length() - originSubnetLen - 1;
|
||||||
|
String[] addrSeg = e.getValue();
|
||||||
|
String addrSegBeg = addrSeg[0];
|
||||||
|
String addrSegEnd = addrSeg[1];
|
||||||
|
if (originAddrLen < addrSegBeg.length() || addrSegEnd.length() < originAddrLen) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (originAddrLen == addrSegBeg.length()) {
|
||||||
|
for (byte j = 0; j < addrSegBeg.length(); j++) {
|
||||||
|
if (ip.charAt(originSubnetLen + 1 + j) < addrSegBeg.charAt(j)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (originAddrLen == addrSegEnd.length()) {
|
||||||
|
for (byte j = 0; j < addrSegEnd.length(); j++) {
|
||||||
|
if (addrSegEnd.charAt(j) < ip.charAt(originSubnetLen + 1 + j)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JacksonUtils.writeValueAsString(this);
|
return JacksonUtils.writeValueAsString(this);
|
||||||
|
|||||||
@@ -14,19 +14,20 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.listener.AggregateRedisConfig;
|
|
||||||
import we.util.Constants;
|
|
||||||
import we.util.JacksonUtils;
|
|
||||||
import we.util.ReactorUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.listener.AggregateRedisConfig;
|
||||||
|
import we.util.Constants;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
import we.util.ReactorUtils;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -37,7 +38,7 @@ import java.util.Objects;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
|||||||
@@ -14,23 +14,24 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.plugin.PluginFilter;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.plugin.PluginFilter;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component(AuthPluginFilter.AUTH_PLUGIN_FILTER)
|
@Component(AuthPluginFilter.AUTH_PLUGIN_FILTER)
|
||||||
@@ -52,8 +53,7 @@ public class AuthPluginFilter extends PluginFilter {
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("req auth: " + r, LogService.BIZ_ID, exchange.getRequest().getId());
|
log.debug("req auth: " + r, LogService.BIZ_ID, exchange.getRequest().getId());
|
||||||
}
|
}
|
||||||
Map<String, Object> data = new HashMap<>(1, 1.0f);
|
Map<String, Object> data = Collections.singletonMap(RESULT, r);
|
||||||
data.put(RESULT, r);
|
|
||||||
return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, AUTH_PLUGIN_FILTER, data);
|
return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, AUTH_PLUGIN_FILTER, data);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,13 +14,14 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface CustomAuth {
|
public interface CustomAuth {
|
||||||
|
|||||||
@@ -14,70 +14,52 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GatewayGroup {
|
public class GatewayGroup {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(GatewayGroup.class);
|
private static final Logger log = LoggerFactory.getLogger(GatewayGroup.class);
|
||||||
|
|
||||||
public static final char C = 'c';
|
public static final String DEFAULT = "default";
|
||||||
|
|
||||||
public static final char B = 'b';
|
public static final int DELETED = 1;
|
||||||
|
|
||||||
public static final char T = 't';
|
public int id;
|
||||||
|
|
||||||
public char id;
|
public int isDeleted = 0;
|
||||||
|
|
||||||
private Map<String, ServiceConfig> serviceConfigMap = new HashMap<>(128);
|
public String group;
|
||||||
|
|
||||||
public GatewayGroup(char id) {
|
public String name;
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, ServiceConfig> getServiceConfigMap() {
|
public Set<String> gateways = new HashSet<>();
|
||||||
return serviceConfigMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
public void setGateways(String gateways) {
|
||||||
public ServiceConfig getServiceConfig(String id) {
|
if (StringUtils.isNotBlank(gateways)) {
|
||||||
return serviceConfigMap.get(id);
|
Arrays.stream(StringUtils.split(gateways, ',')).forEach(
|
||||||
}
|
ip -> {
|
||||||
|
this.gateways.add(ip.trim());
|
||||||
public void remove(ApiConfig ac) {
|
}
|
||||||
ServiceConfig sc = serviceConfigMap.get(ac.service);
|
);
|
||||||
if (sc == null) {
|
|
||||||
log.info("no service config for " + ac);
|
|
||||||
} else {
|
|
||||||
sc.remove(ac);
|
|
||||||
if (sc.apiConfigMap().isEmpty()) {
|
|
||||||
serviceConfigMap.remove(ac.service);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(ApiConfig ac) {
|
@Override
|
||||||
ServiceConfig sc = new ServiceConfig(ac.service);
|
public String toString() {
|
||||||
serviceConfigMap.put(ac.service, sc);
|
return JacksonUtils.writeValueAsString(this);
|
||||||
sc.add(ac);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(ApiConfig ac) {
|
|
||||||
ServiceConfig sc = serviceConfigMap.get(ac.service);
|
|
||||||
if (sc == null) {
|
|
||||||
add(ac);
|
|
||||||
} else {
|
|
||||||
sc.update(ac);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package we.plugin.auth;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongqiaowei
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GatewayGroup2appsToApiConfig {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(GatewayGroup2appsToApiConfig.class);
|
||||||
|
|
||||||
|
private Map<String/*gg*/, Map<String/*a*/, ApiConfig>> configMap = new HashMap<>(6);
|
||||||
|
|
||||||
|
public Map<String, Map<String, ApiConfig>> getConfigMap() {
|
||||||
|
return configMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigMap(Map<String, Map<String, ApiConfig>> configMap) {
|
||||||
|
this.configMap = configMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ApiConfig ac) {
|
||||||
|
for (String gg : ac.gatewayGroups) {
|
||||||
|
Map<String, ApiConfig> app2apiConfigMap = configMap.get(gg);
|
||||||
|
if (app2apiConfigMap == null) {
|
||||||
|
app2apiConfigMap = new HashMap<>();
|
||||||
|
configMap.put(gg, app2apiConfigMap);
|
||||||
|
}
|
||||||
|
for (String a : ac.apps) {
|
||||||
|
app2apiConfigMap.put(a, ac);
|
||||||
|
log.info(gg + " add " + a + " -> " + ac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(ApiConfig ac) {
|
||||||
|
for (String gg : ac.gatewayGroups) {
|
||||||
|
Map<String, ApiConfig> app2apiConfigMap = configMap.get(gg);
|
||||||
|
if (app2apiConfigMap != null) {
|
||||||
|
for (String a : ac.apps) {
|
||||||
|
ApiConfig r = app2apiConfigMap.remove(a);
|
||||||
|
log.info(gg + " remove " + a + " -> " + r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(ApiConfig ac) {
|
||||||
|
for (String gg : ac.gatewayGroups) {
|
||||||
|
Map<String, ApiConfig> app2apiConfigMap = configMap.get(gg);
|
||||||
|
if (app2apiConfigMap == null) {
|
||||||
|
app2apiConfigMap = new HashMap<>();
|
||||||
|
configMap.put(gg, app2apiConfigMap);
|
||||||
|
}
|
||||||
|
for (String a : ac.apps) {
|
||||||
|
ApiConfig old = app2apiConfigMap.put(a, ac);
|
||||||
|
log.info(gg + " update " + a + " -> " + old + " with " + ac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiConfig get(String gatewayGroup, String app) {
|
||||||
|
Map<String, ApiConfig> app2apiConfigMap = configMap.get(gatewayGroup);
|
||||||
|
if (app2apiConfigMap == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return app2apiConfigMap.get(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return JacksonUtils.writeValueAsString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
src/main/java/we/plugin/auth/GatewayGroupService.java
Normal file
181
src/main/java/we/plugin/auth/GatewayGroupService.java
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package we.plugin.auth;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
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.listener.AggregateRedisConfig;
|
||||||
|
import we.util.Constants;
|
||||||
|
import we.util.JacksonUtils;
|
||||||
|
import we.util.NetworkUtils;
|
||||||
|
import we.util.ReactorUtils;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongqiaowei
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class GatewayGroupService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(GatewayGroupService.class);
|
||||||
|
|
||||||
|
private static final String fizzGatewayGroup = "fizz_gateway_group";
|
||||||
|
|
||||||
|
private static final String fizzGatewayGroupChannel = "fizz_gateway_group_channel";
|
||||||
|
|
||||||
|
public Map<String, GatewayGroup> gatewayGroupMap = new HashMap<>(6);
|
||||||
|
|
||||||
|
private Map<Integer, GatewayGroup> oldGatewayGroupMap = new HashMap<>(6);
|
||||||
|
|
||||||
|
public Set<String> currentGatewayGroupSet = new HashSet<>(6);
|
||||||
|
|
||||||
|
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
|
||||||
|
private ReactiveStringRedisTemplate rt;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() throws Throwable {
|
||||||
|
final Throwable[] throwable = new Throwable[1];
|
||||||
|
Throwable error = Mono.just(Objects.requireNonNull(rt.opsForHash().entries(fizzGatewayGroup)
|
||||||
|
.defaultIfEmpty(new AbstractMap.SimpleEntry<>(ReactorUtils.OBJ, ReactorUtils.OBJ)).onErrorStop().doOnError(t -> {
|
||||||
|
log.info(null, t);
|
||||||
|
})
|
||||||
|
.concatMap(e -> {
|
||||||
|
Object k = e.getKey();
|
||||||
|
if (k == ReactorUtils.OBJ) {
|
||||||
|
return Flux.just(e);
|
||||||
|
}
|
||||||
|
Object v = e.getValue();
|
||||||
|
log.info(k.toString() + Constants.Symbol.COLON + v.toString(), LogService.BIZ_ID, k.toString());
|
||||||
|
String json = (String) v;
|
||||||
|
try {
|
||||||
|
GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class);
|
||||||
|
oldGatewayGroupMap.put(gg.id, gg);
|
||||||
|
updateGatewayGroupMap(gg);
|
||||||
|
return Flux.just(e);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throwable[0] = t;
|
||||||
|
log.info(json, t);
|
||||||
|
return Flux.error(t);
|
||||||
|
}
|
||||||
|
}).blockLast())).flatMap(
|
||||||
|
e -> {
|
||||||
|
if (throwable[0] != null) {
|
||||||
|
return Mono.error(throwable[0]);
|
||||||
|
}
|
||||||
|
return lsnGatewayGroupChange();
|
||||||
|
}
|
||||||
|
).block();
|
||||||
|
if (error != ReactorUtils.EMPTY_THROWABLE) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<Throwable> lsnGatewayGroupChange() {
|
||||||
|
final Throwable[] throwable = new Throwable[1];
|
||||||
|
final boolean[] b = {false};
|
||||||
|
rt.listenToChannel(fizzGatewayGroupChannel).doOnError(t -> {
|
||||||
|
throwable[0] = t;
|
||||||
|
b[0] = false;
|
||||||
|
log.error("lsn " + fizzGatewayGroupChannel, t);
|
||||||
|
}).doOnSubscribe(
|
||||||
|
s -> {
|
||||||
|
b[0] = true;
|
||||||
|
log.info("success to lsn on " + fizzGatewayGroupChannel);
|
||||||
|
}
|
||||||
|
).doOnNext(msg -> {
|
||||||
|
String json = msg.getMessage();
|
||||||
|
log.info(json, LogService.BIZ_ID, "gg" + System.currentTimeMillis());
|
||||||
|
try {
|
||||||
|
GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class);
|
||||||
|
GatewayGroup r = oldGatewayGroupMap.remove(gg.id);
|
||||||
|
if (gg.isDeleted != GatewayGroup.DELETED && r != null) {
|
||||||
|
gatewayGroupMap.remove(r.group);
|
||||||
|
}
|
||||||
|
updateGatewayGroupMap(gg);
|
||||||
|
if (gg.isDeleted != GatewayGroup.DELETED) {
|
||||||
|
oldGatewayGroupMap.put(gg.id, gg);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
log.info(json, t);
|
||||||
|
}
|
||||||
|
}).subscribe();
|
||||||
|
Throwable t = throwable[0];
|
||||||
|
while (!b[0]) {
|
||||||
|
if (t != null) {
|
||||||
|
return Mono.error(t);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(2);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGatewayGroupMap(GatewayGroup gg) {
|
||||||
|
if (gg.isDeleted == GatewayGroup.DELETED) {
|
||||||
|
GatewayGroup r = gatewayGroupMap.remove(gg.group);
|
||||||
|
log.info("remove " + r);
|
||||||
|
} else {
|
||||||
|
GatewayGroup existGatewayGroup = gatewayGroupMap.get(gg.group);
|
||||||
|
gatewayGroupMap.put(gg.group, gg);
|
||||||
|
if (existGatewayGroup == null) {
|
||||||
|
log.info("add " + gg);
|
||||||
|
} else {
|
||||||
|
log.info("update " + existGatewayGroup + " with " + gg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateCurrentGatewayGroupSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCurrentGatewayGroupSet() {
|
||||||
|
String ip = NetworkUtils.getServerIp();
|
||||||
|
currentGatewayGroupSet.clear();
|
||||||
|
gatewayGroupMap.forEach(
|
||||||
|
(k, gg) -> {
|
||||||
|
if (gg.gateways.contains(ip)) {
|
||||||
|
currentGatewayGroupSet.add(gg.group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (currentGatewayGroupSet.isEmpty()) {
|
||||||
|
currentGatewayGroupSet.add(GatewayGroup.DEFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean currentGatewayGroupIn(Set<String> gatewayGroups) {
|
||||||
|
for (String cgg : currentGatewayGroupSet) {
|
||||||
|
if (gatewayGroups.contains(cgg)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,10 +14,14 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.auth;
|
package we.plugin.auth;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import we.util.Constants;
|
import we.util.Constants;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@@ -27,99 +31,122 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ServiceConfig {
|
public class ServiceConfig {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ServiceConfig.class);
|
private static final Logger log = LoggerFactory.getLogger(ServiceConfig.class);
|
||||||
|
|
||||||
private static final String forward_slash_str = String.valueOf(Constants.Symbol.FORWARD_SLASH);
|
public String id;
|
||||||
|
|
||||||
public String id;
|
@JsonIgnore
|
||||||
|
public Map<Integer, ApiConfig> apiConfigMap = new HashMap<>(32);
|
||||||
|
|
||||||
private Map<Integer, ApiConfig> apiConfigMap = new HashMap<>(32);
|
public Map<String, EnumMap<HttpMethod, GatewayGroup2appsToApiConfig>> path2methodToApiConfigMapMap = new HashMap<>(6);
|
||||||
|
|
||||||
private Map<String, EnumMap<HttpMethod, ApiConfig>> path2methodToApiConfigMapMap = new HashMap<>(32);
|
|
||||||
|
|
||||||
public ServiceConfig(String id) {
|
public ServiceConfig(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, ApiConfig> apiConfigMap() {
|
public void add(ApiConfig ac) {
|
||||||
return apiConfigMap;
|
apiConfigMap.put(ac.id, ac);
|
||||||
}
|
EnumMap<HttpMethod, GatewayGroup2appsToApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
||||||
|
if (method2apiConfigMap == null) {
|
||||||
public Map<String, EnumMap<HttpMethod, ApiConfig>> getPath2methodToApiConfigMapMap() {
|
method2apiConfigMap = new EnumMap<>(HttpMethod.class);
|
||||||
return path2methodToApiConfigMapMap;
|
GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig();
|
||||||
|
gatewayGroup2appsToApiConfig.add(ac);
|
||||||
|
method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig);
|
||||||
|
path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap);
|
||||||
|
} else {
|
||||||
|
GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method);
|
||||||
|
if (gatewayGroup2appsToApiConfig == null) {
|
||||||
|
gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig();
|
||||||
|
method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig);
|
||||||
|
}
|
||||||
|
gatewayGroup2appsToApiConfig.add(ac);
|
||||||
|
}
|
||||||
|
log.info("add " + ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(ApiConfig ac) {
|
public void remove(ApiConfig ac) {
|
||||||
ApiConfig remove = apiConfigMap.remove(ac.id);
|
ApiConfig remove = apiConfigMap.remove(ac.id);
|
||||||
log.info(remove + " is removed from api config map");
|
Map<HttpMethod, GatewayGroup2appsToApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
||||||
Map<HttpMethod, ApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
|
||||||
if (method2apiConfigMap != null) {
|
|
||||||
ApiConfig r = method2apiConfigMap.remove(ac.method);
|
|
||||||
log.info(r + " is removed from method 2 api config map");
|
|
||||||
if (method2apiConfigMap.isEmpty()) {
|
|
||||||
path2methodToApiConfigMapMap.remove(ac.path);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.info("no method 2 api config map for " + ac.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(ApiConfig ac) {
|
|
||||||
apiConfigMap.put(ac.id, ac);
|
|
||||||
EnumMap<HttpMethod, ApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
|
||||||
if (method2apiConfigMap == null) {
|
if (method2apiConfigMap == null) {
|
||||||
method2apiConfigMap = new EnumMap<>(HttpMethod.class);
|
log.info("no config to delete for " + ac.service + ' ' + ac.path);
|
||||||
path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap);
|
} else {
|
||||||
|
GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method);
|
||||||
|
if (gatewayGroup2appsToApiConfig == null) {
|
||||||
|
log.info("no config to delete for " + ac.service + ' ' + ac.method + ' ' + ac.path);
|
||||||
|
} else {
|
||||||
|
log.info(id + " remove " + ac);
|
||||||
|
gatewayGroup2appsToApiConfig.remove(ac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
method2apiConfigMap.put(ac.method, ac);
|
|
||||||
log.info(ac + " is added to api config map");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(ApiConfig ac) {
|
public void update(ApiConfig ac) {
|
||||||
ApiConfig prev = apiConfigMap.put(ac.id, ac);
|
ApiConfig prev = apiConfigMap.put(ac.id, ac);
|
||||||
log.info(prev + " is updated by " + ac + " in api config map");
|
log.info(prev + " is updated by " + ac + " in api config map");
|
||||||
EnumMap<HttpMethod, ApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
EnumMap<HttpMethod, GatewayGroup2appsToApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path);
|
||||||
if (method2apiConfigMap == null) {
|
if (method2apiConfigMap == null) {
|
||||||
method2apiConfigMap = new EnumMap<>(HttpMethod.class);
|
method2apiConfigMap = new EnumMap<>(HttpMethod.class);
|
||||||
|
GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig();
|
||||||
|
gatewayGroup2appsToApiConfig.add(ac);
|
||||||
|
method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig);
|
||||||
path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap);
|
path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap);
|
||||||
|
} else {
|
||||||
|
GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method);
|
||||||
|
if (gatewayGroup2appsToApiConfig == null) {
|
||||||
|
gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig();
|
||||||
|
method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig);
|
||||||
|
gatewayGroup2appsToApiConfig.add(ac);
|
||||||
|
} else {
|
||||||
|
log.info(id + " update " + ac);
|
||||||
|
gatewayGroup2appsToApiConfig.update(ac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ApiConfig put = method2apiConfigMap.put(ac.method, ac);
|
|
||||||
log.info(put + " is updated by " + ac + " in method 2 api config map");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public ApiConfig getApiConfig(HttpMethod method, String path) {
|
public ApiConfig getApiConfig(HttpMethod method, String path, String gatewayGroup, String app) {
|
||||||
|
GatewayGroup2appsToApiConfig r = getApiConfig0(method, path);
|
||||||
|
if (r == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(app)) {
|
||||||
|
app = App.ALL_APP;
|
||||||
|
}
|
||||||
|
return r.get(gatewayGroup, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GatewayGroup2appsToApiConfig getApiConfig0(HttpMethod method, String path) {
|
||||||
while (true) {
|
while (true) {
|
||||||
EnumMap<HttpMethod, ApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(path);
|
EnumMap<HttpMethod, GatewayGroup2appsToApiConfig> method2apiConfigMap = path2methodToApiConfigMapMap.get(path);
|
||||||
if (method2apiConfigMap == null) {
|
if (method2apiConfigMap == null) {
|
||||||
int i = path.lastIndexOf(Constants.Symbol.FORWARD_SLASH);
|
int i = path.lastIndexOf(Constants.Symbol.FORWARD_SLASH);
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
method2apiConfigMap = path2methodToApiConfigMapMap.get(forward_slash_str);
|
method2apiConfigMap = path2methodToApiConfigMapMap.get(Constants.Symbol.FORWARD_SLASH_STR);
|
||||||
if (method2apiConfigMap == null) {
|
if (method2apiConfigMap == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return getApiConfig0(method, method2apiConfigMap);
|
return getApiConfig1(method, method2apiConfigMap);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
path = path.substring(0, i);
|
path = path.substring(0, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return getApiConfig0(method, method2apiConfigMap);
|
return getApiConfig1(method, method2apiConfigMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiConfig getApiConfig0(HttpMethod method, EnumMap<HttpMethod, ApiConfig> method2apiConfigMap) {
|
private GatewayGroup2appsToApiConfig getApiConfig1(HttpMethod method, EnumMap<HttpMethod, GatewayGroup2appsToApiConfig> method2apiConfigMap) {
|
||||||
ApiConfig ac = method2apiConfigMap.get(method);
|
GatewayGroup2appsToApiConfig r = method2apiConfigMap.get(method);
|
||||||
if (ac == null) {
|
if (r == null) {
|
||||||
return method2apiConfigMap.get(HttpMethod.X);
|
return method2apiConfigMap.get(HttpMethod.X);
|
||||||
} else {
|
} else {
|
||||||
return ac;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,24 +14,32 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.plugin.stat;
|
package we.plugin.stat;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import we.plugin.PluginFilter;
|
|
||||||
import we.util.Constants;
|
|
||||||
import we.util.ThreadContext;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.listener.AggregateRedisConfig;
|
||||||
|
import we.plugin.PluginFilter;
|
||||||
|
import we.plugin.auth.GatewayGroupService;
|
||||||
|
import we.util.Constants;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component(StatPluginFilter.STAT_PLUGIN_FILTER)
|
@Component(StatPluginFilter.STAT_PLUGIN_FILTER)
|
||||||
@@ -41,8 +49,6 @@ public class StatPluginFilter extends PluginFilter {
|
|||||||
|
|
||||||
public static final String STAT_PLUGIN_FILTER = "statPlugin";
|
public static final String STAT_PLUGIN_FILTER = "statPlugin";
|
||||||
|
|
||||||
private static final String accessStat = "$accessStat";
|
|
||||||
|
|
||||||
private static final String ip = "\"ip\":";
|
private static final String ip = "\"ip\":";
|
||||||
|
|
||||||
private static final String gatewayGroup = "\"gatewayGroup\":";
|
private static final String gatewayGroup = "\"gatewayGroup\":";
|
||||||
@@ -60,24 +66,37 @@ public class StatPluginFilter extends PluginFilter {
|
|||||||
@Value("${stat.open:false}")
|
@Value("${stat.open:false}")
|
||||||
private boolean statOpen = false;
|
private boolean statOpen = false;
|
||||||
|
|
||||||
@Value("${stat.topic:fizz_access_stat}")
|
@Value("${stat.channel:fizz_access_stat}")
|
||||||
|
private String fizzAccessStatChannel;
|
||||||
|
|
||||||
|
@Value("${stat.topic:}")
|
||||||
private String fizzAccessStatTopic;
|
private String fizzAccessStatTopic;
|
||||||
|
|
||||||
|
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
|
||||||
|
private ReactiveStringRedisTemplate rt;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private GatewayGroupService gatewayGroupService;
|
||||||
|
|
||||||
|
private String currentGatewayGroups;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
Iterator<String> it = gatewayGroupService.currentGatewayGroupSet.iterator();
|
||||||
|
currentGatewayGroups = it.next();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
currentGatewayGroups = currentGatewayGroups + ',' + it.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> doFilter(ServerWebExchange exchange, Map<String, Object> config, String fixedConfig) {
|
public Mono<Void> doFilter(ServerWebExchange exchange, Map<String, Object> config, String fixedConfig) {
|
||||||
|
|
||||||
if (statOpen) {
|
if (statOpen) {
|
||||||
StringBuilder b = (StringBuilder) ThreadContext.get(accessStat);
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
if (b == null) {
|
|
||||||
b = new StringBuilder(128);
|
|
||||||
ThreadContext.set(accessStat, b);
|
|
||||||
} else {
|
|
||||||
b.delete(0, b.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
b.append(Constants.Symbol.LEFT_BRACE);
|
b.append(Constants.Symbol.LEFT_BRACE);
|
||||||
b.append(ip); toJsonStringValue(b, WebUtils.getOriginIp(exchange)); b.append(Constants.Symbol.COMMA);
|
b.append(ip); toJsonStringValue(b, WebUtils.getOriginIp(exchange)); b.append(Constants.Symbol.COMMA);
|
||||||
b.append(gatewayGroup); toJsonStringValue(b, WebUtils.getCurrentGatewayGroup(exchange)); b.append(Constants.Symbol.COMMA);
|
b.append(gatewayGroup); toJsonStringValue(b, currentGatewayGroups); b.append(Constants.Symbol.COMMA);
|
||||||
b.append(service); toJsonStringValue(b, WebUtils.getServiceId(exchange)); b.append(Constants.Symbol.COMMA);
|
b.append(service); toJsonStringValue(b, WebUtils.getServiceId(exchange)); b.append(Constants.Symbol.COMMA);
|
||||||
b.append(appid); toJsonStringValue(b, WebUtils.getAppId(exchange)); b.append(Constants.Symbol.COMMA);
|
b.append(appid); toJsonStringValue(b, WebUtils.getAppId(exchange)); b.append(Constants.Symbol.COMMA);
|
||||||
b.append(apiMethod); toJsonStringValue(b, exchange.getRequest().getMethodValue()); b.append(Constants.Symbol.COMMA);
|
b.append(apiMethod); toJsonStringValue(b, exchange.getRequest().getMethodValue()); b.append(Constants.Symbol.COMMA);
|
||||||
@@ -85,7 +104,11 @@ public class StatPluginFilter extends PluginFilter {
|
|||||||
b.append(reqTime) .append(System.currentTimeMillis());
|
b.append(reqTime) .append(System.currentTimeMillis());
|
||||||
b.append(Constants.Symbol.RIGHT_BRACE);
|
b.append(Constants.Symbol.RIGHT_BRACE);
|
||||||
|
|
||||||
log.info(b.toString(), LogService.HANDLE_STGY, LogService.toKF(fizzAccessStatTopic));
|
if (StringUtils.isBlank(fizzAccessStatTopic)) {
|
||||||
|
rt.convertAndSend(fizzAccessStatChannel, b.toString());
|
||||||
|
} else {
|
||||||
|
log.info(b.toString(), LogService.HANDLE_STGY, LogService.toKF(fizzAccessStatTopic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, STAT_PLUGIN_FILTER, null);
|
return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, STAT_PLUGIN_FILTER, null);
|
||||||
|
|||||||
@@ -14,10 +14,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.proxy;
|
package we.proxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
* 请求转发/调用后端接口时的负载均衡、流控、failover、超时等配置
|
* 请求转发/调用后端接口时的负载均衡、流控、failover、超时等配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,13 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.proxy;
|
package we.proxy;
|
||||||
|
|
||||||
import com.netflix.appinfo.InstanceInfo;
|
import com.netflix.appinfo.InstanceInfo;
|
||||||
import com.netflix.discovery.EurekaClient;
|
import com.netflix.discovery.EurekaClient;
|
||||||
import com.netflix.discovery.shared.Applications;
|
import com.netflix.discovery.shared.Applications;
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.config.AggrWebClientConfig;
|
|
||||||
import we.config.ProxyWebClientConfig;
|
|
||||||
import we.util.Constants;
|
|
||||||
import we.util.ThreadContext;
|
|
||||||
import we.util.WebUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -38,14 +34,22 @@ import org.springframework.web.reactive.function.client.ClientResponse;
|
|||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.config.AggrWebClientConfig;
|
||||||
|
import we.config.ProxyWebClientConfig;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.util.Constants;
|
||||||
|
import we.util.ThreadContext;
|
||||||
|
import we.util.WebUtils;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -95,18 +99,26 @@ public class FizzWebClient {
|
|||||||
return aggrResolveAddressSend(aggrService, aggrMethod, aggrPath, originReqIdOrBizId, method, uriOrSvc, headers, body, null);
|
return aggrResolveAddressSend(aggrService, aggrMethod, aggrPath, originReqIdOrBizId, method, uriOrSvc, headers, body, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<ClientResponse> aggrResolveAddressSend(String aggrService, HttpMethod aggrMethod, String aggrPath, @Nullable String originReqIdOrBizId,
|
public Mono<ClientResponse> send(String reqId, HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body) {
|
||||||
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, @Nullable CallBackendConfig cbc) {
|
return send(reqId, method, uriOrSvc, headers, body, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mono<ClientResponse> send(String reqId, HttpMethod method, String uriOrSvc, HttpHeaders headers, Object body, CallBackendConfig cbc) {
|
||||||
String s = extractServiceOrAddress(uriOrSvc);
|
String s = extractServiceOrAddress(uriOrSvc);
|
||||||
if (isService(s)) {
|
if (isService(s)) {
|
||||||
String path = uriOrSvc.substring(uriOrSvc.indexOf(Constants.Symbol.FORWARD_SLASH, 10));
|
String path = uriOrSvc.substring(uriOrSvc.indexOf(Constants.Symbol.FORWARD_SLASH, 10));
|
||||||
return send2service(originReqIdOrBizId, method, s, path, headers, body, cbc);
|
return send2service(reqId, method, s, path, headers, body, cbc);
|
||||||
} else {
|
} else {
|
||||||
return send2uri(originReqIdOrBizId, method, uriOrSvc, headers, body, cbc);
|
return send2uri(reqId, method, uriOrSvc, headers, body, cbc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<ClientResponse> aggrResolveAddressSend(String aggrService, HttpMethod aggrMethod, String aggrPath, @Nullable String originReqIdOrBizId,
|
||||||
|
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, @Nullable CallBackendConfig cbc) {
|
||||||
|
|
||||||
|
return send(originReqIdOrBizId, method, uriOrSvc, headers, body, cbc);
|
||||||
|
}
|
||||||
|
|
||||||
public Mono<ClientResponse> proxySend2service(@Nullable String originReqIdOrBizId, HttpMethod method, String service, String relativeUri,
|
public Mono<ClientResponse> proxySend2service(@Nullable String originReqIdOrBizId, HttpMethod method, String service, String relativeUri,
|
||||||
@Nullable HttpHeaders headers, @Nullable Object body) {
|
@Nullable HttpHeaders headers, @Nullable Object body) {
|
||||||
|
|
||||||
@@ -218,7 +230,23 @@ public class FizzWebClient {
|
|||||||
return b.append(Constants.Symbol.HTTP_PROTOCOL_PREFIX).append(inst.getIPAddr()).append(Constants.Symbol.COLON).append(inst.getPort()).append(path).toString();
|
return b.append(Constants.Symbol.HTTP_PROTOCOL_PREFIX).append(inst.getIPAddr()).append(Constants.Symbol.COLON).append(inst.getPort()).append(path).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// private static List<InstanceInfo> aggrMemberInsts = new ArrayList<>();
|
||||||
|
// static {
|
||||||
|
// InstanceInfo i0 = InstanceInfo.Builder.newBuilder().setAppName("TRIP-MINI").setIPAddr("xxx.25.63.192").setPort(7094).build();
|
||||||
|
// aggrMemberInsts.add(i0);
|
||||||
|
// }
|
||||||
|
// private static AtomicLong counter = new AtomicLong(0);
|
||||||
|
// private static final String aggrMember = "trip-mini";
|
||||||
|
|
||||||
|
|
||||||
private InstanceInfo roundRobinChoose1instFrom(String service) {
|
private InstanceInfo roundRobinChoose1instFrom(String service) {
|
||||||
|
|
||||||
|
// if (aggrMember.equals(service)) {
|
||||||
|
// int idx = (int) (counter.incrementAndGet() % aggrMemberInsts.size());
|
||||||
|
// return aggrMemberInsts.get(idx);
|
||||||
|
// }
|
||||||
|
|
||||||
List<InstanceInfo> insts = eurekaClient.getInstancesByVipAddress(service, false);
|
List<InstanceInfo> insts = eurekaClient.getInstancesByVipAddress(service, false);
|
||||||
if (insts == null || insts.isEmpty()) {
|
if (insts == null || insts.isEmpty()) {
|
||||||
throw new RuntimeException("eureka no " + service, null, false, false) {};
|
throw new RuntimeException("eureka no " + service, null, false, false) {};
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import org.apache.commons.lang3.SystemUtils;
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class Constants {
|
public final class Constants {
|
||||||
@@ -33,6 +34,7 @@ public final class Constants {
|
|||||||
public static final char BLANK = ' ';
|
public static final char BLANK = ' ';
|
||||||
public static final char SPACE = BLANK;
|
public static final char SPACE = BLANK;
|
||||||
public static final char FORWARD_SLASH = '/';
|
public static final char FORWARD_SLASH = '/';
|
||||||
|
public static final String FORWARD_SLASH_STR = "/";
|
||||||
public static final char BACK_SLASH = '\\';
|
public static final char BACK_SLASH = '\\';
|
||||||
public static final char DOT = '.';
|
public static final char DOT = '.';
|
||||||
public static final char SEMICOLON = ';';
|
public static final char SEMICOLON = ';';
|
||||||
|
|||||||
@@ -14,9 +14,8 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package we.util;
|
|
||||||
|
|
||||||
import we.util.Constants.DatetimePattern;
|
package we.util;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
@@ -25,8 +24,10 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import we.util.Constants.DatetimePattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class DateTimeUtils {
|
public abstract class DateTimeUtils {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.apache.commons.codec.binary.Hex;
|
|||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class DigestUtils extends org.apache.commons.codec.digest.DigestUtils {
|
public abstract class DigestUtils extends org.apache.commons.codec.digest.DigestUtils {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
@@ -23,6 +24,7 @@ import com.fasterxml.jackson.core.JsonParser;
|
|||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.*;
|
import com.fasterxml.jackson.databind.*;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
|
||||||
import we.plugin.auth.ApiConfig;
|
import we.plugin.auth.ApiConfig;
|
||||||
import we.util.Constants.DatetimePattern;
|
import we.util.Constants.DatetimePattern;
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class JacksonUtils {
|
public abstract class JacksonUtils {
|
||||||
@@ -42,19 +44,19 @@ public abstract class JacksonUtils {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
JsonFactory f = new JsonFactory();
|
JsonFactory f = new JsonFactory();
|
||||||
f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||||
f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||||
|
|
||||||
m = new ObjectMapper(f);
|
m = new ObjectMapper(f);
|
||||||
|
|
||||||
m.setSerializationInclusion(Include.NON_EMPTY);
|
m.setSerializationInclusion(Include.NON_EMPTY);
|
||||||
m.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
|
m.configure( SerializationFeature. WRITE_ENUMS_USING_TO_STRING, true);
|
||||||
m.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
|
m.configure( DeserializationFeature. READ_ENUMS_USING_TO_STRING, true);
|
||||||
m.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
|
m.configure( DeserializationFeature. FAIL_ON_NUMBERS_FOR_ENUMS, true);
|
||||||
m.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true); // FIXME
|
m.configure( SerializationFeature. WRITE_EMPTY_JSON_ARRAYS, true); // FIXME
|
||||||
m.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, true);
|
m.configure( SerializationFeature. WRITE_NULL_MAP_VALUES, true);
|
||||||
m.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
m.configure( DeserializationFeature. FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
m.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
|
m.configure( JsonParser.Feature. ALLOW_UNQUOTED_CONTROL_CHARS, true);
|
||||||
|
|
||||||
SimpleModule m0 = new SimpleModule();
|
SimpleModule m0 = new SimpleModule();
|
||||||
m0.addDeserializer(Date.class, new DateDeseralizer());
|
m0.addDeserializer(Date.class, new DateDeseralizer());
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -27,7 +28,7 @@ import java.security.SecureRandom;
|
|||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NetworkUtils {
|
public class NetworkUtils {
|
||||||
@@ -75,7 +76,7 @@ public class NetworkUtils {
|
|||||||
public static int getServerId() {
|
public static int getServerId() {
|
||||||
if (serverId == -1) {
|
if (serverId == -1) {
|
||||||
try {
|
try {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = ThreadContext.getStringBuilder();
|
||||||
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
|
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
|
||||||
while (nis.hasMoreElements()) {
|
while (nis.hasMoreElements()) {
|
||||||
NetworkInterface ni = nis.nextElement();
|
NetworkInterface ni = nis.nextElement();
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface ReactorUtils {
|
public interface ReactorUtils {
|
||||||
|
|||||||
@@ -14,10 +14,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Script {
|
public class Script {
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import javax.script.*;
|
import javax.script.*;
|
||||||
@@ -26,7 +26,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class ScriptUtils {
|
public abstract class ScriptUtils {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -21,7 +22,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class ThreadContext {
|
public abstract class ThreadContext {
|
||||||
@@ -29,7 +30,7 @@ public abstract class ThreadContext {
|
|||||||
private static ThreadLocal<Map<String, Object>> tl = new ThreadLocal<>();
|
private static ThreadLocal<Map<String, Object>> tl = new ThreadLocal<>();
|
||||||
private static final int mapCap = 32;
|
private static final int mapCap = 32;
|
||||||
|
|
||||||
private static final String sb = "_sb";
|
private static final String sb = "$sb";
|
||||||
private static final int sbCap = 256;
|
private static final int sbCap = 256;
|
||||||
|
|
||||||
/** use me carefully! */
|
/** use me carefully! */
|
||||||
@@ -39,31 +40,29 @@ public abstract class ThreadContext {
|
|||||||
|
|
||||||
/** use me carefully! */
|
/** use me carefully! */
|
||||||
public static StringBuilder getStringBuilder(boolean clean) {
|
public static StringBuilder getStringBuilder(boolean clean) {
|
||||||
// Map<String, Object> m = getMap();
|
Map<String, Object> m = getMap();
|
||||||
// StringBuilder b = (StringBuilder) m.get(sb);
|
StringBuilder b = (StringBuilder) m.get(sb);
|
||||||
// if (b == null) {
|
if (b == null) {
|
||||||
// b = new StringBuilder(sbCap);
|
b = new StringBuilder(sbCap);
|
||||||
// m.put(sb, b);
|
m.put(sb, b);
|
||||||
// } else {
|
} else {
|
||||||
// if (clean) {
|
if (clean) {
|
||||||
// b.delete(0, b.length());
|
b.delete(0, b.length());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// return b;
|
return b;
|
||||||
return new StringBuilder(64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StringBuilder getStringBuilder(String key) {
|
public static StringBuilder getStringBuilder(String key) {
|
||||||
// StringBuilder b = (StringBuilder) get(key);
|
StringBuilder b = (StringBuilder) get(key);
|
||||||
// if (b == null) {
|
if (b == null) {
|
||||||
// b = new StringBuilder(sbCap);
|
b = new StringBuilder(sbCap);
|
||||||
// Map<String, Object> m = getMap();
|
Map<String, Object> m = getMap();
|
||||||
// m.put(key, b);
|
m.put(key, b);
|
||||||
// } else {
|
} else {
|
||||||
// b.delete(0, b.length());
|
b.delete(0, b.length());
|
||||||
// }
|
}
|
||||||
// return b;
|
return b;
|
||||||
return getStringBuilder(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** for legacy code. */
|
/** for legacy code. */
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -23,7 +24,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class Utils {
|
public abstract class Utils {
|
||||||
|
|||||||
@@ -14,11 +14,9 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package we.util;
|
package we.util;
|
||||||
|
|
||||||
import we.flume.clients.log4j2appender.LogService;
|
|
||||||
import we.filter.FilterResult;
|
|
||||||
import we.legacy.RespEntity;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -32,11 +30,14 @@ import org.springframework.lang.Nullable;
|
|||||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import we.filter.FilterResult;
|
||||||
|
import we.flume.clients.log4j2appender.LogService;
|
||||||
|
import we.legacy.RespEntity;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lancer
|
* @author hongqiaowei
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class WebUtils {
|
public abstract class WebUtils {
|
||||||
@@ -57,7 +58,7 @@ public abstract class WebUtils {
|
|||||||
|
|
||||||
private static final String SERVICE_ID = "serviceId";
|
private static final String SERVICE_ID = "serviceId";
|
||||||
|
|
||||||
private static final String xForwardedFor = "X_FORWARDED_FOR";
|
private static final String xForwardedFor = "X-FORWARDED-FOR";
|
||||||
|
|
||||||
private static final String unknown = "unknown";
|
private static final String unknown = "unknown";
|
||||||
|
|
||||||
@@ -73,8 +74,6 @@ public abstract class WebUtils {
|
|||||||
|
|
||||||
private static final String originIp = "originIp";
|
private static final String originIp = "originIp";
|
||||||
|
|
||||||
public static final String CGG = "cgg";
|
|
||||||
|
|
||||||
public static String getHeaderValue(ServerWebExchange exchange, String header) {
|
public static String getHeaderValue(ServerWebExchange exchange, String header) {
|
||||||
return exchange.getRequest().getHeaders().getFirst(header);
|
return exchange.getRequest().getHeaders().getFirst(header);
|
||||||
}
|
}
|
||||||
@@ -87,10 +86,6 @@ public abstract class WebUtils {
|
|||||||
return exchange.getAttribute(APP_HEADER);
|
return exchange.getAttribute(APP_HEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Character getCurrentGatewayGroup(ServerWebExchange exchange) {
|
|
||||||
return exchange.getAttribute(CGG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getServiceId(ServerWebExchange exchange) {
|
public static String getServiceId(ServerWebExchange exchange) {
|
||||||
String svc = exchange.getAttribute(SERVICE_ID);
|
String svc = exchange.getAttribute(SERVICE_ID);
|
||||||
if (svc == null) {
|
if (svc == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user