diff --git a/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java b/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java index b0d94878..8eda427a 100644 --- a/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java +++ b/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java @@ -15,6 +15,7 @@ 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.cloud.gateway.support.NotFoundException; import org.springframework.core.Ordered; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -100,10 +101,7 @@ public class GatewayEndpoint {/*extends AbstractEndpoint> {* } /* -http POST :8080/admin/gateway/routes/addreqhead2 \ -uri=http://httpbin.org/headers \ -predicates:='["Host=**.addrequestheader.org", "Url=/headers"]' \ -filters:='["AddRequestHeader=X-Request-Foo, Bar"]' +http POST :8080/admin/gateway/routes/apiaddreqhead uri=http://httpbin.org:80 predicates:='["Host=**.apiaddrequestheader.org", "Url=/headers"]' filters:='["AddRequestHeader=X-Request-ApiFoo, ApiBar"]' */ @PostMapping("/routes/{id}") public Mono> save(@PathVariable String id, @RequestBody Mono route) { @@ -111,25 +109,25 @@ filters:='["AddRequestHeader=X-Request-Foo, Bar"]' r.setId(id); log.debug("Saving route: " + route); return r; - })).then(() -> { - GatewayEndpoint.this.refresh(); - return Mono.just(ResponseEntity.created(URI.create("/routes/"+id)).build()); - }); + })).then(() -> + Mono.just(ResponseEntity.created(URI.create("/routes/"+id)).build()) + ); } @DeleteMapping("/routes/{id}") - public Mono> delete(@PathVariable Mono id) { - return this.routeWriter.delete(id).then(() -> { - GatewayEndpoint.this.refresh(); - return Mono.just(ResponseEntity.ok().build()); - }); + public Mono> delete(@PathVariable String id) { + return this.routeWriter .delete(Mono.just(id)) + .then(() -> Mono.just(ResponseEntity.ok().build())) + .otherwise(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build())); } @GetMapping("/routes/{id}") - public Mono route(@PathVariable String id) { + public Mono> route(@PathVariable String id) { return this.routeLocator.getRoutes() .filter(route -> route.getId().equals(id)) - .singleOrEmpty(); + .singleOrEmpty() + .map(route -> ResponseEntity.ok(route)) + .otherwiseIfEmpty(Mono.just(ResponseEntity.notFound().build())); } @GetMapping("/routes/{id}/combinedfilters") diff --git a/src/main/java/org/springframework/cloud/gateway/support/InMemoryRouteRepository.java b/src/main/java/org/springframework/cloud/gateway/support/InMemoryRouteRepository.java index 7638b05d..515a51ff 100644 --- a/src/main/java/org/springframework/cloud/gateway/support/InMemoryRouteRepository.java +++ b/src/main/java/org/springframework/cloud/gateway/support/InMemoryRouteRepository.java @@ -21,16 +21,20 @@ public class InMemoryRouteRepository implements RouteLocator, RouteWriter { @Override public Mono save(Mono route) { - return route.doOnNext(r -> routes.put(r.getId(), r)).then(); - //route.subscribe(r -> ); - //return Mono.empty(); + return route.then( r -> { + routes.put(r.getId(), r); + return Mono.empty(); + }); } @Override public Mono delete(Mono routeId) { return routeId.then(id -> { - routes.remove(id); - return Mono.empty(); + if (routes.containsKey(id)) { + routes.remove(id); + return Mono.empty(); + } + return Mono.error(new NotFoundException("Route not found: "+routeId)); }); } diff --git a/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java b/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java new file mode 100644 index 00000000..7d421a4c --- /dev/null +++ b/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java @@ -0,0 +1,14 @@ +package org.springframework.cloud.gateway.support; + +/** + * @author Spencer Gibb + */ +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java b/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java index 988612b7..205ea42c 100644 --- a/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java +++ b/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java @@ -54,6 +54,25 @@ public class GatewayTestApplication { } } + @Configuration + @Profile("!discovery") + protected static class GatewayInMemoryConfiguration { + + @Bean + public PropertiesRouteLocator propertiesRouteLocator(GatewayProperties properties) { + return new PropertiesRouteLocator(properties); + } + + @Bean + @Primary + public RouteLocator compositeRouteLocator(InMemoryRouteRepository inMemoryRouteRepository, + PropertiesRouteLocator propertiesRouteLocator) { + final Flux flux = Flux.just(inMemoryRouteRepository, propertiesRouteLocator); + final CompositeRouteLocator composite = new CompositeRouteLocator(flux); + return new CachingRouteLocator(composite); + } + } + public static void main(String[] args) { System.setProperty("java.net.preferIPv4Stack", "true"); //Remove when configurable SpringApplication.run(GatewayTestApplication.class, args); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 267b695e..d4d08114 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -179,6 +179,7 @@ logging: level: org.springframework.cloud.gateway: TRACE org.springframework.http.server.reactive: DEBUG + org.springframework.web.reactive: DEBUG reactor.ipc.netty: DEBUG management: