Commit 243e163d by Dave Syer

Add JMX and MVC endpoints to ZuulHandlerMapping

User can now list routes with /zuul/routes and reset with a POST. Fixes gh-75
parent 05fe1752
...@@ -3,57 +3,102 @@ package org.springframework.cloud.netflix.zuul; ...@@ -3,57 +3,102 @@ package org.springframework.cloud.netflix.zuul;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.cloud.client.discovery.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.InstanceRegisteredEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping; import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
/** /**
* MVC HandlerMapping that maps incoming request paths to remote services.
*
* @author Spencer Gibb * @author Spencer Gibb
* @author Dave Syer
*/ */
public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements ApplicationListener<InstanceRegisteredEvent> { @ManagedResource(description = "Can be used to list and reset the reverse proxy routes")
public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
ApplicationListener<InstanceRegisteredEvent>, MvcEndpoint {
private RouteLocator routeLocator; private RouteLocator routeLocator;
private ZuulController zuul; private ZuulController zuul;
private ZuulProperties properties; private ZuulProperties properties;
@Autowired @Autowired
public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul, ZuulProperties properties) { public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul,
this.routeLocator = routeLocator; ZuulProperties properties) {
this.routeLocator = routeLocator;
this.zuul = zuul; this.zuul = zuul;
this.properties = properties; this.properties = properties;
setOrder(-200); setOrder(-200);
} }
@Override @Override
public void onApplicationEvent(InstanceRegisteredEvent event) { public void onApplicationEvent(InstanceRegisteredEvent event) {
registerHandlers(routeLocator.getRoutes()); registerHandlers(routeLocator.getRoutes());
} }
private void registerHandlers(Map<String, String> routes) { private void registerHandlers(Map<String, String> routes) {
if (routes.isEmpty()) { if (routes.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
} }
else { else {
for (Map.Entry<String, String> entry : routes.entrySet()) { for (Map.Entry<String, String> entry : routes.entrySet()) {
String url = entry.getKey(); String url = entry.getKey();
// Prepend with slash if not already present. // Prepend with slash if not already present.
if (!url.startsWith("/")) { if (!url.startsWith("/")) {
url = "/" + url; url = "/" + url;
} }
if (StringUtils.hasText(properties.getRoutePrefix())) { if (StringUtils.hasText(properties.getRoutePrefix())) {
url = properties.getMapping()+url; url = properties.getMapping() + url;
if (!url.startsWith("/")) { if (!url.startsWith("/")) {
url = "/" + url; url = "/" + url;
} }
} }
registerHandler(url, zuul); registerHandler(url, zuul);
} }
} }
} }
@RequestMapping(value = "routes", method = RequestMethod.POST)
@ResponseBody
@ManagedOperation
public Map<String, String> reset() {
Map<String, String> routes = routeLocator.getRoutes();
registerHandlers(routes);
return routes;
}
@RequestMapping(value = "routes", method = RequestMethod.GET)
@ResponseBody
@ManagedAttribute
public Map<String, String> getRoutes() {
return routeLocator.getRoutes();
}
@Override
public String getPath() {
return "/proxy";
}
@Override
public boolean isSensitive() {
return true;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
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