From 243e163de4e1a818ff78bd71a05c49012d0a45b8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 26 Nov 2014 10:50:23 +0000 Subject: [PATCH] Add JMX and MVC endpoints to ZuulHandlerMapping User can now list routes with /zuul/routes and reset with a POST. Fixes gh-75 --- .../netflix/zuul/ZuulHandlerMapping.java | 119 ++++++++++++------ 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulHandlerMapping.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulHandlerMapping.java index afaa6a49..d176aae9 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulHandlerMapping.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulHandlerMapping.java @@ -3,57 +3,102 @@ package org.springframework.cloud.netflix.zuul; import java.util.Map; 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.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.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; /** + * MVC HandlerMapping that maps incoming request paths to remote services. + * * @author Spencer Gibb + * @author Dave Syer */ -public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements ApplicationListener { +@ManagedResource(description = "Can be used to list and reset the reverse proxy routes") +public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements + ApplicationListener, MvcEndpoint { - private RouteLocator routeLocator; + private RouteLocator routeLocator; - private ZuulController zuul; + private ZuulController zuul; - private ZuulProperties properties; + private ZuulProperties properties; - @Autowired - public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul, ZuulProperties properties) { - this.routeLocator = routeLocator; + @Autowired + public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul, + ZuulProperties properties) { + this.routeLocator = routeLocator; this.zuul = zuul; this.properties = properties; setOrder(-200); - } - - @Override - public void onApplicationEvent(InstanceRegisteredEvent event) { - registerHandlers(routeLocator.getRoutes()); - } - - private void registerHandlers(Map routes) { - if (routes.isEmpty()) { - logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); - } - else { - for (Map.Entry entry : routes.entrySet()) { - String url = entry.getKey(); - // Prepend with slash if not already present. - if (!url.startsWith("/")) { - url = "/" + url; - } - - if (StringUtils.hasText(properties.getRoutePrefix())) { - url = properties.getMapping()+url; - if (!url.startsWith("/")) { - url = "/" + url; - } - } - - registerHandler(url, zuul); - } - } - } + } + + @Override + public void onApplicationEvent(InstanceRegisteredEvent event) { + registerHandlers(routeLocator.getRoutes()); + } + + private void registerHandlers(Map routes) { + if (routes.isEmpty()) { + logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); + } + else { + for (Map.Entry entry : routes.entrySet()) { + String url = entry.getKey(); + // Prepend with slash if not already present. + if (!url.startsWith("/")) { + url = "/" + url; + } + + if (StringUtils.hasText(properties.getRoutePrefix())) { + url = properties.getMapping() + url; + if (!url.startsWith("/")) { + url = "/" + url; + } + } + + registerHandler(url, zuul); + } + } + } + + @RequestMapping(value = "routes", method = RequestMethod.POST) + @ResponseBody + @ManagedOperation + public Map reset() { + Map routes = routeLocator.getRoutes(); + registerHandlers(routes); + return routes; + } + + @RequestMapping(value = "routes", method = RequestMethod.GET) + @ResponseBody + @ManagedAttribute + public Map getRoutes() { + return routeLocator.getRoutes(); + } + + @Override + public String getPath() { + return "/proxy"; + } + + @Override + public boolean isSensitive() { + return true; + } + + @Override + public Class> getEndpointType() { + return null; + } }