3232import reactor .core .publisher .Flux ;
3333import reactor .core .publisher .Mono ;
3434
35+ import org .springframework .boot .actuate .autoconfigure .endpoint .web .WebEndpointProperties ;
3536import org .springframework .cloud .gateway .event .RefreshRoutesEvent ;
3637import org .springframework .cloud .gateway .filter .FilterDefinition ;
3738import org .springframework .cloud .gateway .filter .GlobalFilter ;
@@ -71,8 +72,6 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
7172
7273 private static final Log log = LogFactory .getLog (GatewayControllerEndpoint .class );
7374
74- private static final String ENDPOINT_PREFIX = "/actuator/gateway" ;
75-
7675 protected RouteDefinitionLocator routeDefinitionLocator ;
7776
7877 protected List <GlobalFilter > globalFilters ;
@@ -88,25 +87,55 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
8887
8988 protected ApplicationEventPublisher publisher ;
9089
90+ protected WebEndpointProperties webEndpointProperties ;
91+
92+ private final SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory ();
93+
9194 public AbstractGatewayControllerEndpoint (RouteDefinitionLocator routeDefinitionLocator ,
9295 List <GlobalFilter > globalFilters , List <GatewayFilterFactory > gatewayFilters ,
9396 List <RoutePredicateFactory > routePredicates , RouteDefinitionWriter routeDefinitionWriter ,
94- RouteLocator routeLocator ) {
97+ RouteLocator routeLocator , WebEndpointProperties webEndpointProperties ) {
9598 this .routeDefinitionLocator = routeDefinitionLocator ;
9699 this .globalFilters = globalFilters ;
97100 this .GatewayFilters = gatewayFilters ;
98101 this .routePredicates = routePredicates ;
99102 this .routeDefinitionWriter = routeDefinitionWriter ;
100103 this .routeLocator = routeLocator ;
104+ this .webEndpointProperties = webEndpointProperties ;
105+ }
106+
107+ @ GetMapping ("/" )
108+ Mono <List <GatewayEndpointInfo >> getEndpoints () {
109+ List <GatewayEndpointInfo > endpoints = mergeEndpoints (
110+ getAvailableEndpointsForClass (AbstractGatewayControllerEndpoint .class .getName ()),
111+ getAvailableEndpointsForClass (GatewayControllerEndpoint .class .getName ()));
112+
113+ return Flux .fromIterable (endpoints ).map (p -> p )
114+ .flatMap (path -> this .routeLocator .getRoutes ().map (r -> generateHref (r , path )).distinct ().collectList ()
115+ .flatMapMany (Flux ::fromIterable ))
116+ .distinct () // Ensure overall uniqueness
117+ .collectList ();
118+ }
119+
120+ private List <GatewayEndpointInfo > mergeEndpoints (List <GatewayEndpointInfo > listA ,
121+ List <GatewayEndpointInfo > listB ) {
122+ Map <String , List <String >> mergedMap = new HashMap <>();
123+
124+ Stream .concat (listA .stream (), listB .stream ()).forEach (e -> mergedMap
125+ .computeIfAbsent (e .getHref (), k -> new ArrayList <>()).addAll (Arrays .asList (e .getMethods ())));
126+
127+ return mergedMap .entrySet ().stream ().map (entry -> new GatewayEndpointInfo (entry .getKey (), entry .getValue ()))
128+ .collect (Collectors .toList ());
101129 }
102130
103131 private List <GatewayEndpointInfo > getAvailableEndpointsForClass (String className ) {
104132 try {
105- MetadataReader metadataReader = new SimpleMetadataReaderFactory () .getMetadataReader (className );
133+ MetadataReader metadataReader = simpleMetadataReaderFactory .getMetadataReader (className );
106134 Set <MethodMetadata > annotatedMethods = metadataReader .getAnnotationMetadata ()
107135 .getAnnotatedMethods (RequestMapping .class .getName ());
108136
109- return annotatedMethods .stream ().map (method -> new GatewayEndpointInfo (ENDPOINT_PREFIX
137+ String gatewayActuatorPath = webEndpointProperties .getBasePath () + "/gateway" ;
138+ return annotatedMethods .stream ().map (method -> new GatewayEndpointInfo (gatewayActuatorPath
110139 + ((String []) method .getAnnotationAttributes (RequestMapping .class .getName ()).get ("path" ))[0 ],
111140 ((RequestMethod []) method .getAnnotationAttributes (RequestMapping .class .getName ()).get ("method" ))[0 ]
112141 .name ()))
@@ -118,35 +147,10 @@ private List<GatewayEndpointInfo> getAvailableEndpointsForClass(String className
118147 }
119148 }
120149
121- public static List <GatewayEndpointInfo > mergeEndpoints (List <GatewayEndpointInfo > listA ,
122- List <GatewayEndpointInfo > listB ) {
123- Map <String , List <String >> mergedMap = new HashMap <>();
124-
125- Stream .concat (listA .stream (), listB .stream ()).forEach (e -> mergedMap
126- .computeIfAbsent (e .getHref (), k -> new ArrayList <>()).addAll (Arrays .asList (e .getMethods ())));
127-
128- return mergedMap .entrySet ().stream ().map (entry -> new GatewayEndpointInfo (entry .getKey (), entry .getValue ()))
129- .collect (Collectors .toList ());
130- }
131-
132- GatewayEndpointInfo generateHref (Route r , GatewayEndpointInfo path ) {
150+ private GatewayEndpointInfo generateHref (Route r , GatewayEndpointInfo path ) {
133151 return new GatewayEndpointInfo (path .getHref ().replace ("{id}" , r .getId ()), Arrays .asList (path .getMethods ()));
134152 }
135153
136- @ GetMapping ("/" )
137- public Mono <List <GatewayEndpointInfo >> getEndpoints () {
138- List <GatewayEndpointInfo > endpoints = mergeEndpoints (
139- getAvailableEndpointsForClass (AbstractGatewayControllerEndpoint .class .getName ()),
140- getAvailableEndpointsForClass (GatewayControllerEndpoint .class .getName ()));
141-
142- return Flux .fromIterable (endpoints ).map (p -> p )
143- .flatMap (path -> this .routeLocator .getRoutes ().map (r -> generateHref (r , path )).distinct ().collectList ()
144- .flatMapMany (Flux ::fromIterable ))
145- .distinct () // Ensure overall uniqueness
146- .collectList ();
147-
148- }
149-
150154 @ Override
151155 public void setApplicationEventPublisher (ApplicationEventPublisher publisher ) {
152156 this .publisher = publisher ;
0 commit comments