Commit 48913cbb by Dave Syer

Add zuul.ignoredHeaders configuration hook

User can exclude headers (generally in responses is most useful) by configuring them, or calling a setter in ZuulProperties. If Spring Security is on the classpath we add a few headers automatically, corresponding to the ones that would be added by Spring Security in the remote backend anyway (so they are not added twice). Nothing is actually removed, so if the remote service doesn't add those headers, we don't change anything. The X-Application-Context header is also added to the hard coded list of ignored headers, because it isn't relevant in the gateway (and leaks information about the remote service). Fixes gh-819
parent 86ac0127
...@@ -21,7 +21,6 @@ import org.springframework.boot.actuate.endpoint.Endpoint; ...@@ -21,7 +21,6 @@ import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
...@@ -31,7 +30,6 @@ import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; ...@@ -31,7 +30,6 @@ import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator; import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper; import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper;
import org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper; import org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper;
...@@ -99,24 +97,26 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -99,24 +97,26 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
// route filters // route filters
@Bean @Bean
public RibbonRoutingFilter ribbonRoutingFilter( public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,
RibbonCommandFactory<?> ribbonCommandFactory) { RibbonCommandFactory<?> ribbonCommandFactory) {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (this.traces != null) {
helper.setTraces(this.traces);
}
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, RibbonRoutingFilter filter = new RibbonRoutingFilter(helper,
ribbonCommandFactory); ribbonCommandFactory);
return filter; return filter;
} }
@Bean @Bean
public SimpleHostRoutingFilter simpleHostRoutingFilter() { public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper) {
return new SimpleHostRoutingFilter(helper);
}
@Bean
public ProxyRequestHelper proxyRequestHelper() {
ProxyRequestHelper helper = new ProxyRequestHelper(); ProxyRequestHelper helper = new ProxyRequestHelper();
if (this.traces != null) { if (this.traces != null) {
helper.setTraces(this.traces); helper.setTraces(this.traces);
} }
return new SimpleHostRoutingFilter(helper); helper.setIgnoredHeaders(this.zuulProperties.getIgnoredHeaders());
return helper;
} }
@Bean @Bean
......
...@@ -24,6 +24,7 @@ import java.util.Collection; ...@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
...@@ -60,6 +61,12 @@ public class ProxyRequestHelper { ...@@ -60,6 +61,12 @@ public class ProxyRequestHelper {
private TraceRepository traces; private TraceRepository traces;
private Set<String> ignoredHeaders = new LinkedHashSet<>();
public void setIgnoredHeaders(Set<String> ignoredHeaders) {
this.ignoredHeaders = ignoredHeaders;
}
public void setTraces(TraceRepository traces) { public void setTraces(TraceRepository traces) {
this.traces = traces; this.traces = traces;
} }
...@@ -170,6 +177,9 @@ public class ProxyRequestHelper { ...@@ -170,6 +177,9 @@ public class ProxyRequestHelper {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Set<String> set = (Set<String>) ctx.get(IGNORED_HEADERS); Set<String> set = (Set<String>) ctx.get(IGNORED_HEADERS);
for (String name : this.ignoredHeaders) {
set.add(name.toLowerCase());
}
for (String name : names) { for (String name : names) {
set.add(name.toLowerCase()); set.add(name.toLowerCase());
} }
...@@ -191,6 +201,7 @@ public class ProxyRequestHelper { ...@@ -191,6 +201,7 @@ public class ProxyRequestHelper {
case "content-encoding": case "content-encoding":
case "server": case "server":
case "transfer-encoding": case "transfer-encoding":
case "x-application-context":
return false; return false;
default: default:
return true; return true;
...@@ -284,7 +295,7 @@ public class ProxyRequestHelper { ...@@ -284,7 +295,7 @@ public class ProxyRequestHelper {
for (String value : params.get(param)) { for (String value : params.get(param)) {
query.append("&"); query.append("&");
query.append(param); query.append(param);
if(!"".equals(value)) { if (!"".equals(value)) {
query.append("="); query.append("=");
query.append(value); query.append(value);
} }
......
...@@ -16,15 +16,19 @@ ...@@ -16,15 +16,19 @@
package org.springframework.cloud.netflix.zuul.filters; package org.springframework.cloud.netflix.zuul.filters;
import java.util.ArrayList; import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
...@@ -39,6 +43,13 @@ import lombok.NoArgsConstructor; ...@@ -39,6 +43,13 @@ import lombok.NoArgsConstructor;
@ConfigurationProperties("zuul") @ConfigurationProperties("zuul")
public class ZuulProperties { public class ZuulProperties {
/**
*
*/
private static final List<String> SECURITY_HEADERS = Arrays.asList("Pragma",
"Cache-Control", "X-Frame-Options", "X-Content-Type-Options",
"X-XSS-Protection", "Expires");
private String prefix = ""; private String prefix = "";
private boolean stripPrefix = true; private boolean stripPrefix = true;
...@@ -49,14 +60,31 @@ public class ZuulProperties { ...@@ -49,14 +60,31 @@ public class ZuulProperties {
private boolean addProxyHeaders = true; private boolean addProxyHeaders = true;
private List<String> ignoredServices = new ArrayList<>(); private Set<String> ignoredServices = new LinkedHashSet<>();
private List<String> ignoredPatterns = new ArrayList<>(); private Set<String> ignoredPatterns = new LinkedHashSet<>();
private Set<String> ignoredHeaders = new LinkedHashSet<>();
private String servletPath = "/zuul"; private String servletPath = "/zuul";
private boolean ignoreLocalService = true; private boolean ignoreLocalService = true;
public Set<String> getIgnoredHeaders() {
Set<String> ignoredHeaders = new LinkedHashSet<>(this.ignoredHeaders);
if (ClassUtils.isPresent(
"org.springframework.security.config.annotation.web.WebSecurityConfigurer",
null) && Collections.disjoint(ignoredHeaders, SECURITY_HEADERS)) {
// Allow Spring Security in the gateway to control these headers
ignoredHeaders.addAll(SECURITY_HEADERS);
}
return ignoredHeaders;
}
public void setIgnoredHeaders(Set<String> ignoredHeaders) {
this.ignoredHeaders.addAll(ignoredHeaders);
}
@PostConstruct @PostConstruct
public void init() { public void init() {
for (Entry<String, ZuulRoute> entry : this.routes.entrySet()) { for (Entry<String, ZuulRoute> entry : this.routes.entrySet()) {
......
...@@ -72,6 +72,7 @@ public class RibbonRoutingFilter extends ZuulFilter { ...@@ -72,6 +72,7 @@ public class RibbonRoutingFilter extends ZuulFilter {
@Override @Override
public Object run() { public Object run() {
RequestContext context = RequestContext.getCurrentContext(); RequestContext context = RequestContext.getCurrentContext();
this.helper.addIgnoredHeaders();
try { try {
RibbonCommandContext commandContext = buildCommandContext(context); RibbonCommandContext commandContext = buildCommandContext(context);
ClientHttpResponse response = forward(commandContext); ClientHttpResponse response = forward(commandContext);
...@@ -133,7 +134,8 @@ public class RibbonRoutingFilter extends ZuulFilter { ...@@ -133,7 +134,8 @@ public class RibbonRoutingFilter extends ZuulFilter {
} }
protected ClientHttpResponse handleException(Map<String, Object> info, HystrixRuntimeException ex) throws ZuulException { protected ClientHttpResponse handleException(Map<String, Object> info,
HystrixRuntimeException ex) throws ZuulException {
int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
Throwable cause = ex; Throwable cause = ex;
String message = ex.getFailureType().toString(); String message = ex.getFailureType().toString();
...@@ -144,7 +146,8 @@ public class RibbonRoutingFilter extends ZuulFilter { ...@@ -144,7 +146,8 @@ public class RibbonRoutingFilter extends ZuulFilter {
} }
if (clientException != null) { if (clientException != null) {
if (clientException.getErrorType() == ClientException.ErrorType.SERVER_THROTTLED) { if (clientException
.getErrorType() == ClientException.ErrorType.SERVER_THROTTLED) {
statusCode = HttpStatus.SERVICE_UNAVAILABLE.value(); statusCode = HttpStatus.SERVICE_UNAVAILABLE.value();
} }
cause = clientException; cause = clientException;
...@@ -159,7 +162,7 @@ public class RibbonRoutingFilter extends ZuulFilter { ...@@ -159,7 +162,7 @@ public class RibbonRoutingFilter extends ZuulFilter {
return null; return null;
} }
if (t instanceof ClientException) { if (t instanceof ClientException) {
return (ClientException)t; return (ClientException) t;
} }
return findClientException(t.getCause()); return findClientException(t.getCause());
} }
......
...@@ -18,9 +18,7 @@ package org.springframework.cloud.netflix.zuul.filters.route; ...@@ -18,9 +18,7 @@ package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
...@@ -169,6 +167,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter { ...@@ -169,6 +167,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
} }
String uri = this.helper.buildZuulRequestURI(request); String uri = this.helper.buildZuulRequestURI(request);
this.helper.addIgnoredHeaders();
try { try {
HttpResponse response = forward(this.httpClient, verb, uri, request, headers, HttpResponse response = forward(this.httpClient, verb, uri, request, headers,
...@@ -277,7 +276,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter { ...@@ -277,7 +276,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
httpPatch.setEntity(entity); httpPatch.setEntity(entity);
break; break;
default: default:
httpRequest = new BasicHttpRequest(verb, uri + this.helper.getQueryString(params)); httpRequest = new BasicHttpRequest(verb,
uri + this.helper.getQueryString(params));
log.debug(uri + this.helper.getQueryString(params)); log.debug(uri + this.helper.getQueryString(params));
} }
try { try {
......
...@@ -19,13 +19,8 @@ package org.springframework.cloud.netflix.zuul; ...@@ -19,13 +19,8 @@ package org.springframework.cloud.netflix.zuul;
import java.io.InputStream; import java.io.InputStream;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import com.netflix.client.ClientException; import javax.servlet.http.HttpServletRequest;
import com.netflix.client.http.HttpRequest;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.client.http.RestClient;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -45,6 +40,7 @@ import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory ...@@ -45,6 +40,7 @@ import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -57,18 +53,25 @@ import org.springframework.util.MultiValueMap; ...@@ -57,18 +53,25 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import lombok.SneakyThrows; import com.netflix.client.ClientException;
import com.netflix.client.http.HttpRequest;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.client.http.RestClient;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import lombok.SneakyThrows;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class) @SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest({ "server.port: 0", @IntegrationTest({ "server.port: 0",
"zuul.routes.other: /test/**=http://localhost:7777/local", "zuul.routes.other: /test/**=http://localhost:7777/local",
"zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**",
"zuul.routes.badhost: /badhost/**" }) "zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header" })
@DirtiesContext @DirtiesContext
public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
...@@ -84,6 +87,29 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { ...@@ -84,6 +87,29 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
} }
@Test @Test
public void simpleHostRouteIgnoredHeader() {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/add-header", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertNull(result.getHeaders().get("X-Header"));
}
@Test
public void simpleHostRouteDefaultIgnoredHeader() {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/add-header", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("[testclient:0]",
result.getHeaders().get("X-Application-Context").toString());
}
@Test
public void ribbonCommandForbidden() { public void ribbonCommandForbidden() {
ResponseEntity<String> result = new TestRestTemplate().exchange( ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/simple/throwexception/403", "http://localhost:" + this.port + "/simple/throwexception/403",
...@@ -102,15 +128,14 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { ...@@ -102,15 +128,14 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
@Test @Test
public void ribbonCommandBadHost() { public void ribbonCommandBadHost() {
ResponseEntity<String> result = new TestRestTemplate().exchange( ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/badhost/1", "http://localhost:" + this.port + "/badhost/1", HttpMethod.GET,
HttpMethod.GET, new HttpEntity<>((Void) null), String.class); new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode()); assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode());
} }
@Test @Test
public void ribbonCommandFactoryOverridden() { public void ribbonCommandFactoryOverridden() {
assertTrue( assertTrue("ribbonCommandFactory not a MyRibbonCommandFactory",
"ribbonCommandFactory not a MyRibbonCommandFactory",
this.ribbonCommandFactory instanceof SampleZuulProxyApplication.MyRibbonCommandFactory); this.ribbonCommandFactory instanceof SampleZuulProxyApplication.MyRibbonCommandFactory);
} }
...@@ -132,8 +157,18 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl ...@@ -132,8 +157,18 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl
return request.getRequestURI(); return request.getRequestURI();
} }
@RequestMapping(value = "/add-header")
public ResponseEntity<String> addHeader(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.set("X-Header", "FOO");
ResponseEntity<String> result = new ResponseEntity<String>(
request.getRequestURI(), headers, HttpStatus.OK);
return result;
}
@Bean @Bean
public RibbonCommandFactory<?> ribbonCommandFactory(SpringClientFactory clientFactory) { public RibbonCommandFactory<?> ribbonCommandFactory(
SpringClientFactory clientFactory) {
return new MyRibbonCommandFactory(clientFactory); return new MyRibbonCommandFactory(clientFactory);
} }
...@@ -154,12 +189,12 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl ...@@ -154,12 +189,12 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl
String uri = context.getUri(); String uri = context.getUri();
if (uri.startsWith("/throwexception/")) { if (uri.startsWith("/throwexception/")) {
String code = uri.replace("/throwexception/", ""); String code = uri.replace("/throwexception/", "");
RestClient restClient = getClientFactory().getClient(context.getServiceId(), RestClient restClient = getClientFactory()
RestClient.class); .getClient(context.getServiceId(), RestClient.class);
return new MyCommand(Integer.parseInt(code), return new MyCommand(Integer.parseInt(code), context.getServiceId(),
context.getServiceId(), restClient, getVerb(context.getVerb()), restClient, getVerb(context.getVerb()), context.getUri(),
context.getUri(), context.getRetryable(), context.getHeaders(), context.getRetryable(), context.getHeaders(), context.getParams(),
context.getParams(), context.getRequestEntity()); context.getRequestEntity());
} }
return super.create(context); return super.create(context);
} }
...@@ -169,17 +204,23 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl ...@@ -169,17 +204,23 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl
private int errorCode; private int errorCode;
public MyCommand(int errorCode, String commandKey, RestClient restClient, HttpRequest.Verb verb, String uri, Boolean retryable, MultiValueMap<String, String> headers, MultiValueMap<String, String> params, InputStream requestEntity) throws URISyntaxException { public MyCommand(int errorCode, String commandKey, RestClient restClient,
super(commandKey, restClient, verb, uri, retryable, headers, params, requestEntity); HttpRequest.Verb verb, String uri, Boolean retryable,
MultiValueMap<String, String> headers,
MultiValueMap<String, String> params, InputStream requestEntity)
throws URISyntaxException {
super(commandKey, restClient, verb, uri, retryable, headers, params,
requestEntity);
this.errorCode = errorCode; this.errorCode = errorCode;
} }
@Override @Override
protected ClientHttpResponse forward() throws Exception { protected ClientHttpResponse forward() throws Exception {
if (errorCode == 503) { if (this.errorCode == 503) {
throw new ClientException(ClientException.ErrorType.SERVER_THROTTLED); throw new ClientException(ClientException.ErrorType.SERVER_THROTTLED);
} }
return new MockClientHttpResponse((byte[])null, HttpStatus.valueOf(this.errorCode)); return new MockClientHttpResponse((byte[]) null,
HttpStatus.valueOf(this.errorCode));
} }
} }
......
...@@ -5,11 +5,6 @@ import java.util.HashMap; ...@@ -5,11 +5,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -33,12 +28,17 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -33,12 +28,17 @@ 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.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class ZuulProxyTestBase { public abstract class ZuulProxyTestBase {
@Value("${local.server.port}") @Value("${local.server.port}")
protected int port; protected int port;
...@@ -113,8 +113,8 @@ public class ZuulProxyTestBase { ...@@ -113,8 +113,8 @@ public class ZuulProxyTestBase {
@Test @Test
public void testNotFoundFromApp() { public void testNotFoundFromApp() {
ResponseEntity<String> result = new TestRestTemplate().exchange( ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/simple/local/notfound", HttpMethod.GET, "http://localhost:" + this.port + "/simple/local/notfound",
new HttpEntity<>((Void) null), String.class); HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode());
} }
...@@ -246,7 +246,8 @@ public class ZuulProxyTestBase { ...@@ -246,7 +246,8 @@ public class ZuulProxyTestBase {
.containsKey("override")) { .containsKey("override")) {
Map<String, List<String>> overridden = new HashMap<>(); Map<String, List<String>> overridden = new HashMap<>();
overridden.put("key", Arrays.asList("overridden")); overridden.put("key", Arrays.asList("overridden"));
RequestContext.getCurrentContext().setRequestQueryParams(overridden); RequestContext.getCurrentContext()
.setRequestQueryParams(overridden);
} }
return null; return null;
} }
......
...@@ -191,7 +191,8 @@ class SampleCustomZuulProxyApplication { ...@@ -191,7 +191,8 @@ class SampleCustomZuulProxyApplication {
protected static class CustomZuulProxyConfig extends ZuulProxyConfiguration { protected static class CustomZuulProxyConfig extends ZuulProxyConfiguration {
@Bean @Bean
@Override @Override
public SimpleHostRoutingFilter simpleHostRoutingFilter() { public SimpleHostRoutingFilter simpleHostRoutingFilter(
ProxyRequestHelper helper) {
return new CustomHostRoutingFilter(); return new CustomHostRoutingFilter();
} }
......
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters;
import java.util.Collections;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*/
public class ZuulPropertiesTests {
private ZuulProperties zuul = new ZuulProperties();
@Test
public void defaultIgnoredHeaders() {
assertTrue(this.zuul.getIgnoredHeaders().isEmpty());
}
@Test
public void addtIgnoredHeaders() {
this.zuul.setIgnoredHeaders(Collections.singleton("x-foo"));
assertTrue(this.zuul.getIgnoredHeaders().contains("x-foo"));
}
}
...@@ -229,7 +229,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -229,7 +229,7 @@ public class DiscoveryClientRouteLocatorTests {
public void testGetMatchingPathWithoutMatchingIgnoredPattern() throws Exception { public void testGetMatchingPathWithoutMatchingIgnoredPattern() throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("bar", new ZuulRoute("/bar/**")); this.properties.getRoutes().put("bar", new ZuulRoute("/bar/**"));
this.properties.init(); this.properties.init();
routeLocator.getRoutes(); // force refresh routeLocator.getRoutes(); // force refresh
...@@ -242,7 +242,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -242,7 +242,7 @@ public class DiscoveryClientRouteLocatorTests {
public void testGetMatchingPathWithMatchingIgnoredPattern() throws Exception { public void testGetMatchingPathWithMatchingIgnoredPattern() throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.init(); this.properties.init();
routeLocator.getRoutes(); // force refresh routeLocator.getRoutes(); // force refresh
...@@ -255,7 +255,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -255,7 +255,7 @@ public class DiscoveryClientRouteLocatorTests {
throws Exception { throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.setPrefix("/proxy"); this.properties.setPrefix("/proxy");
this.properties.init(); this.properties.init();
...@@ -270,7 +270,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -270,7 +270,7 @@ public class DiscoveryClientRouteLocatorTests {
throws Exception { throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/app", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/app",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.init(); this.properties.init();
routeLocator.getRoutes(); // force refresh routeLocator.getRoutes(); // force refresh
...@@ -283,7 +283,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -283,7 +283,7 @@ public class DiscoveryClientRouteLocatorTests {
throws Exception { throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false, null)); new ZuulRoute("foo", "/foo/**", "foo", null, false, null));
this.properties.setStripPrefix(false); this.properties.setStripPrefix(false);
...@@ -300,7 +300,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -300,7 +300,7 @@ public class DiscoveryClientRouteLocatorTests {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties this.properties
.setIgnoredPatterns(Collections.singletonList("/proxy" + IGNOREDPATTERN)); .setIgnoredPatterns(Collections.singleton("/proxy" + IGNOREDPATTERN));
this.properties.getRoutes().put("foo", this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false, null)); new ZuulRoute("foo", "/foo/**", "foo", null, false, null));
this.properties.setStripPrefix(false); this.properties.setStripPrefix(false);
...@@ -315,7 +315,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -315,7 +315,7 @@ public class DiscoveryClientRouteLocatorTests {
throws Exception { throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo"));
this.properties.setStripPrefix(false); this.properties.setStripPrefix(false);
this.properties.setPrefix("/proxy"); this.properties.setPrefix("/proxy");
...@@ -331,7 +331,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -331,7 +331,7 @@ public class DiscoveryClientRouteLocatorTests {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties this.properties
.setIgnoredPatterns(Collections.singletonList("/proxy" + IGNOREDPATTERN)); .setIgnoredPatterns(Collections.singleton("/proxy" + IGNOREDPATTERN));
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo"));
this.properties.setStripPrefix(false); this.properties.setStripPrefix(false);
this.properties.setPrefix("/proxy"); this.properties.setPrefix("/proxy");
...@@ -345,7 +345,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -345,7 +345,7 @@ public class DiscoveryClientRouteLocatorTests {
throws Exception { throws Exception {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false, null)); new ZuulRoute("foo", "/foo/**", "foo", null, false, null));
this.properties.setPrefix("/proxy"); this.properties.setPrefix("/proxy");
...@@ -361,7 +361,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -361,7 +361,7 @@ public class DiscoveryClientRouteLocatorTests {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties this.properties
.setIgnoredPatterns(Collections.singletonList("/proxy" + IGNOREDPATTERN)); .setIgnoredPatterns(Collections.singleton("/proxy" + IGNOREDPATTERN));
this.properties.getRoutes().put("foo", this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false, null)); new ZuulRoute("foo", "/foo/**", "foo", null, false, null));
this.properties.setPrefix("/proxy"); this.properties.setPrefix("/proxy");
...@@ -377,7 +377,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -377,7 +377,7 @@ public class DiscoveryClientRouteLocatorTests {
this.discovery, this.properties); this.discovery, this.properties);
ZuulRoute zuulRoute = new ZuulRoute("/foo/**"); ZuulRoute zuulRoute = new ZuulRoute("/foo/**");
zuulRoute.setStripPrefix(true); zuulRoute.setStripPrefix(true);
this.properties.setIgnoredPatterns(Collections.singletonList(IGNOREDPATTERN)); this.properties.setIgnoredPatterns(Collections.singleton(IGNOREDPATTERN));
this.properties.getRoutes().put("foo", zuulRoute); this.properties.getRoutes().put("foo", zuulRoute);
this.properties.init(); this.properties.init();
routeLocator.getRoutes(); // force refresh routeLocator.getRoutes(); // force refresh
...@@ -448,7 +448,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -448,7 +448,7 @@ public class DiscoveryClientRouteLocatorTests {
public void testIgnoreRoutes() { public void testIgnoreRoutes() {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList(IGNOREDSERVICE)); this.properties.setIgnoredServices(Collections.singleton(IGNOREDSERVICE));
given(this.discovery.getServices()) given(this.discovery.getServices())
.willReturn(Collections.singletonList(IGNOREDSERVICE)); .willReturn(Collections.singletonList(IGNOREDSERVICE));
List<Route> routesMap = routeLocator.getRoutes(); List<Route> routesMap = routeLocator.getRoutes();
...@@ -460,7 +460,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -460,7 +460,7 @@ public class DiscoveryClientRouteLocatorTests {
public void testIgnoreRoutesWithPattern() { public void testIgnoreRoutesWithPattern() {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("ignore*")); this.properties.setIgnoredServices(Collections.singleton("ignore*"));
given(this.discovery.getServices()) given(this.discovery.getServices())
.willReturn(Collections.singletonList(IGNOREDSERVICE)); .willReturn(Collections.singletonList(IGNOREDSERVICE));
List<Route> routesMap = routeLocator.getRoutes(); List<Route> routesMap = routeLocator.getRoutes();
...@@ -472,7 +472,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -472,7 +472,7 @@ public class DiscoveryClientRouteLocatorTests {
public void testIgnoreAllRoutes() { public void testIgnoreAllRoutes() {
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("*")); this.properties.setIgnoredServices(Collections.singleton("*"));
given(this.discovery.getServices()) given(this.discovery.getServices())
.willReturn(Collections.singletonList(IGNOREDSERVICE)); .willReturn(Collections.singletonList(IGNOREDSERVICE));
List<Route> routesMap = routeLocator.getRoutes(); List<Route> routesMap = routeLocator.getRoutes();
...@@ -485,7 +485,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -485,7 +485,7 @@ public class DiscoveryClientRouteLocatorTests {
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**")); this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("*")); this.properties.setIgnoredServices(Collections.singleton("*"));
given(this.discovery.getServices()).willReturn(Collections.singletonList("foo")); given(this.discovery.getServices()).willReturn(Collections.singletonList("foo"));
List<Route> routesMap = routeLocator.getRoutes(); List<Route> routesMap = routeLocator.getRoutes();
assertNotNull("routes ignored foo", getRoute(routesMap, "/foo/**")); assertNotNull("routes ignored foo", getRoute(routesMap, "/foo/**"));
...@@ -499,7 +499,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -499,7 +499,7 @@ public class DiscoveryClientRouteLocatorTests {
this.properties.getRoutes().put("foo", route); this.properties.getRoutes().put("foo", route);
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("*")); this.properties.setIgnoredServices(Collections.singleton("*"));
given(this.discovery.getServices()).willReturn(Collections.singletonList("foo")); given(this.discovery.getServices()).willReturn(Collections.singletonList("foo"));
LinkedHashMap<String, ZuulRoute> routes = routeLocator.locateRoutes(); LinkedHashMap<String, ZuulRoute> routes = routeLocator.locateRoutes();
ZuulRoute actual = routes.get("/foo/**"); ZuulRoute actual = routes.get("/foo/**");
...@@ -517,7 +517,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -517,7 +517,7 @@ public class DiscoveryClientRouteLocatorTests {
this.properties.getRoutes().put("foo", route); this.properties.getRoutes().put("foo", route);
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("*")); this.properties.setIgnoredServices(Collections.singleton("*"));
given(this.discovery.getServices()).willReturn(Collections.singletonList("foo")); given(this.discovery.getServices()).willReturn(Collections.singletonList("foo"));
LinkedHashMap<String, ZuulRoute> routes = routeLocator.locateRoutes(); LinkedHashMap<String, ZuulRoute> routes = routeLocator.locateRoutes();
ZuulRoute actual = routes.get("/**"); ZuulRoute actual = routes.get("/**");
...@@ -533,7 +533,7 @@ public class DiscoveryClientRouteLocatorTests { ...@@ -533,7 +533,7 @@ public class DiscoveryClientRouteLocatorTests {
new ZuulRoute("/foo/**", "http://foo.com")); new ZuulRoute("/foo/**", "http://foo.com"));
DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/", DiscoveryClientRouteLocator routeLocator = new DiscoveryClientRouteLocator("/",
this.discovery, this.properties); this.discovery, this.properties);
this.properties.setIgnoredServices(Collections.singletonList("*")); this.properties.setIgnoredServices(Collections.singleton("*"));
given(this.discovery.getServices()).willReturn(Collections.singletonList("bar")); given(this.discovery.getServices()).willReturn(Collections.singletonList("bar"));
List<Route> routesMap = routeLocator.getRoutes(); List<Route> routesMap = routeLocator.getRoutes();
assertNotNull("routes ignored foo", getRoute(routesMap, getMapping("foo"))); assertNotNull("routes ignored foo", getRoute(routesMap, getMapping("foo")));
......
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