sequence
In this paper, we study the springcloud GatewayControllerEndpoint
GatewayAutoConfiguration
Spring – the cloud – gateway – core – 2.0.0. RC1 – sources. The jar! /org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
//......
@Bean
public AfterRoutePredicateFactory afterRoutePredicateFactory() {
return new AfterRoutePredicateFactory();
}
@Bean
public BeforeRoutePredicateFactory beforeRoutePredicateFactory() {
return new BeforeRoutePredicateFactory();
}
@Bean
public BetweenRoutePredicateFactory betweenRoutePredicateFactory() {
return new BetweenRoutePredicateFactory();
}
@Bean
public CookieRoutePredicateFactory cookieRoutePredicateFactory() {
return new CookieRoutePredicateFactory();
}
@Bean
public HeaderRoutePredicateFactory headerRoutePredicateFactory() {
return new HeaderRoutePredicateFactory();
}
@Bean
public HostRoutePredicateFactory hostRoutePredicateFactory() {
return new HostRoutePredicateFactory();
}
@Bean
public MethodRoutePredicateFactory methodRoutePredicateFactory() {
return new MethodRoutePredicateFactory();
}
@Bean
public PathRoutePredicateFactory pathRoutePredicateFactory() {
return new PathRoutePredicateFactory();
}
@Bean
public QueryRoutePredicateFactory queryRoutePredicateFactory() {
return new QueryRoutePredicateFactory();
}
@Bean
public ReadBodyPredicateFactory readBodyPredicateFactory(ServerCodecConfigurer codecConfigurer) {
returnnew ReadBodyPredicateFactory(codecConfigurer); } / /... @Configuration @ConditionalOnClass(Health.class) protected static class GatewayActuatorConfiguration { @Bean @ConditionalOnEnabledEndpoint public GatewayControllerEndpoint gatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters, List<GatewayFilterFactory> GatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {returnnew GatewayControllerEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator); }}}Copy the code
Can see a GatewayActuatorConfiguration finally, on the premise of a physical library can configuration, the configuration is GatewayControllerEndpoint
GatewayControllerEndpoint
Spring – the cloud – gateway – core – 2.0.0. RC1 – sources. The jar! /org/springframework/cloud/gateway/actuate/GatewayControllerEndpoint.java
@RestControllerEndpoint(id = "gateway")
public class GatewayControllerEndpoint implements ApplicationEventPublisherAware {
private static final Log log = LogFactory.getLog(GatewayControllerEndpoint.class);
private RouteDefinitionLocator routeDefinitionLocator;
private List<GlobalFilter> globalFilters;
private List<GatewayFilterFactory> GatewayFilters;
private RouteDefinitionWriter routeDefinitionWriter;
private RouteLocator routeLocator;
private ApplicationEventPublisher publisher;
public GatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> GatewayFilters, RouteDefinitionWriter routeDefinitionWriter,
RouteLocator routeLocator) {
this.routeDefinitionLocator = routeDefinitionLocator;
this.globalFilters = globalFilters;
this.GatewayFilters = GatewayFilters;
this.routeDefinitionWriter = routeDefinitionWriter;
this.routeLocator = routeLocator;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
// TODO: Add uncommited or new but not active routes endpoint
@PostMapping("/refresh")
public Mono<Void> refresh() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return Mono.empty();
}
@GetMapping("/globalfilters")
public Mono<HashMap<String, Object>> globalfilters() {
return getNamesToOrders(this.globalFilters);
}
@GetMapping("/routefilters")
public Mono<HashMap<String, Object>> routefilers() {
return getNamesToOrders(this.GatewayFilters);
}
private <T> Mono<HashMap<String, Object>> getNamesToOrders(List<T> list) {
return Flux.fromIterable(list).reduce(new HashMap<>(), this::putItem);
}
private HashMap<String, Object> putItem(HashMap<String, Object> map, Object o) {
Integer order = null;
if (o instanceof Ordered) {
order = ((Ordered)o).getOrder();
}
//filters.put(o.getClass().getName(), order);
map.put(o.toString(), order);
return map;
}
// TODO: Flush out routes without a definition
@GetMapping("/routes")
public Mono<List<Map<String, Object>>> routes() {
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator.getRouteDefinitions()
.collectMap(RouteDefinition::getId);
Mono<List<Route>> routes = this.routeLocator.getRoutes().collectList();
return Mono.zip(routeDefs, routes).map(tuple -> {
Map<String, RouteDefinition> defs = tuple.getT1();
List<Route> routeList = tuple.getT2();
List<Map<String, Object>> allRoutes = new ArrayList<>();
routeList.forEach(route -> {
HashMap<String, Object> r = new HashMap<>();
r.put("route_id", route.getId());
r.put("order", route.getOrder());
if (defs.containsKey(route.getId())) {
r.put("route_definition", defs.get(route.getId()));
} else {
HashMap<String, Object> obj = new HashMap<>();
obj.put("predicate", route.getPredicate().toString());
if(! route.getFilters().isEmpty()) { ArrayList<String> filters = new ArrayList<>();for (GatewayFilter filter : route.getFilters()) {
filters.add(filter.toString());
}
obj.put("filters", filters);
}
if(! obj.isEmpty()) { r.put("route_object", obj);
}
}
allRoutes.add(r);
});
return allRoutes;
});
}
/*
http POST :8080/admin/gateway/routes/apiaddreqhead uri=http://httpbin.org:80 predicates:='["Host=**.apiaddrequestheader.org", "Path=/headers"]' filters:='["AddRequestHeader=X-Request-ApiFoo, ApiBar"]'
*/
@PostMapping("/routes/{id}")
@SuppressWarnings("unchecked")
public Mono<ResponseEntity<Void>> save(@PathVariable String id, @RequestBody Mono<RouteDefinition> route) {
return this.routeDefinitionWriter.save(route.map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() ->
Mono.just(ResponseEntity.created(URI.create("/routes/"+id)).build())
));
}
@DeleteMapping("/routes/{id}")
public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
return this.routeDefinitionWriter.delete(Mono.just(id))
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
}
@GetMapping("/routes/{id}")
public Mono<ResponseEntity<RouteDefinition>> route(@PathVariable String id) {
//TODO: missing RouteLocator
returnthis.routeDefinitionLocator.getRouteDefinitions() .filter(route -> route.getId().equals(id)) .singleOrEmpty() .map(route -> ResponseEntity.ok(route)) .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); } @GetMapping("/routes/{id}/combinedfilters")
public Mono<HashMap<String, Object>> combinedfilters(@PathVariable String id) {
//TODO: missing global filters
returnthis.routeLocator.getRoutes() .filter(route -> route.getId().equals(id)) .reduce(new HashMap<>(), this::putItem); }}Copy the code
You can see that the following REST apis are provided
- POST /refresh
- GET /globalfilters
- GET /routefilters
- GET /routes
- POST /routes/{id}
- GET /routes/{id}
- GET /routes/{id}/combinedfilters
The instance
/actuator/gateway/routes
[{"route_id": "CompositeDiscoveryClient_DISCOVERY-SERVICE"."route_definition": {
"id": "CompositeDiscoveryClient_DISCOVERY-SERVICE"."predicates": [{"name": "Path"."args": {
"pattern": "/DISCOVERY-SERVICE/**"}}]."filters": [{"name": "RewritePath"."args": {
"regexp": "/DISCOVERY-SERVICE/(?
.*)"
."replacement": "/${remaining}"}}]."uri": "lb://DISCOVERY-SERVICE"."order": 0}."order": 0}, {"route_id": "CompositeDiscoveryClient_GATEWAY-SERVICE"."route_definition": {
"id": "CompositeDiscoveryClient_GATEWAY-SERVICE"."predicates": [{"name": "Path"."args": {
"pattern": "/GATEWAY-SERVICE/**"}}]."filters": [{"name": "RewritePath"."args": {
"regexp": "/GATEWAY-SERVICE/(?
.*)"
."replacement": "/${remaining}"}}]."uri": "lb://GATEWAY-SERVICE"."order": 0}."order": 0}]Copy the code
/actuator/gateway/globalfilters
{
"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@f425231": 10100,
"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@5cbd94b2": 1,"org.springframework.cloud.gateway.filter.NettyRoutingFilter@506aabf6": 2147483647,
"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@756aadfc": 10000,
"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@705a8dbc": 2147483647,
"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@6824b913": 2147483637,
"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@40729f01": 2147483646}Copy the code
/actuator/gateway/routefilters
{
"[RedirectToGatewayFilterFactory@32f96bba configClass = RedirectToGatewayFilterFactory.Config]": null,
"[StripPrefixGatewayFilterFactory@4a481728 configClass = StripPrefixGatewayFilterFactory.Config]": null,
"[RemoveResponseHeaderGatewayFilterFactory@67e25252 configClass = AbstractGatewayFilterFactory.NameConfig]": null,
"[RequestHeaderToRequestUriGatewayFilterFactory@4ace284d configClass = AbstractGatewayFilterFactory.NameConfig]": null,
"[ModifyRequestBodyGatewayFilterFactory@b3e86d5 configClass = ModifyRequestBodyGatewayFilterFactory.Config]": null,
"[RemoveRequestHeaderGatewayFilterFactory@611640f0 configClass = AbstractGatewayFilterFactory.NameConfig]": null,
"[SetStatusGatewayFilterFactory@3fd05b3e configClass = SetStatusGatewayFilterFactory.Config]": null,
"[PreserveHostHeaderGatewayFilterFactory@4d0e54e0 configClass = Object]": null,
"[SetResponseHeaderGatewayFilterFactory@1682c08c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@76ececd configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4eb9f2af configClass = Object]": null,
"[AddResponseHeaderGatewayFilterFactory@75b6dd5b configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[PrefixPathGatewayFilterFactory@e111c7c configClass = PrefixPathGatewayFilterFactory.Config]": null,
"[SetRequestHeaderGatewayFilterFactory@7affc159 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[RewritePathGatewayFilterFactory@58f4b31a configClass = RewritePathGatewayFilterFactory.Config]": null,
"[SetPathGatewayFilterFactory@72eb6200 configClass = SetPathGatewayFilterFactory.Config]": null,
"[RetryGatewayFilterFactory@21a9a705 configClass = RetryGatewayFilterFactory.Retry]": null,
"[AddRequestHeaderGatewayFilterFactory@1f1cddf3 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[ModifyResponseBodyGatewayFilterFactory@72b43104 configClass = ModifyResponseBodyGatewayFilterFactory.Config]": null,
"[AddRequestParameterGatewayFilterFactory@228bda54 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null
}
Copy the code
/actuator/gateway/routes/CompositeDiscoveryClient_DISCOVERY-SERVICE
{
"id": "CompositeDiscoveryClient_DISCOVERY-SERVICE"."predicates": [{"name": "Path"."args": {
"pattern": "/DISCOVERY-SERVICE/**"}}]."filters": [{"name": "RewritePath"."args": {
"regexp": "/DISCOVERY-SERVICE/(?
.*)"
."replacement": "/${remaining}"}}]."uri": "lb://DISCOVERY-SERVICE"."order": 0}Copy the code
/actuator/gateway/routes/CompositeDiscoveryClient_DISCOVERY-SERVICE/combinedfilters
{
"Route{id='CompositeDiscoveryClient_DISCOVERY-SERVICE', uri=lb://DISCOVERY-SERVICE, order=0, predicate=org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$LambdaThe $769/1774209584@7d9639ad, gatewayFilters=[OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterF actory$$LambdaThe $771/1052389952@528c8627, order=1}]}": 0}Copy the code
summary
Springcloud Gateway provides a Gateway actuator. The Endpiont provides REST API for querying information about filter and routes and updating information about specified routes, which provides great convenience for web interface management and configuration functions.
doc
- Part XV. Spring Cloud Gateway 115. Actuator API