Initial RouteWriter support

This commit is contained in:
Spencer Gibb
2017-01-31 20:49:07 -07:00
parent a9ce9e061c
commit 01bb526fa9
5 changed files with 111 additions and 8 deletions

View File

@@ -1,20 +1,27 @@
package org.springframework.cloud.gateway.actuate;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.cloud.gateway.support.CachingRouteLocator;
import org.springframework.cloud.gateway.api.RouteLocator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.api.Route;
import org.springframework.cloud.gateway.api.RouteLocator;
import org.springframework.cloud.gateway.api.RouteWriter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.route.RouteFilter;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.support.CachingRouteLocator;
import org.springframework.core.Ordered;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -30,18 +37,23 @@ import reactor.core.publisher.Mono;
@RequestMapping("/admin/gateway")
public class GatewayEndpoint {/*extends AbstractEndpoint<Map<String, Object>> {*/
private static final Log log = LogFactory.getLog(GatewayEndpoint.class);
private RouteLocator routeLocator;
private List<GlobalFilter> globalFilters;
private List<RouteFilter> routeFilters;
private FilteringWebHandler filteringWebHandler;
private RouteWriter routeWriter;
public GatewayEndpoint(RouteLocator routeLocator, List<GlobalFilter> globalFilters,
List<RouteFilter> routeFilters, FilteringWebHandler filteringWebHandler) {
List<RouteFilter> routeFilters, FilteringWebHandler filteringWebHandler,
RouteWriter routeWriter) {
//super("gateway");
this.routeLocator = routeLocator;
this.globalFilters = globalFilters;
this.routeFilters = routeFilters;
this.filteringWebHandler = filteringWebHandler;
this.routeWriter = routeWriter;
}
/*@Override
@@ -87,6 +99,32 @@ public class GatewayEndpoint {/*extends AbstractEndpoint<Map<String, Object>> {*
return this.routeLocator.getRoutes().collectList();
}
/*
http POST :8080/admin/gateway/routes/addreqhead2 \
uri=http://httpbin.org/headers \
predicates:='["Host=**.addrequestheader.org", "Url=/headers"]' \
filters:='["AddRequestHeader=X-Request-Foo, Bar"]'
*/
@PostMapping("/routes/{id}")
public Mono<ResponseEntity<Void>> save(@PathVariable String id, @RequestBody Mono<Route> route) {
return this.routeWriter.save(route.map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(() -> {
GatewayEndpoint.this.refresh();
return Mono.just(ResponseEntity.created(URI.create("/routes/"+id)).build());
});
}
@DeleteMapping("/routes/{id}")
public Mono<ResponseEntity<Void>> delete(@PathVariable Mono<String> id) {
return this.routeWriter.delete(id).then(() -> {
GatewayEndpoint.this.refresh();
return Mono.just(ResponseEntity.ok().build());
});
}
@GetMapping("/routes/{id}")
public Mono<Route> route(@PathVariable String id) {
return this.routeLocator.getRoutes()

View File

@@ -0,0 +1,13 @@
package org.springframework.cloud.gateway.api;
import reactor.core.publisher.Mono;
/**
* @author Spencer Gibb
*/
public interface RouteWriter {
Mono<Void> save(Mono<Route> route);
Mono<Void> delete(Mono<String> routeId);
}

View File

@@ -11,6 +11,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.gateway.actuate.GatewayEndpoint;
import org.springframework.cloud.gateway.api.RouteLocator;
import org.springframework.cloud.gateway.api.RouteWriter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
@@ -43,6 +44,7 @@ import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredic
import org.springframework.cloud.gateway.handler.predicate.RoutePredicate;
import org.springframework.cloud.gateway.handler.predicate.UrlRoutePredicate;
import org.springframework.cloud.gateway.support.CachingRouteLocator;
import org.springframework.cloud.gateway.support.InMemoryRouteRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -233,14 +235,21 @@ public class GatewayAutoConfiguration {
return new SetStatusRouteFilter();
}
//TODO: control creation
@Bean
public InMemoryRouteRepository inMemoryRouteRepository() {
return new InMemoryRouteRepository();
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class GatewayActuatorConfiguration {
@Bean
public GatewayEndpoint gatewayEndpoint(RouteLocator routeLocator, List<GlobalFilter> globalFilters,
List<RouteFilter> routeFilters, FilteringWebHandler filteringWebHandler) {
return new GatewayEndpoint(routeLocator, globalFilters, routeFilters, filteringWebHandler);
List<RouteFilter> routeFilters, FilteringWebHandler filteringWebHandler,
RouteWriter routeWriter) {
return new GatewayEndpoint(routeLocator, globalFilters, routeFilters, filteringWebHandler, routeWriter);
}
}

View File

@@ -0,0 +1,41 @@
package org.springframework.cloud.gateway.support;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.cloud.gateway.api.Route;
import org.springframework.cloud.gateway.api.RouteLocator;
import org.springframework.cloud.gateway.api.RouteWriter;
import static java.util.Collections.synchronizedMap;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @author Spencer Gibb
*/
public class InMemoryRouteRepository implements RouteLocator, RouteWriter {
private final Map<String, Route> routes = synchronizedMap(new LinkedHashMap<String, Route>());
@Override
public Mono<Void> save(Mono<Route> route) {
return route.doOnNext(r -> routes.put(r.getId(), r)).then();
//route.subscribe(r -> );
//return Mono.empty();
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.then(id -> {
routes.remove(id);
return Mono.empty();
});
}
@Override
public Flux<Route> getRoutes() {
return Flux.fromIterable(routes.values());
}
}

View File

@@ -11,6 +11,7 @@ import org.springframework.cloud.gateway.api.RouteLocator;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteLocator;
import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteLocator;
import org.springframework.cloud.gateway.support.InMemoryRouteRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@@ -44,9 +45,10 @@ public class GatewayTestApplication {
@Bean
@Primary
public RouteLocator compositeRouteLocator(DiscoveryClientRouteLocator discoveryClientRouteLocator,
PropertiesRouteLocator propertiesRouteLocator) {
final Flux<RouteLocator> flux = Flux.just(discoveryClientRouteLocator, propertiesRouteLocator);
public RouteLocator compositeRouteLocator(InMemoryRouteRepository inMemoryRouteRepository,
DiscoveryClientRouteLocator discoveryClientRouteLocator,
PropertiesRouteLocator propertiesRouteLocator) {
final Flux<RouteLocator> flux = Flux.just(inMemoryRouteRepository, discoveryClientRouteLocator, propertiesRouteLocator);
final CompositeRouteLocator composite = new CompositeRouteLocator(flux);
return new CachingRouteLocator(composite);
}