Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2020 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.fizzgate.plugin.auth;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import com.fizzgate.config.AggregateRedisConfig;
import com.fizzgate.config.SystemConfig;
import com.fizzgate.plugin.FizzPluginFilter;
import com.fizzgate.util.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.regex.Pattern;
/**
* @author hongqiaowei
*/
@Service
public class ApiConfigService implements ApplicationListener {
private static final Logger log = LoggerFactory.getLogger(ApiConfigService.class);
public Map serviceConfigMap = new HashMap<>(128);
private Map apiConfigMap = new HashMap<>(128);
private Map pluginConfigMap = new HashMap<>(32);
@Resource
private ReactiveWebServerApplicationContext applicationContext;
@Resource
private ApiConfigServiceProperties apiConfigServiceProperties;
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
private ReactiveStringRedisTemplate rt;
@Resource
private AppService appService;
@Resource
private ApiConfig2appsService apiConfig2AppsService;
@Resource
private GatewayGroupService gatewayGroupService;
@Resource
private SystemConfig systemConfig;
@Autowired(required = false)
private CustomAuth customAuth;
@PostConstruct
public void init() throws Throwable {
this.init(this::lsnApiConfigChange);
}
// TODO: no need like this
public void refreshLocalCache() throws Throwable {
this.init(null);
initPlugin();
}
// TODO: no need like this
private void init(Supplier> doAfterLoadCache) throws Throwable {
Map apiConfigMapTmp = new HashMap<>(128);
Map serviceConfigMapTmp = new HashMap<>(128);
final Throwable[] throwable = new Throwable[1];
Throwable error = Mono.just(Objects.requireNonNull(rt.opsForHash().entries(apiConfigServiceProperties.getFizzApiConfig())
.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);
}
String json = (String) e.getValue();
// log.info("init api config: {}", json, LogService.BIZ_ID, k.toString());
org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, k.toString());
log.info("init api config: {}", json);
try {
ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class);
apiConfigMapTmp.put(ac.id, ac);
updateServiceConfigMap(ac, serviceConfigMapTmp);
return Flux.just(e);
} catch (Throwable t) {
throwable[0] = t;
log.error("deser {}", json, t);
return Flux.error(t);
}
}).blockLast())).flatMap(
e -> {
if (throwable[0] != null) {
return Mono.error(throwable[0]);
}
if (doAfterLoadCache != null) {
return doAfterLoadCache.get();
} else {
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
}
}
).block();
if (error != ReactorUtils.EMPTY_THROWABLE) {
throw error;
}
this.apiConfigMap = apiConfigMapTmp;
this.serviceConfigMap = serviceConfigMapTmp;
}
// TODO: no need like this
private Mono lsnApiConfigChange() {
final Throwable[] throwable = new Throwable[1];
final boolean[] b = {false};
String ch = apiConfigServiceProperties.getFizzApiConfigChannel();
rt.listenToChannel(ch).doOnError(t -> {
throwable[0] = t;
b[0] = false;
log.error("lsn {}", ch, t);
}).doOnSubscribe(
s -> {
b[0] = true;
log.info("success to lsn on {}", ch);
}
).doOnNext(msg -> {
String json = msg.getMessage();
// log.info("api config change: {}", json, LogService.BIZ_ID, "acc" + System.currentTimeMillis());
org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, "acc" + System.currentTimeMillis());
log.info("api config change: {}", json);
try {
ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class);
ApiConfig r = apiConfigMap.remove(ac.id);
if (!ac.isDeleted && r != null) {
r.isDeleted = true;
updateServiceConfigMap(r, serviceConfigMap);
}
updateServiceConfigMap(ac, serviceConfigMap);
if (!ac.isDeleted) {
apiConfigMap.put(ac.id, ac);
} else {
apiConfig2AppsService.remove(ac.id);
}
} catch (Throwable t) {
log.error("deser {}", 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 Result> initPlugin() {
Result> result = Result.succ();
String key = apiConfigServiceProperties.getFizzPluginConfig();
Flux> plugins = rt.opsForHash().entries(key);
plugins.collectList()
.defaultIfEmpty(Collections.emptyList())
.flatMap(
es -> {
if (!es.isEmpty()) {
String json = null;
try {
for (Map.Entry