diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index d618a80b..60c44576 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -708,7 +708,22 @@ failures will show up in Hystrix metrics, and once the circuit is open the proxy will not try to contact the service. To skip having a service automatically added, set -`zuul.ignored-services` to a list of service ids. To augment or change +`zuul.ignored-services` to a list of service id patterns. If a service +matches a pattern that is ignored, but also included in the explicitly +configured routes map, then it will be unignored. Example: + +.application.yml +[source,yaml] +---- + zuul: + ignoredServices: * + routes: + users: /myusers/** +---- + +In this example, all services are ignored *except* "users". + +To augment or change the proxy routes, you can add external configuration like the following: diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocator.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocator.java index 4c0a9d37..7319dbcf 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocator.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocator.java @@ -31,6 +31,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; +import org.springframework.util.PatternMatchUtils; import org.springframework.util.StringUtils; /** @@ -107,7 +108,7 @@ public class ProxyRouteLocator implements RouteLocator { prefix = prefix + routePrefix; } } - if(route.getRetryable() != null) { + if (route.getRetryable() != null) { retryable = route.getRetryable(); } break; @@ -122,19 +123,38 @@ public class ProxyRouteLocator implements RouteLocator { } protected LinkedHashMap locateRoutes() { - LinkedHashMap routesMap = new LinkedHashMap<>(); + LinkedHashMap routesMap = new LinkedHashMap(); addConfiguredRoutes(routesMap); routesMap.putAll(this.staticRoutes); if (this.discovery != null) { + Map staticServices = new LinkedHashMap(); + for (ZuulRoute route : routesMap.values()) { + String serviceId = route.getServiceId(); + if (serviceId == null) { + serviceId = route.getId(); + } + if (serviceId != null) { + staticServices.put(serviceId, route); + } + } // Add routes for discovery services by default List services = this.discovery.getServices(); + String[] ignored = this.properties.getIgnoredServices() + .toArray(new String[0]); for (String serviceId : services) { // Ignore specifically ignored services and those that were manually // configured String key = "/" + serviceId + "/**"; - if (!this.properties.getIgnoredServices().contains(serviceId) + ZuulRoute route = new ZuulRoute(key, serviceId); + if (staticServices.containsKey(serviceId) + && staticServices.get(serviceId).getUrl() == null) { + // Explicitly configured with no URL, cannot be ignored + routesMap.put(key, route); + } + if (!PatternMatchUtils.simpleMatch(ignored, serviceId) && !routesMap.containsKey(key)) { - routesMap.put(key, new ZuulRoute(key, serviceId)); + // Not ignored + routesMap.put(key, route); } } } @@ -167,8 +187,8 @@ public class ProxyRouteLocator implements RouteLocator { for (ZuulRoute entry : routeEntries.values()) { String route = entry.getPath(); if (routes.containsKey(route)) { - log.warn("Overwriting route "+route+": already defined by " + - routes.get(route)); + log.warn("Overwriting route " + route + ": already defined by " + + routes.get(route)); } routes.put(route, entry); } @@ -191,7 +211,7 @@ public class ProxyRouteLocator implements RouteLocator { private String location; private String prefix; - + private Boolean retryable; } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java index f0a41db7..3f9e7ea6 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java @@ -42,7 +42,7 @@ public class ZuulProperties { private String prefix = ""; private boolean stripPrefix = true; - + private Boolean retryable; private Map routes = new LinkedHashMap(); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocatorTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocatorTests.java index 00a24bbe..316f7146 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocatorTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRouteLocatorTests.java @@ -209,6 +209,55 @@ public class ProxyRouteLocatorTests { assertNull("routes did not ignore " + IGNOREDSERVICE, serviceId); } + @Test + public void testIgnoreRoutesWithPattern() { + ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, + this.properties); + this.properties.setIgnoredServices(Collections.singletonList("ignore*")); + given(this.discovery.getServices()).willReturn( + Collections.singletonList(IGNOREDSERVICE)); + Map routesMap = routeLocator.getRoutes(); + String serviceId = routesMap.get(getMapping(IGNOREDSERVICE)); + assertNull("routes did not ignore " + IGNOREDSERVICE, serviceId); + } + + @Test + public void testIgnoreAllRoutes() { + ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, + this.properties); + this.properties.setIgnoredServices(Collections.singletonList("*")); + given(this.discovery.getServices()).willReturn( + Collections.singletonList(IGNOREDSERVICE)); + Map routesMap = routeLocator.getRoutes(); + String serviceId = routesMap.get(getMapping(IGNOREDSERVICE)); + assertNull("routes did not ignore " + IGNOREDSERVICE, serviceId); + } + + @Test + public void testIgnoredRouteIncludedIfConfiguredAndDiscovered() { + this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**")); + ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, + this.properties); + this.properties.setIgnoredServices(Collections.singletonList("*")); + given(this.discovery.getServices()).willReturn(Collections.singletonList("foo")); + Map routesMap = routeLocator.getRoutes(); + String serviceId = routesMap.get(getMapping("foo")); + assertNotNull("routes ignored foo", serviceId); + } + + @Test + public void testIgnoredRouteIncludedIfConfiguredAndNotDiscovered() { + this.properties.getRoutes() + .put("foo", new ZuulRoute("/foo/**", "http://foo.com")); + ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, + this.properties); + this.properties.setIgnoredServices(Collections.singletonList("*")); + given(this.discovery.getServices()).willReturn(Collections.singletonList("bar")); + Map routesMap = routeLocator.getRoutes(); + String id = routesMap.get(getMapping("foo")); + assertNotNull("routes ignored foo", id); + } + @Test public void testAutoRoutes() { ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,