Commit ce75960f by Johannes Edmeier

Add CompositeRouteLocator

This CompositeRouteLocator allows extensions to add custom RouteLocators
parent 4a011458
......@@ -15,6 +15,8 @@
*/
package de.codecentric.boot.admin.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.trace.TraceRepository;
......@@ -35,11 +37,14 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import de.codecentric.boot.admin.event.RoutesOutdatedEvent;
import de.codecentric.boot.admin.registry.ApplicationRegistry;
import de.codecentric.boot.admin.zuul.ApplicationRouteLocator;
import de.codecentric.boot.admin.zuul.OptionsDispatchingZuulController;
import de.codecentric.boot.admin.zuul.filters.CompositeRouteLocator;
import de.codecentric.boot.admin.zuul.filters.route.SimpleHostRoutingFilter;
@Configuration
......@@ -59,14 +64,25 @@ public class RevereseZuulProxyConfiguration extends ZuulConfiguration {
private ZuulHandlerMapping zuulHandlerMapping;
@Bean
@Override
@Order(0)
@ConfigurationProperties("spring.boot.admin.routes")
public ApplicationRouteLocator routeLocator() {
public ApplicationRouteLocator applicationRouteLocator() {
return new ApplicationRouteLocator(this.server.getServletPrefix(), registry,
adminServer.getContextPath() + "/api/applications/");
}
@Bean
@Primary
public CompositeRouteLocator routeLocator(List<RouteLocator> locators) {
return new CompositeRouteLocator(locators);
}
@Override
public RouteLocator routeLocator() {
return null;
}
@Bean
@Override
public ZuulController zuulController() {
return new OptionsDispatchingZuulController();
......@@ -115,7 +131,6 @@ public class RevereseZuulProxyConfiguration extends ZuulConfiguration {
}
}
private static class ZuulRefreshListener implements ApplicationListener<ApplicationEvent> {
private ZuulHandlerMapping zuulHandlerMapping;
......
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codecentric.boot.admin.zuul.filters;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.util.Assert;
public class CompositeRouteLocator implements RefreshableRouteLocator {
private final Collection<? extends RouteLocator> routeLocators;
public CompositeRouteLocator(Collection<? extends RouteLocator> routeLocators) {
Assert.notNull(routeLocators);
this.routeLocators = routeLocators;
}
@Override
public Collection<String> getIgnoredPaths() {
Set<String> ignoredPaths = new HashSet<>();
for (RouteLocator locator : routeLocators) {
ignoredPaths.addAll(locator.getIgnoredPaths());
}
return ignoredPaths;
}
@Override
public List<Route> getRoutes() {
List<Route> route = new ArrayList<>();
for (RouteLocator locator : routeLocators) {
route.addAll(locator.getRoutes());
}
return route;
}
@Override
public Route getMatchingRoute(String path) {
for (RouteLocator locator : routeLocators) {
Route route = locator.getMatchingRoute(path);
if (route != null) {
return route;
}
}
return null;
}
@Override
public void refresh() {
for (RouteLocator locator : routeLocators) {
if (locator instanceof RefreshableRouteLocator) {
((RefreshableRouteLocator) locator).refresh();
}
}
}
}
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codecentric.boot.admin.zuul.filters;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
public class CompositeRouteLocatorTest {
private CompositeRouteLocator locator;
public CompositeRouteLocatorTest() {
List<RouteLocator> locators = new ArrayList<>();
locators.add(new TestRouteLocator(asList("ign1"),
asList(createRoute("1", "/pathA"))));
locators.add(
new TestRouteLocator(asList("ign1", "ign2"),
asList(createRoute("2", "/pathA"), createRoute("2", "/pathB"))));
this.locator = new CompositeRouteLocator(locators);
}
@Test
public void test_getIgnoredPaths() {
assertThat(locator.getIgnoredPaths(), hasItems("ign1", "ign2"));
}
@Test
public void test_getRoutes() {
assertThat(locator.getRoutes(),
hasItems(createRoute("1", "/pathA"), createRoute("2", "/pathB")));
}
@Test
public void test_getMatchingRoute() {
assertThat(locator.getMatchingRoute("/pathA"), notNullValue());
assertThat(locator.getMatchingRoute("/pathA").getId(), is("1"));
assertThat("Locator 1 should take precedence", locator.getMatchingRoute("/pathB").getId(),
is("2"));
assertThat(locator.getMatchingRoute("/pathNot"), nullValue());
}
@Test
public void test_refresh() {
RefreshableRouteLocator mock = mock(RefreshableRouteLocator.class);
new CompositeRouteLocator(asList(mock)).refresh();
verify(mock).refresh();
}
private Route createRoute(String id, String path) {
return new Route(id, path, null, null, false, Collections.<String>emptySet());
}
private static class TestRouteLocator implements RouteLocator {
private Collection<String> ignoredPaths;
private List<Route> routes;
public TestRouteLocator(Collection<String> ignoredPaths, List<Route> routes) {
this.ignoredPaths = ignoredPaths;
this.routes = routes;
}
@Override
public Collection<String> getIgnoredPaths() {
return this.ignoredPaths;
}
@Override
public List<Route> getRoutes() {
return this.routes;
}
@Override
public Route getMatchingRoute(String path) {
for (Route route : routes) {
if (path.startsWith(route.getPath())) {
return route;
}
}
return null;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment