Commit ce1fcb15 by Dave Syer

Remove ugly depednency on Environment

You can bind to a Map<String,String> with application.yml, so there's no need to work so hard to extract the zuul routes.
parent 243e163d
...@@ -4,34 +4,24 @@ import java.lang.reflect.Field; ...@@ -4,34 +4,24 @@ import java.lang.reflect.Field;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.bind.PropertySourceUtils;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@Slf4j @Slf4j
public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent>, EnvironmentAware { public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent> {
public static final String DEFAULT_ROUTE = "/"; public static final String DEFAULT_ROUTE = "/";
private ConfigurableEnvironment env = new StandardEnvironment();
private DiscoveryClient discovery; private DiscoveryClient discovery;
private ZuulProperties properties; private ZuulProperties properties;
...@@ -39,11 +29,6 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent> ...@@ -39,11 +29,6 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent>
private Field propertySourcesField; private Field propertySourcesField;
private AtomicReference<LinkedHashMap<String, String>> routes = new AtomicReference<>(); private AtomicReference<LinkedHashMap<String, String>> routes = new AtomicReference<>();
@Override
public void setEnvironment(Environment environment) {
env = (ConfigurableEnvironment) environment;
}
public RouteLocator(DiscoveryClient discovery, ZuulProperties properties) { public RouteLocator(DiscoveryClient discovery, ZuulProperties properties) {
this.discovery = discovery; this.discovery = discovery;
this.properties = properties; this.properties = properties;
...@@ -51,21 +36,21 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent> ...@@ -51,21 +36,21 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent>
} }
private void initField() { private void initField() {
propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class, "propertySources"); propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class,
"propertySources");
propertySourcesField.setAccessible(true); propertySourcesField.setAccessible(true);
} }
@Override @Override
public void onApplicationEvent(EnvironmentChangeEvent event) { public void onApplicationEvent(EnvironmentChangeEvent event) {
for (String key : event.getKeys()) { for (String key : event.getKeys()) {
if (key.startsWith(properties.getRoutePrefix())) { if (key.startsWith(properties.getMapping())) {
routes.set(locateRoutes()); routes.set(locateRoutes());
return; return;
} }
} }
} }
//TODO: respond to changes in eureka
public Map<String, String> getRoutes() { public Map<String, String> getRoutes() {
if (routes.get() == null) { if (routes.get() == null) {
routes.set(locateRoutes()); routes.set(locateRoutes());
...@@ -77,54 +62,37 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent> ...@@ -77,54 +62,37 @@ public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent>
protected LinkedHashMap<String, String> locateRoutes() { protected LinkedHashMap<String, String> locateRoutes() {
LinkedHashMap<String, String> routesMap = new LinkedHashMap<>(); LinkedHashMap<String, String> routesMap = new LinkedHashMap<>();
//Add routes for discovery services by default // Add routes for discovery services by default
List<String> services = discovery.getServices(); List<String> services = discovery.getServices();
for (String serviceId : services) { for (String serviceId : services) {
//Ignore specified services // Ignore specified services
if (!properties.getIgnoredServices().contains(serviceId)) if (!properties.getIgnoredServices().contains(serviceId))
routesMap.put("/" + serviceId + "/**", serviceId); routesMap.put("/" + serviceId + "/**", serviceId);
} }
MutablePropertySources propertySources = env.getPropertySources(); addConfiguredRoutes(routesMap);
for (PropertySource<?> propertySource : propertySources) {
getRoutes(propertySource, routesMap);
}
String defaultServiceId = routesMap.get(DEFAULT_ROUTE); String defaultServiceId = routesMap.get(DEFAULT_ROUTE);
if (defaultServiceId != null) { if (defaultServiceId != null) {
//move the defaultServiceId to the end // move the defaultServiceId to the end
routesMap.remove(DEFAULT_ROUTE); routesMap.remove(DEFAULT_ROUTE);
routesMap.put(DEFAULT_ROUTE, defaultServiceId); routesMap.put(DEFAULT_ROUTE, defaultServiceId);
} }
return routesMap; return routesMap;
} }
protected void getRoutes(PropertySource<?> propertySource, Map<String, String> routes) { protected void addConfiguredRoutes(Map<String, String> routes) {
if (propertySource instanceof CompositePropertySource) { Map<String, String> routeEntries = properties.getRoute();
try { for (Map.Entry<String, String> entry : routeEntries.entrySet()) {
@SuppressWarnings("unchecked")
Set<PropertySource<?>> sources = (Set<PropertySource<?>>) propertySourcesField.get(propertySource);
for (PropertySource<?> source : sources) {
getRoutes(source, routes);
}
} catch (IllegalAccessException e) {
return;
}
} else {
//EnumerablePropertySource enumerable = (EnumerablePropertySource) propertySource;
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(propertySource);
Map<String, Object> routeEntries = PropertySourceUtils.getSubProperties(propertySources, properties.getRoutePrefix());
for (Map.Entry<String, Object> entry : routeEntries.entrySet()) {
String serviceId = entry.getKey(); String serviceId = entry.getKey();
String route = entry.getValue().toString(); String route = entry.getValue() ;
if (routes.containsKey(route)) { if (routes.containsKey(route)) {
log.warn("Overwriting route {}: already defined by {}", route, routes.get(route)); log.warn("Overwriting route {}: already defined by {}", route,
routes.get(route));
} }
routes.put(route, serviceId); routes.put(route, serviceId);
} }
} }
}
} }
...@@ -58,7 +58,7 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements ...@@ -58,7 +58,7 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
url = "/" + url; url = "/" + url;
} }
if (StringUtils.hasText(properties.getRoutePrefix())) { if (StringUtils.hasText(properties.getMapping())) {
url = properties.getMapping() + url; url = properties.getMapping() + url;
if (!url.startsWith("/")) { if (!url.startsWith("/")) {
url = "/" + url; url = "/" + url;
......
package org.springframework.cloud.netflix.zuul; package org.springframework.cloud.netflix.zuul;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
...@@ -14,7 +17,7 @@ import java.util.List; ...@@ -14,7 +17,7 @@ import java.util.List;
public class ZuulProperties { public class ZuulProperties {
private String mapping = ""; private String mapping = "";
private boolean stripMapping = false; private boolean stripMapping = false;
private String routePrefix = "zuul.route."; private Map<String,String> route = new HashMap<String, String>();
private boolean addProxyHeaders = true; private boolean addProxyHeaders = true;
private List<String> ignoredServices = Collections.emptyList(); private List<String> ignoredServices = Collections.emptyList();
} }
package org.springframework.cloud.netflix.zuul; package org.springframework.cloud.netflix.zuul;
import com.google.common.collect.Lists; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.Map;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock; import org.mockito.Mock;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.mock.env.MockPropertySource;
import java.util.Map; import com.google.common.collect.Lists;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
...@@ -23,6 +25,7 @@ public class RouteLocatorTests { ...@@ -23,6 +25,7 @@ public class RouteLocatorTests {
public static final String IGNOREDSERVICE = "ignoredservice"; public static final String IGNOREDSERVICE = "ignoredservice";
public static final String ASERVICE = "aservice"; public static final String ASERVICE = "aservice";
public static final String MYSERVICE = "myservice"; public static final String MYSERVICE = "myservice";
@Mock @Mock
ConfigurableEnvironment env; ConfigurableEnvironment env;
...@@ -39,12 +42,8 @@ public class RouteLocatorTests { ...@@ -39,12 +42,8 @@ public class RouteLocatorTests {
ZuulProperties properties = new ZuulProperties(); ZuulProperties properties = new ZuulProperties();
RouteLocator routeLocator = new RouteLocator(this.discovery, properties); RouteLocator routeLocator = new RouteLocator(this.discovery, properties);
properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE)); properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE));
routeLocator.setEnvironment(this.env); properties.getRoute().put(ASERVICE, "/"+ASERVICE + "/**");
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addFirst(new MockPropertySource().withProperty("zuul.route."
+ ASERVICE, getMapping(ASERVICE)));
when(env.getPropertySources()).thenReturn(propertySources);
when(discovery.getServices()).thenReturn( when(discovery.getServices()).thenReturn(
Lists.newArrayList(MYSERVICE, IGNOREDSERVICE)); Lists.newArrayList(MYSERVICE, IGNOREDSERVICE));
......
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