Commit 2cdcd767 by Dave Syer

Move some of the routing logic into the route locator

We now support prefix stripping per service, e.g. zuul: routes: customers: path: /customers/** stripPrefix: true Will route /customers/101 -> /101 (on the customers service) See gh-77
parent 34f277b8
...@@ -551,7 +551,19 @@ The location of the backend can be specified as either a "serviceId" ...@@ -551,7 +551,19 @@ The location of the backend can be specified as either a "serviceId"
Forwarding to the service is protected by a Hystrix circuit breaker so if a service is down the client will see an error, but once the circuit is open the proxy will not try to contact the service. Forwarding to the service is protected by a Hystrix circuit breaker so if a service is down the client will see an error, but once the circuit is open the proxy will not try to contact the service.
To add a prefix to the mapping, set `zuul.prefix` to a value, such as `/api`. To strip the proxy prefix from the request before the request is forwarded set `zuul.stripPrefix = true`. To add a prefix to all mappings, set `zuul.prefix` to a value, such as `/api`. To strip the proxy prefix from the request before the request is forwarded set `zuul.stripPrefix = true`. You can also strip the non-wildcard prefix from individual routes, e.g.
.application.yml
[source,yaml]
----
zuul:
routes:
users:
path: /myusers/**
stripPrefix: true
----
In this example requests to "/myusers/101" will be forwarded to "/101" on the "users" service (the path is stripped up to the first wildcard character).
The `X-Forwarded-Host` header added to the forwarded requests by default. To turn it off set `zuul.addProxyHeaders = false`. The `X-Forwarded-Host` header added to the forwarded requests by default. To turn it off set `zuul.addProxyHeaders = false`.
......
package org.springframework.cloud.netflix.zuul;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.netflix.zuul.ZuulProperties.ZuulRoute;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* @author Spencer Gibb
*/
@Slf4j
public class ProxyRouteLocator implements ApplicationListener<EnvironmentChangeEvent> {
public static final String DEFAULT_ROUTE = "/";
private DiscoveryClient discovery;
private ZuulProperties properties;
private PathMatcher pathMatcher = new AntPathMatcher();
private Field propertySourcesField;
private AtomicReference<Map<String, ZuulRoute>> routes = new AtomicReference<>();
private Map<String, String> staticRoutes = new LinkedHashMap<String, String>();
public ProxyRouteLocator(DiscoveryClient discovery, ZuulProperties properties) {
this.discovery = discovery;
this.properties = properties;
initField();
}
private void initField() {
propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class,
"propertySources");
propertySourcesField.setAccessible(true);
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
for (String key : event.getKeys()) {
if (key.startsWith("zuul.routes")) {
resetRoutes();
return;
}
}
}
public void addRoute(String path, String location) {
staticRoutes.put(path, location);
resetRoutes();
}
public Collection<String> getRoutePaths() {
return getRoutes().keySet();
}
public Map<String, String> getRoutes() {
if (routes.get() == null) {
routes.set(locateRoutes());
}
Map<String, String> values = new LinkedHashMap<String, String>();
for (String key : routes.get().keySet()) {
String url = key;
values.put(url, routes.get().get(key).getLocation());
}
return values;
}
public ProxyRouteSpec getMatchingRoute(String path) {
String location = null;
String targetPath = null;
for (Entry<String, ZuulRoute> entry : routes.get().entrySet()) {
String pattern = entry.getKey();
if (pathMatcher.match(pattern, path)) {
ZuulRoute route = entry.getValue();
String prefix = properties.getPrefix();
location = route.getLocation();
targetPath = path;
if (path.startsWith(prefix) && properties.isStripPrefix()) {
targetPath = path.substring(prefix.length());
}
if (route.isStripPrefix()) {
int index = route.getPath().indexOf("*");
index = index > 0 ? index-1 : 0;
targetPath = path.substring(index);
}
}
}
return location==null ? null : new ProxyRouteSpec(targetPath, location);
}
// Package access so ZuulHandlerMapping can reset it's mappings
void resetRoutes() {
routes.set(locateRoutes());
}
protected LinkedHashMap<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();
addConfiguredRoutes(routesMap);
addStaticRoutes(routesMap);
// Add routes for discovery services by default
List<String> services = discovery.getServices();
for (String serviceId : services) {
// Ignore specifically ignored services and those that were manually
// configured
String key = "/" + serviceId + "/**";
if (!properties.getIgnoredServices().contains(serviceId)
&& !routesMap.containsKey(key)) {
routesMap.put(key, new ZuulRoute(key, serviceId));
}
}
if (routesMap.get(DEFAULT_ROUTE) != null) {
String defaultServiceId = routesMap.get(DEFAULT_ROUTE).getServiceId();
// Move the defaultServiceId to the end
routesMap.remove(DEFAULT_ROUTE);
routesMap.put(DEFAULT_ROUTE, new ZuulRoute(defaultServiceId));
}
LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
for (Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
String path = entry.getKey();
// Prepend with slash if not already present.
if (!path.startsWith("/")) {
path = "/" + path;
}
if (StringUtils.hasText(properties.getPrefix())) {
path = properties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
}
values.put(path, entry.getValue());
}
return values;
}
protected void addStaticRoutes(LinkedHashMap<String, ZuulRoute> routes) {
for (Entry<String, String> entry : staticRoutes.entrySet()) {
routes.put(entry.getKey(), new ZuulRoute(entry.getKey(), entry.getValue()));
}
}
protected void addConfiguredRoutes(Map<String, ZuulRoute> routes) {
Map<String, ZuulRoute> routeEntries = properties.getRoutesWithDefaultServiceIds();
for (ZuulRoute entry : routeEntries.values()) {
String route = entry.getPath();
if (routes.containsKey(route)) {
log.warn("Overwriting route {}: already defined by {}", route,
routes.get(route));
}
routes.put(route, entry);
}
}
public String getTargetPath(String matchingRoute, String requestURI) {
String path = getRoutes().get(matchingRoute);
if (path==null) {
path = requestURI;
} else {
}
return path;
}
@Data
@AllArgsConstructor
public static class ProxyRouteSpec {
private String path;
private String location;
}
}
...@@ -40,8 +40,8 @@ public class ZuulConfiguration { ...@@ -40,8 +40,8 @@ public class ZuulConfiguration {
private ZuulProperties zuulProperties; private ZuulProperties zuulProperties;
@Bean @Bean
public ZuulRouteLocator routes() { public ProxyRouteLocator routes() {
return new ZuulRouteLocator(discovery, zuulProperties); return new ProxyRouteLocator(discovery, zuulProperties);
} }
@Bean @Bean
...@@ -51,7 +51,7 @@ public class ZuulConfiguration { ...@@ -51,7 +51,7 @@ public class ZuulConfiguration {
@Bean @Bean
public ZuulHandlerMapping zuulHandlerMapping() { public ZuulHandlerMapping zuulHandlerMapping() {
return new ZuulHandlerMapping(routes(), zuulController(), zuulProperties); return new ZuulHandlerMapping(routes(), zuulController());
} }
@Configuration @Configuration
......
...@@ -11,7 +11,6 @@ import org.springframework.context.ApplicationListener; ...@@ -11,7 +11,6 @@ import org.springframework.context.ApplicationListener;
import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
...@@ -27,24 +26,20 @@ import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping; ...@@ -27,24 +26,20 @@ import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
ApplicationListener<InstanceRegisteredEvent>, MvcEndpoint { ApplicationListener<InstanceRegisteredEvent>, MvcEndpoint {
private ZuulRouteLocator routeLocator; private ProxyRouteLocator routeLocator;
private ZuulController zuul; private ZuulController zuul;
private ZuulProperties properties;
@Autowired @Autowired
public ZuulHandlerMapping(ZuulRouteLocator routeLocator, ZuulController zuul, public ZuulHandlerMapping(ProxyRouteLocator routeLocator, ZuulController zuul) {
ZuulProperties properties) {
this.routeLocator = routeLocator; this.routeLocator = routeLocator;
this.zuul = zuul; this.zuul = zuul;
this.properties = properties;
setOrder(-200); setOrder(-200);
} }
@Override @Override
public void onApplicationEvent(InstanceRegisteredEvent event) { public void onApplicationEvent(InstanceRegisteredEvent event) {
registerHandlers(routeLocator.getRoutes().keySet()); registerHandlers(routeLocator.getRoutePaths());
} }
protected void registerHandlers(Collection<String> routes) { protected void registerHandlers(Collection<String> routes) {
...@@ -53,18 +48,6 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements ...@@ -53,18 +48,6 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
} }
else { else {
for (String url : routes) { for (String url : routes) {
// Prepend with slash if not already present.
if (!url.startsWith("/")) {
url = "/" + url;
}
if (StringUtils.hasText(properties.getPrefix())) {
url = properties.getPrefix() + url;
if (!url.startsWith("/")) {
url = "/" + url;
}
}
registerHandler(url, zuul); registerHandler(url, zuul);
} }
} }
...@@ -75,7 +58,7 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements ...@@ -75,7 +58,7 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
@ManagedOperation @ManagedOperation
public Map<String, String> reset() { public Map<String, String> reset() {
routeLocator.resetRoutes(); routeLocator.resetRoutes();
registerHandlers(routeLocator.getRoutes().keySet()); registerHandlers(routeLocator.getRoutePaths());
return getRoutes(); return getRoutes();
} }
......
...@@ -43,7 +43,7 @@ public class ZuulProperties { ...@@ -43,7 +43,7 @@ public class ZuulProperties {
private String path; private String path;
private String serviceId; private String serviceId;
private String url; private String url;
private boolean stripPath = false; private boolean stripPrefix = false;
public ZuulRoute(String text) { public ZuulRoute(String text) {
String location = null; String location = null;
......
package org.springframework.cloud.netflix.zuul;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.netflix.zuul.ZuulProperties.ZuulRoute;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.util.ReflectionUtils;
/**
* @author Spencer Gibb
*/
@Slf4j
public class ZuulRouteLocator implements ApplicationListener<EnvironmentChangeEvent> {
public static final String DEFAULT_ROUTE = "/";
private DiscoveryClient discovery;
private ZuulProperties properties;
private Field propertySourcesField;
private AtomicReference<LinkedHashMap<String, String>> routes = new AtomicReference<>();
public ZuulRouteLocator(DiscoveryClient discovery, ZuulProperties properties) {
this.discovery = discovery;
this.properties = properties;
initField();
}
private void initField() {
propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class,
"propertySources");
propertySourcesField.setAccessible(true);
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
for (String key : event.getKeys()) {
if (key.startsWith("zuul.route")) {
resetRoutes();
return;
}
}
}
public Collection<String> getRoutePaths() {
return getRoutes().keySet();
}
public Map<String, String> getRoutes() {
if (routes.get() == null) {
resetRoutes();
}
return routes.get();
}
//access so ZuulHandlerMapping actuator can reset it's mappings
/*package*/ void resetRoutes() {
LinkedHashMap<String, String> newValue = locateRoutes();
routes.set(newValue);
}
protected LinkedHashMap<String, String> locateRoutes() {
LinkedHashMap<String, String> routesMap = new LinkedHashMap<>();
addConfiguredRoutes(routesMap);
String defaultServiceId = routesMap.get(DEFAULT_ROUTE);
// Add routes for discovery services by default
List<String> services = discovery.getServices();
for (String serviceId : services) {
// Ignore specifically ignored services and those that were manually configured
String key = "/" + serviceId + "/**";
if (!properties.getIgnoredServices().contains(serviceId) && !routesMap.containsKey(key)) {
routesMap.put(key, serviceId);
}
}
if (defaultServiceId != null) {
// move the defaultServiceId to the end
routesMap.remove(DEFAULT_ROUTE);
routesMap.put(DEFAULT_ROUTE, defaultServiceId);
}
return routesMap;
}
protected void addConfiguredRoutes(Map<String, String> routes) {
Map<String, ZuulRoute> routeEntries = properties.getRoutesWithDefaultServiceIds();
for (ZuulRoute entry : routeEntries.values()) {
String location = entry.getLocation();
String route = entry.getPath();
if (routes.containsKey(route)) {
log.warn("Overwriting route {}: already defined by {}", route,
routes.get(route));
}
routes.put(route, location);
}
}
}
package org.springframework.cloud.netflix.zuul.filters.pre; package org.springframework.cloud.netflix.zuul.filters.pre;
import static com.google.common.collect.Iterables.tryFind;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.ZuulRouteLocator; import org.springframework.cloud.netflix.zuul.ProxyRouteLocator;
import org.springframework.cloud.netflix.zuul.ProxyRouteLocator.ProxyRouteSpec;
import org.springframework.cloud.netflix.zuul.ZuulProperties; import org.springframework.cloud.netflix.zuul.ZuulProperties;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.context.RequestContext;
public class PreDecorationFilter extends ZuulFilter { public class PreDecorationFilter extends ZuulFilter {
private static Logger LOG = LoggerFactory.getLogger(PreDecorationFilter.class); private static Logger LOG = LoggerFactory.getLogger(PreDecorationFilter.class);
private ZuulRouteLocator routeLocator; private ProxyRouteLocator routeLocator;
private ZuulProperties properties; private ZuulProperties properties;
private PathMatcher pathMatcher = new AntPathMatcher(); public PreDecorationFilter(ProxyRouteLocator routeLocator, ZuulProperties properties) {
public PreDecorationFilter(ZuulRouteLocator routeLocator, ZuulProperties properties) {
this.routeLocator = routeLocator; this.routeLocator = routeLocator;
this.properties = properties; this.properties = properties;
} }
...@@ -55,44 +45,27 @@ public class PreDecorationFilter extends ZuulFilter { ...@@ -55,44 +45,27 @@ public class PreDecorationFilter extends ZuulFilter {
public Object run() { public Object run() {
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
String requestURI = ctx.getRequest().getRequestURI(); final String requestURI = ctx.getRequest().getRequestURI();
String proxyMapping = properties.getPrefix(); ProxyRouteSpec route = routeLocator.getMatchingRoute(requestURI);
final String uriPart; if (route!=null) {
if (StringUtils.hasText(proxyMapping) && properties.isStripPrefix()
&& requestURI.startsWith(proxyMapping)) {
// TODO: better strategy?
uriPart = requestURI.substring(proxyMapping.length());
}
else {
uriPart = requestURI;
}
ctx.put("requestURI", uriPart);
Map<String, String> routesMap = routeLocator.getRoutes();
Optional<String> route = tryFind(routesMap.keySet(), new Predicate<String>() { String location = route.getLocation();
@Override
public boolean apply(@Nullable String path) {
return pathMatcher.match(path, uriPart);
}
});
if (route.isPresent()) { if (location != null) {
String target = routesMap.get(route.get());
if (target != null) { ctx.put("requestURI", route.getPath());
if (target.startsWith("http:") || target.startsWith("https:")) { if (location.startsWith("http:") || location.startsWith("https:")) {
ctx.setRouteHost(getUrl(target)); ctx.setRouteHost(getUrl(location));
ctx.addOriginResponseHeader("X-Zuul-Service", target); ctx.addOriginResponseHeader("X-Zuul-Service", location);
} }
else { else {
// set serviceId for use in filters.route.RibbonRequest // set serviceId for use in filters.route.RibbonRequest
ctx.set("serviceId", target); ctx.set("serviceId", location);
ctx.setRouteHost(null); ctx.setRouteHost(null);
ctx.addOriginResponseHeader("X-Zuul-ServiceId", target); ctx.addOriginResponseHeader("X-Zuul-ServiceId", location);
} }
if (properties.isAddProxyHeaders()) { if (properties.isAddProxyHeaders()) {
......
package org.springframework.cloud.netflix.zuul; package org.springframework.cloud.netflix.zuul.filters.route;
import com.netflix.client.http.HttpRequest; import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse; import com.netflix.client.http.HttpResponse;
......
...@@ -19,7 +19,6 @@ import org.slf4j.LoggerFactory; ...@@ -19,7 +19,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.RibbonClientPreprocessor; import org.springframework.cloud.netflix.ribbon.RibbonClientPreprocessor;
import org.springframework.cloud.netflix.zuul.RibbonCommand;
import org.springframework.cloud.netflix.zuul.SpringFilter; import org.springframework.cloud.netflix.zuul.SpringFilter;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
......
...@@ -13,6 +13,7 @@ import org.junit.Before; ...@@ -13,6 +13,7 @@ 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.cloud.netflix.zuul.ProxyRouteLocator.ProxyRouteSpec;
import org.springframework.cloud.netflix.zuul.ZuulProperties.ZuulRoute; import org.springframework.cloud.netflix.zuul.ZuulProperties.ZuulRoute;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
...@@ -22,7 +23,7 @@ import com.google.common.collect.Lists; ...@@ -22,7 +23,7 @@ import com.google.common.collect.Lists;
* @author Spencer Gibb * @author Spencer Gibb
* @author Dave Syer * @author Dave Syer
*/ */
public class ZuulRouteLocatorTests { public class ProxyRouteLocatorTests {
public static final String IGNOREDSERVICE = "ignoredservice"; public static final String IGNOREDSERVICE = "ignoredservice";
public static final String ASERVICE = "aservice"; public static final String ASERVICE = "aservice";
...@@ -34,16 +35,61 @@ public class ZuulRouteLocatorTests { ...@@ -34,16 +35,61 @@ public class ZuulRouteLocatorTests {
@Mock @Mock
DiscoveryClient discovery; DiscoveryClient discovery;
private ZuulProperties properties = new ZuulProperties();
@Before @Before
public void init() { public void init() {
initMocks(this); initMocks(this);
} }
@Test
public void testGetMatchingPath() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/foo/1");
assertEquals("foo", route.getLocation());
}
@Test
public void testGetMatchingPathWithPrefix() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.setPrefix("/proxy");
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
assertEquals("foo", route.getLocation());
assertEquals("/proxy/foo/1", route.getPath());
}
@Test
public void testGetMatchingPathWithPrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.setStripPrefix(true);
this.properties.setPrefix("/proxy");
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
assertEquals("foo", route.getLocation());
assertEquals("/foo/1", route.getPath());
}
@Test
public void testGetMatchingPathWithRoutePrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRoute zuulRoute = new ZuulRoute("/foo/**");
zuulRoute.setStripPrefix(true);
this.properties.getRoutes().put("foo", zuulRoute);
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/foo/1");
assertEquals("foo", route.getLocation());
assertEquals("/1", route.getPath());
}
@Test @Test
public void testGetRoutes() { public void testGetRoutes() {
ZuulProperties properties = new ZuulProperties(); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties); this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**"));
properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**"));
Map<String, String> routesMap = routeLocator.getRoutes(); Map<String, String> routesMap = routeLocator.getRoutes();
...@@ -54,24 +100,18 @@ public class ZuulRouteLocatorTests { ...@@ -54,24 +100,18 @@ public class ZuulRouteLocatorTests {
@Test @Test
public void testGetRoutesWithMapping() { public void testGetRoutesWithMapping() {
ZuulProperties properties = new ZuulProperties(); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties); this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", ASERVICE));
properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", ASERVICE)); this.properties.setPrefix("/foo");
// Prefix doesn't have any impact on the routes (it's used in the filter)
properties.setPrefix("/foo");
Map<String, String> routesMap = routeLocator.getRoutes(); Map<String, String> routesMap = routeLocator.getRoutes();
assertMapping(routesMap, ASERVICE, "foo/" + ASERVICE);
assertNotNull("routesMap was null", routesMap);
assertFalse("routesMap was empty", routesMap.isEmpty());
assertMapping(routesMap, ASERVICE);
} }
@Test @Test
public void testGetPhysicalRoutes() { public void testGetPhysicalRoutes() {
ZuulProperties properties = new ZuulProperties(); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties); this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", "http://" + ASERVICE));
properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", "http://" + ASERVICE));
Map<String, String> routesMap = routeLocator.getRoutes(); Map<String, String> routesMap = routeLocator.getRoutes();
...@@ -82,9 +122,8 @@ public class ZuulRouteLocatorTests { ...@@ -82,9 +122,8 @@ public class ZuulRouteLocatorTests {
@Test @Test
public void testIgnoreRoutes() { public void testIgnoreRoutes() {
ZuulProperties properties = new ZuulProperties(); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties); this.properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE));
properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE));
when(discovery.getServices()).thenReturn( when(discovery.getServices()).thenReturn(
Lists.newArrayList(IGNOREDSERVICE)); Lists.newArrayList(IGNOREDSERVICE));
...@@ -96,8 +135,7 @@ public class ZuulRouteLocatorTests { ...@@ -96,8 +135,7 @@ public class ZuulRouteLocatorTests {
@Test @Test
public void testAutoRoutes() { public void testAutoRoutes() {
ZuulProperties properties = new ZuulProperties(); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties);
when(discovery.getServices()).thenReturn( when(discovery.getServices()).thenReturn(
Lists.newArrayList(MYSERVICE)); Lists.newArrayList(MYSERVICE));
...@@ -111,9 +149,8 @@ public class ZuulRouteLocatorTests { ...@@ -111,9 +149,8 @@ public class ZuulRouteLocatorTests {
@Test @Test
public void testAutoRoutesCanBeOverridden() { public void testAutoRoutesCanBeOverridden() {
ZuulProperties properties = new ZuulProperties(); this.properties.getRoutes().put(MYSERVICE, new ZuulRoute("/"+MYSERVICE + "/**", "http://example.com/" + MYSERVICE));
properties.getRoutes().put(MYSERVICE, new ZuulRoute("/"+MYSERVICE + "/**", "http://example.com/" + MYSERVICE)); ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ZuulRouteLocator routeLocator = new ZuulRouteLocator(this.discovery, properties);
when(discovery.getServices()).thenReturn( when(discovery.getServices()).thenReturn(
Lists.newArrayList(MYSERVICE)); Lists.newArrayList(MYSERVICE));
......
...@@ -28,13 +28,13 @@ public class SampleZuulProxyApplicationTests { ...@@ -28,13 +28,13 @@ public class SampleZuulProxyApplicationTests {
private int port; private int port;
@Autowired @Autowired
private ZuulRouteLocator routes; private ProxyRouteLocator routes;
@Autowired @Autowired
private ZuulHandlerMapping mapping; private ZuulHandlerMapping mapping;
@Test @Test
public void bindRouteUsingPropertyEditor() { public void bindRouteUsingPhysicalRoute() {
assertEquals("http://localhost:7777/local", routes.getRoutes().get("/test/**")); assertEquals("http://localhost:7777/local", routes.getRoutes().get("/test/**"));
} }
...@@ -45,8 +45,8 @@ public class SampleZuulProxyApplicationTests { ...@@ -45,8 +45,8 @@ public class SampleZuulProxyApplicationTests {
@Test @Test
public void deleteOnSelfViaSimpleHostRoutingFilter() { public void deleteOnSelfViaSimpleHostRoutingFilter() {
routes.getRoutes().put("/self/**", "http://localhost:" + port + "/local"); routes.addRoute("/self/**", "http://localhost:" + port + "/local");
mapping.registerHandlers(routes.getRoutes().keySet()); mapping.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange( ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/self/1", HttpMethod.DELETE, "http://localhost:" + port + "/self/1", HttpMethod.DELETE,
new HttpEntity<Void>((Void) null), String.class); new HttpEntity<Void>((Void) null), String.class);
......
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