Refactor to use the actuator path set in properties

- Also cleaned up code and warnings
This commit is contained in:
Fredrich Ombico
2023-12-05 13:49:12 -05:00
parent 8157363258
commit 84c351a864
4 changed files with 49 additions and 40 deletions

View File

@@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.GlobalFilter;
@@ -71,8 +72,6 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
private static final Log log = LogFactory.getLog(GatewayControllerEndpoint.class);
private static final String ENDPOINT_PREFIX = "/actuator/gateway";
protected RouteDefinitionLocator routeDefinitionLocator;
protected List<GlobalFilter> globalFilters;
@@ -88,25 +87,55 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
protected ApplicationEventPublisher publisher;
protected WebEndpointProperties webEndpointProperties;
private final SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
public AbstractGatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator,
List<GlobalFilter> globalFilters, List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> routePredicates, RouteDefinitionWriter routeDefinitionWriter,
RouteLocator routeLocator) {
RouteLocator routeLocator, WebEndpointProperties webEndpointProperties) {
this.routeDefinitionLocator = routeDefinitionLocator;
this.globalFilters = globalFilters;
this.GatewayFilters = gatewayFilters;
this.routePredicates = routePredicates;
this.routeDefinitionWriter = routeDefinitionWriter;
this.routeLocator = routeLocator;
this.webEndpointProperties = webEndpointProperties;
}
@GetMapping("/")
Mono<List<GatewayEndpointInfo>> getEndpoints() {
List<GatewayEndpointInfo> endpoints = mergeEndpoints(
getAvailableEndpointsForClass(AbstractGatewayControllerEndpoint.class.getName()),
getAvailableEndpointsForClass(GatewayControllerEndpoint.class.getName()));
return Flux.fromIterable(endpoints).map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes().map(r -> generateHref(r, path)).distinct().collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
}
private List<GatewayEndpointInfo> mergeEndpoints(List<GatewayEndpointInfo> listA,
List<GatewayEndpointInfo> listB) {
Map<String, List<String>> mergedMap = new HashMap<>();
Stream.concat(listA.stream(), listB.stream()).forEach(e -> mergedMap
.computeIfAbsent(e.getHref(), k -> new ArrayList<>()).addAll(Arrays.asList(e.getMethods())));
return mergedMap.entrySet().stream().map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
private List<GatewayEndpointInfo> getAvailableEndpointsForClass(String className) {
try {
MetadataReader metadataReader = new SimpleMetadataReaderFactory().getMetadataReader(className);
MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader(className);
Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata()
.getAnnotatedMethods(RequestMapping.class.getName());
return annotatedMethods.stream().map(method -> new GatewayEndpointInfo(ENDPOINT_PREFIX
String gatewayActuatorPath = webEndpointProperties.getBasePath() + "/gateway";
return annotatedMethods.stream().map(method -> new GatewayEndpointInfo(gatewayActuatorPath
+ ((String[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("path"))[0],
((RequestMethod[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("method"))[0]
.name()))
@@ -118,35 +147,10 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
}
}
public static List<GatewayEndpointInfo> mergeEndpoints(List<GatewayEndpointInfo> listA,
List<GatewayEndpointInfo> listB) {
Map<String, List<String>> mergedMap = new HashMap<>();
Stream.concat(listA.stream(), listB.stream()).forEach(e -> mergedMap
.computeIfAbsent(e.getHref(), k -> new ArrayList<>()).addAll(Arrays.asList(e.getMethods())));
return mergedMap.entrySet().stream().map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
GatewayEndpointInfo generateHref(Route r, GatewayEndpointInfo path) {
private GatewayEndpointInfo generateHref(Route r, GatewayEndpointInfo path) {
return new GatewayEndpointInfo(path.getHref().replace("{id}", r.getId()), Arrays.asList(path.getMethods()));
}
@GetMapping("/")
public Mono<List<GatewayEndpointInfo>> getEndpoints() {
List<GatewayEndpointInfo> endpoints = mergeEndpoints(
getAvailableEndpointsForClass(AbstractGatewayControllerEndpoint.class.getName()),
getAvailableEndpointsForClass(GatewayControllerEndpoint.class.getName()));
return Flux.fromIterable(endpoints).map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes().map(r -> generateHref(r, path)).distinct().collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
@@ -47,9 +48,10 @@ public class GatewayControllerEndpoint extends AbstractGatewayControllerEndpoint
public GatewayControllerEndpoint(List<GlobalFilter> globalFilters, List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> routePredicates, RouteDefinitionWriter routeDefinitionWriter,
RouteLocator routeLocator, RouteDefinitionLocator routeDefinitionLocator) {
super(routeDefinitionLocator, globalFilters, gatewayFilters, routePredicates, routeDefinitionWriter,
routeLocator);
RouteLocator routeLocator, RouteDefinitionLocator routeDefinitionLocator,
WebEndpointProperties webEndpointProperties) {
super(routeDefinitionLocator, globalFilters, gatewayFilters, routePredicates,
routeDefinitionWriter, routeLocator, webEndpointProperties);
}
@GetMapping("/routedefinitions")

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
@@ -47,9 +48,9 @@ public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEn
public GatewayLegacyControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator,
List<GlobalFilter> globalFilters, List<GatewayFilterFactory> gatewayFilterFactories,
List<RoutePredicateFactory> routePredicates, RouteDefinitionWriter routeDefinitionWriter,
RouteLocator routeLocator) {
RouteLocator routeLocator, WebEndpointProperties webEndpointProperties) {
super(routeDefinitionLocator, globalFilters, gatewayFilterFactories, routePredicates, routeDefinitionWriter,
routeLocator);
routeLocator, webEndpointProperties);
}
@GetMapping("/routes")

View File

@@ -40,6 +40,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@@ -817,9 +818,9 @@ public class GatewayAutoConfiguration {
public GatewayControllerEndpoint gatewayControllerEndpoint(List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> gatewayFilters, List<RoutePredicateFactory> routePredicates,
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator,
RouteDefinitionLocator routeDefinitionLocator) {
RouteDefinitionLocator routeDefinitionLocator, WebEndpointProperties webEndpointProperties) {
return new GatewayControllerEndpoint(globalFilters, gatewayFilters, routePredicates, routeDefinitionWriter,
routeLocator, routeDefinitionLocator);
routeLocator, routeDefinitionLocator, webEndpointProperties);
}
@Bean
@@ -828,9 +829,10 @@ public class GatewayAutoConfiguration {
public GatewayLegacyControllerEndpoint gatewayLegacyControllerEndpoint(
RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> gatewayFilters, List<RoutePredicateFactory> routePredicates,
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator,
WebEndpointProperties webEndpointProperties) {
return new GatewayLegacyControllerEndpoint(routeDefinitionLocator, globalFilters, gatewayFilters,
routePredicates, routeDefinitionWriter, routeLocator);
routePredicates, routeDefinitionWriter, routeLocator, webEndpointProperties);
}
}