Add new filters actuator endpoint (#2244)
* Add new Zuul filters endpoint and refactor routes endpoint * Refactor FiltersEndpoint - Extend from AbstractEndpoint and simplify code - Move tests classes into package endpoint - Remove usage of Lombok * Conditionally enable Zuul routes and filters endpoints * Provide FilterRegistry to FiltersEndpoint via constructor
This commit is contained in:
committed by
Spencer Gibb
parent
ffc431753b
commit
de16cb71f1
@@ -1700,11 +1700,17 @@ Security. The assumption in this case is that the downstream services
|
||||
might add these headers too, and we want the values from the proxy.
|
||||
To not discard these well known security headers in case Spring Security is on the classpath you can set `zuul.ignoreSecurityHeaders` to `false`. This can be useful if you disabled the HTTP Security response headers in Spring Security and want the values provided by downstream services
|
||||
|
||||
=== The Routes Endpoint
|
||||
=== Management Endpoints
|
||||
|
||||
If you are using `@EnableZuulProxy` with tha Spring Boot Actuator you
|
||||
will enable (by default) an additional endpoint, available via HTTP as
|
||||
`/routes`. A GET to this endpoint will return a list of the mapped
|
||||
If you are using `@EnableZuulProxy` with the Spring Boot Actuator you
|
||||
will enable (by default) two additional endpoints:
|
||||
|
||||
* Routes
|
||||
* Filters
|
||||
|
||||
==== Routes Endpoint
|
||||
|
||||
A GET to the routes endpoint at `/routes` will return a list of the mapped
|
||||
routes:
|
||||
|
||||
.GET /routes
|
||||
@@ -1743,6 +1749,12 @@ NOTE: the routes should respond automatically to changes in the
|
||||
service catalog, but the POST to /routes is a way to force the change
|
||||
to happen immediately.
|
||||
|
||||
==== Filters Endpoint
|
||||
|
||||
A GET to the filters endpoint at `/filters` will return a map of Zuul
|
||||
filters by type. For each filter type in the map, you will find a list
|
||||
of all the filters of that type, along with their details.
|
||||
|
||||
=== Strangulation Patterns and Local Forwards
|
||||
|
||||
A common pattern when migrating an existing application or API is to
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.filters.FilterRegistry;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Endpoint for listing Zuul filters.
|
||||
*
|
||||
* @author Daryl Robbins
|
||||
* @author Gregor Zurowski
|
||||
*/
|
||||
@ManagedResource(description = "List Zuul filters")
|
||||
public class FiltersEndpoint extends AbstractEndpoint<Map<String, List<Map<String, Object>>>> {
|
||||
|
||||
private static final String ID = "filters";
|
||||
|
||||
private final FilterRegistry filterRegistry;
|
||||
|
||||
public FiltersEndpoint(FilterRegistry filterRegistry) {
|
||||
super(ID, true);
|
||||
this.filterRegistry = filterRegistry;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
@Override
|
||||
public Map<String, List<Map<String, Object>>> invoke() {
|
||||
// Map of filters by type
|
||||
final Map<String, List<Map<String, Object>>> filterMap = new TreeMap<>();
|
||||
|
||||
for (ZuulFilter filter : this.filterRegistry.getAllFilters()) {
|
||||
// Ensure that we have a list to store filters of each type
|
||||
if (!filterMap.containsKey(filter.filterType())) {
|
||||
filterMap.put(filter.filterType(), new ArrayList<Map<String, Object>>());
|
||||
}
|
||||
|
||||
final Map<String, Object> filterInfo = new LinkedHashMap<>();
|
||||
filterInfo.put("class", filter.getClass().getName());
|
||||
filterInfo.put("order", filter.filterOrder());
|
||||
filterInfo.put("disabled", filter.isFilterDisabled());
|
||||
filterInfo.put("static", filter.isStaticFilter());
|
||||
|
||||
filterMap.get(filter.filterType()).add(filterInfo);
|
||||
}
|
||||
|
||||
return filterMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,8 +19,10 @@ package org.springframework.cloud.netflix.zuul;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.zuul.filters.FilterRegistry;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@@ -158,22 +160,31 @@ public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Endpoint.class)
|
||||
protected static class RoutesEndpointConfiguration {
|
||||
protected static class EndpointConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private TraceRepository traces;
|
||||
|
||||
@ConditionalOnEnabledEndpoint("routes")
|
||||
@Bean
|
||||
public RoutesEndpoint zuulEndpoint(RouteLocator routeLocator) {
|
||||
public RoutesEndpoint routesEndpoint(RouteLocator routeLocator) {
|
||||
return new RoutesEndpoint(routeLocator);
|
||||
}
|
||||
|
||||
@ConditionalOnEnabledEndpoint("routes")
|
||||
@Bean
|
||||
public RoutesMvcEndpoint zuulMvcEndpoint(RouteLocator routeLocator,
|
||||
public RoutesMvcEndpoint routesMvcEndpoint(RouteLocator routeLocator,
|
||||
RoutesEndpoint endpoint) {
|
||||
return new RoutesMvcEndpoint(endpoint, routeLocator);
|
||||
}
|
||||
|
||||
@ConditionalOnEnabledEndpoint("filters")
|
||||
@Bean
|
||||
public FiltersEndpoint filtersEndpoint() {
|
||||
FilterRegistry filterRegistry = FilterRegistry.instance();
|
||||
return new FiltersEndpoint(filterRegistry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {
|
||||
TraceProxyRequestHelper helper = new TraceProxyRequestHelper();
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.validator.internal.util.Contracts.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for Filters endpoint
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = FiltersEndpointApplication.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
value = { "server.contextPath: /app" })
|
||||
public class FiltersEndpointTests {
|
||||
|
||||
@Autowired
|
||||
private FiltersEndpoint endpoint;
|
||||
|
||||
@Test
|
||||
public void getFilters() {
|
||||
final Map<String, List<Map<String, Object>>> filters = endpoint.invoke();
|
||||
|
||||
boolean foundFilter = false;
|
||||
|
||||
if (filters.containsKey("sample")) {
|
||||
for (Map<String, Object> filterInfo : filters.get("sample")) {
|
||||
if (TestFilter.class.getName().equals(filterInfo.get("class"))) {
|
||||
foundFilter = true;
|
||||
|
||||
// Verify filter's attributes
|
||||
assertEquals(0, filterInfo.get("order"));
|
||||
|
||||
break; // the search is over
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(foundFilter, "Could not find expected sample filter from filters endpoint");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
@EnableZuulProxy
|
||||
class FiltersEndpointApplication {
|
||||
|
||||
@Bean
|
||||
public ZuulFilter sampleFilter() {
|
||||
return new TestFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestFilter extends ZuulFilter {
|
||||
@Override
|
||||
public String filterType() {
|
||||
return "sample";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int filterOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
|
||||
import org.springframework.cloud.netflix.zuul.filters.Route;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesMvcEndpoint;
|
||||
import org.springframework.cloud.netflix.zuul.filters.Route;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
||||
@@ -23,12 +23,9 @@ import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.BasicCookieStore;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -42,7 +39,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientFactory;
|
||||
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration;
|
||||
|
||||
Reference in New Issue
Block a user