Put Apache Http Client and OkHttpClient in ribbon context.

This eliminates them being created for every zuul request. Also makes properties consistent accross modules: ribbon.httpclient.*, ribbon.restclient.* and ribbon.okhttp.* fixes gh-1150
parent b91fa734
...@@ -1357,6 +1357,12 @@ file as the ordering will be lost using a properties file. For example: ...@@ -1357,6 +1357,12 @@ file as the ordering will be lost using a properties file. For example:
If you were to use a properties file, the `legacy` path may end up in front of the `users` If you were to use a properties file, the `legacy` path may end up in front of the `users`
path rendering the `users` path unreachable. path rendering the `users` path unreachable.
=== Zuul Http Client
The default HTTP client used by zuul is now backed by the Apache HTTP Client instead of the
deprecated Ribbon `RestClient. To use `RestClient` or to use the `okhttp3.OkHttpClient` set
`ribbon.restclient.enabled=true` or `ribbon.okhttp.enabled=true` respectively.
=== Cookies and Sensitive Headers === Cookies and Sensitive Headers
It's OK to share headers between services in the same system, but you It's OK to share headers between services in the same system, but you
......
...@@ -16,12 +16,18 @@ ...@@ -16,12 +16,18 @@
package org.springframework.cloud.netflix.ribbon; package org.springframework.cloud.netflix.ribbon;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
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.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
...@@ -30,6 +36,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfigurati ...@@ -30,6 +36,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfigurati
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
...@@ -79,7 +86,7 @@ public class RibbonAutoConfiguration { ...@@ -79,7 +86,7 @@ public class RibbonAutoConfiguration {
@Configuration @Configuration
@ConditionalOnClass(HttpRequest.class) @ConditionalOnClass(HttpRequest.class)
@ConditionalOnProperty(value = "ribbon.http.client.enabled", matchIfMissing = false) @ConditionalOnRibbonRestClient
protected static class RibbonClientConfig { protected static class RibbonClientConfig {
@Autowired @Autowired
...@@ -102,4 +109,24 @@ public class RibbonAutoConfiguration { ...@@ -102,4 +109,24 @@ public class RibbonAutoConfiguration {
} }
} }
//TODO: support for autoconfiguring restemplate to use apache http client or okhttp
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonRestClientCondition.class)
@interface ConditionalOnRibbonRestClient { }
private static class OnRibbonRestClientCondition extends AnyNestedCondition {
public OnRibbonRestClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Deprecated //remove in Edgware"
@ConditionalOnProperty("ribbon.http.client.enabled")
static class ZuulProperty {}
@ConditionalOnProperty("ribbon.restclient.enabled")
static class RibbonProperty {}
}
} }
...@@ -24,13 +24,17 @@ import org.apache.http.client.params.ClientPNames; ...@@ -24,13 +24,17 @@ import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy; import org.apache.http.client.params.CookiePolicy;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
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.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient;
import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient;
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.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.web.util.UriComponentsBuilder;
import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.DefaultLoadBalancerRetryHandler; import com.netflix.client.DefaultLoadBalancerRetryHandler;
import com.netflix.client.RetryHandler; import com.netflix.client.RetryHandler;
import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.DefaultClientConfigImpl;
...@@ -112,6 +116,53 @@ public class RibbonClientConfiguration { ...@@ -112,6 +116,53 @@ public class RibbonClientConfiguration {
return serverList; return serverList;
} }
@Configuration
@ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)
protected static class HttpClientRibbonConfiguration {
@Value("${ribbon.client.name}")
private String name = "client";
@Bean
@ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)
public RibbonLoadBalancingHttpClient ribbonLoadBalancingHttpClient(
IClientConfig config, ServerIntrospector serverIntrospector,
ILoadBalancer loadBalancer, RetryHandler retryHandler) {
RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(
config, serverIntrospector);
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
}
@Configuration
@ConditionalOnProperty("ribbon.okhttp.enabled")
@ConditionalOnClass(name = "okhttp3.OkHttpClient")
protected static class OkHttpRibbonConfiguration {
@Value("${ribbon.client.name}")
private String name = "client";
@Bean
@ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)
public OkHttpLoadBalancingClient okHttpLoadBalancingClient(IClientConfig config,
ServerIntrospector serverIntrospector, ILoadBalancer loadBalancer,
RetryHandler retryHandler) {
OkHttpLoadBalancingClient client = new OkHttpLoadBalancingClient(config,
serverIntrospector);
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
}
@Configuration
@RibbonAutoConfiguration.ConditionalOnRibbonRestClient
protected static class RestClientRibbonConfiguration {
@Value("${ribbon.client.name}")
private String name = "client";
/** /**
* Create a Netflix {@link RestClient} integrated with Ribbon if none already exists * Create a Netflix {@link RestClient} integrated with Ribbon if none already exists
* in the application context. It is not required for Ribbon to work properly and is * in the application context. It is not required for Ribbon to work properly and is
...@@ -125,7 +176,7 @@ public class RibbonClientConfiguration { ...@@ -125,7 +176,7 @@ public class RibbonClientConfiguration {
*/ */
@Bean @Bean
@Lazy @Lazy
@ConditionalOnMissingBean @ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer, public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer,
ServerIntrospector serverIntrospector, RetryHandler retryHandler) { ServerIntrospector serverIntrospector, RetryHandler retryHandler) {
RestClient client = new OverrideRestClient(config, serverIntrospector); RestClient client = new OverrideRestClient(config, serverIntrospector);
...@@ -134,6 +185,7 @@ public class RibbonClientConfiguration { ...@@ -134,6 +185,7 @@ public class RibbonClientConfiguration {
Monitors.registerObject("Client_" + this.name, client); Monitors.registerObject("Client_" + this.name, client);
return client; return client;
} }
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
......
...@@ -16,33 +16,55 @@ ...@@ -16,33 +16,55 @@
package org.springframework.cloud.netflix.ribbon.apache; package org.springframework.cloud.netflix.ribbon.apache;
import com.netflix.client.config.CommonClientConfigKey; import java.net.URI;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient; import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded;
/** /**
* @author Christian Lohmann * @author Christian Lohmann
*/ */
//TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClient
public class RibbonLoadBalancingHttpClient public class RibbonLoadBalancingHttpClient
extends extends
AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse> { AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse> {
private final HttpClient delegate = HttpClientBuilder.create().disableCookieManagement().build(); private final HttpClient delegate = HttpClientBuilder.create().disableCookieManagement().build();
private final IClientConfig config;
private final ServerIntrospector serverIntrospector;
@Deprecated
public RibbonLoadBalancingHttpClient() { public RibbonLoadBalancingHttpClient() {
super(); super();
this.config = new DefaultClientConfigImpl();
this.serverIntrospector = new DefaultServerIntrospector();
} }
@Deprecated
public RibbonLoadBalancingHttpClient(final ILoadBalancer lb) { public RibbonLoadBalancingHttpClient(final ILoadBalancer lb) {
super(lb); super(lb);
this.config = new DefaultClientConfigImpl();
this.serverIntrospector = new DefaultServerIntrospector();
}
public RibbonLoadBalancingHttpClient(IClientConfig config, ServerIntrospector serverIntrospector) {
this.config = config;
this.serverIntrospector = serverIntrospector;
initWithNiwsConfig(config);
} }
@Override @Override
...@@ -76,4 +98,10 @@ public class RibbonLoadBalancingHttpClient ...@@ -76,4 +98,10 @@ public class RibbonLoadBalancingHttpClient
return new RibbonApacheHttpResponse(httpResponse, httpUriRequest.getURI()); return new RibbonApacheHttpResponse(httpResponse, httpUriRequest.getURI());
} }
@Override
public URI reconstructURIWithServer(Server server, URI original) {
URI uri = updateToHttpsIfNeeded(original, this.config, this.serverIntrospector, server);
return super.reconstructURIWithServer(server, uri);
}
} }
...@@ -19,15 +19,22 @@ package org.springframework.cloud.netflix.ribbon.okhttp; ...@@ -19,15 +19,22 @@ package org.springframework.cloud.netflix.ribbon.okhttp;
import java.net.URI; import java.net.URI;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient; import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import okhttp3.Request; import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import okhttp3.Response;
import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient; import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
...@@ -35,13 +42,28 @@ import com.netflix.loadbalancer.ILoadBalancer; ...@@ -35,13 +42,28 @@ import com.netflix.loadbalancer.ILoadBalancer;
public class OkHttpLoadBalancingClient public class OkHttpLoadBalancingClient
extends AbstractLoadBalancingClient<OkHttpRibbonRequest, OkHttpRibbonResponse> { extends AbstractLoadBalancingClient<OkHttpRibbonRequest, OkHttpRibbonResponse> {
private final OkHttpClient delegate = new OkHttpClient(); private final OkHttpClient delegate = new OkHttpClient();
private final IClientConfig config;
private final ServerIntrospector serverIntrospector;
@Deprecated
public OkHttpLoadBalancingClient() { public OkHttpLoadBalancingClient() {
super(); super();
config = new DefaultClientConfigImpl();
serverIntrospector = new DefaultServerIntrospector();
} }
@Deprecated
public OkHttpLoadBalancingClient(final ILoadBalancer lb) { public OkHttpLoadBalancingClient(final ILoadBalancer lb) {
super(lb); super(lb);
config = new DefaultClientConfigImpl();
serverIntrospector = new DefaultServerIntrospector();
}
public OkHttpLoadBalancingClient(IClientConfig config,
ServerIntrospector serverIntrospector) {
this.config = config;
this.serverIntrospector = serverIntrospector;
initWithNiwsConfig(config);
} }
@Override @Override
...@@ -87,4 +109,11 @@ public class OkHttpLoadBalancingClient ...@@ -87,4 +109,11 @@ public class OkHttpLoadBalancingClient
return builder.build(); return builder.build();
} }
@Override
public URI reconstructURIWithServer(Server server, URI original) {
URI uri = updateToHttpsIfNeeded(original, this.config, this.serverIntrospector,
server);
return super.reconstructURIWithServer(server, uri);
}
} }
...@@ -16,12 +16,18 @@ ...@@ -16,12 +16,18 @@
package org.springframework.cloud.netflix.zuul; package org.springframework.cloud.netflix.zuul;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
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.Endpoint;
import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
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.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
...@@ -52,6 +58,7 @@ import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; ...@@ -52,6 +58,7 @@ import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
...@@ -84,7 +91,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -84,7 +91,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
} }
@Configuration @Configuration
@ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true) @ConditionalOnRibbonHttpClient
protected static class HttpClientRibbonConfiguration { protected static class HttpClientRibbonConfiguration {
@Bean @Bean
...@@ -96,7 +103,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -96,7 +103,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
} }
@Configuration @Configuration
@ConditionalOnProperty("zuul.ribbon.restclient.enabled") @ConditionalOnRibbonRestClient
protected static class RestClientRibbonConfiguration { protected static class RestClientRibbonConfiguration {
@Bean @Bean
...@@ -108,7 +115,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -108,7 +115,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
} }
@Configuration @Configuration
@ConditionalOnProperty("zuul.ribbon.okhttp.enabled") @ConditionalOnRibbonOkHttpClient
@ConditionalOnClass(name = "okhttp3.OkHttpClient") @ConditionalOnClass(name = "okhttp3.OkHttpClient")
protected static class OkHttpRibbonConfiguration { protected static class OkHttpRibbonConfiguration {
...@@ -120,6 +127,63 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -120,6 +127,63 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
} }
} }
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonHttpClientCondition.class)
@interface ConditionalOnRibbonHttpClient { }
private static class OnRibbonHttpClientCondition extends AnyNestedCondition {
public OnRibbonHttpClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Deprecated //remove in Edgware"
@ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true)
static class ZuulProperty {}
@ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)
static class RibbonProperty {}
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonOkHttpClientCondition.class)
@interface ConditionalOnRibbonOkHttpClient { }
private static class OnRibbonOkHttpClientCondition extends AnyNestedCondition {
public OnRibbonOkHttpClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Deprecated //remove in Edgware"
@ConditionalOnProperty("zuul.ribbon.okhttp.enabled")
static class ZuulProperty {}
@ConditionalOnProperty("ribbon.okhttp.enabled")
static class RibbonProperty {}
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonRestClientCondition.class)
@interface ConditionalOnRibbonRestClient { }
private static class OnRibbonRestClientCondition extends AnyNestedCondition {
public OnRibbonRestClientCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Deprecated //remove in Edgware"
@ConditionalOnProperty("zuul.ribbon.restclient.enabled")
static class ZuulProperty {}
@ConditionalOnProperty("ribbon.restclient.enabled")
static class RibbonProperty {}
}
// pre filters // pre filters
@Bean @Bean
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator,
......
...@@ -17,17 +17,27 @@ ...@@ -17,17 +17,27 @@
package org.springframework.cloud.netflix.ribbon; package org.springframework.cloud.netflix.ribbon;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.niws.client.http.RestClient;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration.OverrideRestClient; import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration.OverrideRestClient;
import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient;
import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
...@@ -82,11 +92,11 @@ public class RibbonClientConfigurationTests { ...@@ -82,11 +92,11 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777); Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(true); when(this.inspector.isSecure(server)).thenReturn(true);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config, for (AbstractLoadBalancerAwareClient client : clients()) {
this.inspector); URI uri = client.reconstructURIWithServer(server,
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/")); new URI("http://foo/"));
assertThat(uri, is(new URI("https://foo:7777/"))); assertThat(getReason(client), uri, is(new URI("https://foo:7777/")));
}
} }
@Test @Test
...@@ -94,11 +104,15 @@ public class RibbonClientConfigurationTests { ...@@ -94,11 +104,15 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777); Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(false); when(this.inspector.isSecure(server)).thenReturn(false);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config, for (AbstractLoadBalancerAwareClient client : clients()) {
this.inspector); URI uri = client.reconstructURIWithServer(server,
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/")); new URI("http://foo/"));
assertThat(uri, is(new URI("http://foo:7777/"))); assertThat(getReason(client), uri, is(new URI("http://foo:7777/")));
}
}
String getReason(AbstractLoadBalancerAwareClient client) {
return client.getClass().getSimpleName()+" failed";
} }
@Test @Test
...@@ -106,11 +120,57 @@ public class RibbonClientConfigurationTests { ...@@ -106,11 +120,57 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777); Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(true); when(this.inspector.isSecure(server)).thenReturn(true);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config, for (AbstractLoadBalancerAwareClient client : clients()) {
this.inspector); URI uri = client.reconstructURIWithServer(server,
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/%20bar")); new URI("http://foo/%20bar"));
assertThat(uri, is(new URI("https://foo:7777/%20bar"))); assertThat(getReason(client), uri, is(new URI("https://foo:7777/%20bar")));
}
}
private List<AbstractLoadBalancerAwareClient> clients() {
ArrayList<AbstractLoadBalancerAwareClient> clients = new ArrayList<>();
clients.add(new OverrideRestClient(this.config, this.inspector));
clients.add(new RibbonLoadBalancingHttpClient(this.config, this.inspector));
clients.add(new OkHttpLoadBalancingClient(this.config, this.inspector));
return clients;
}
@Test
public void testDefaultsToApacheHttpClient() {
testClient(RibbonLoadBalancingHttpClient.class, null, RestClient.class, OkHttpLoadBalancingClient.class);
testClient(RibbonLoadBalancingHttpClient.class, "ribbon.httpclient.enabled", RestClient.class, OkHttpLoadBalancingClient.class);
}
@Test
public void testEnableRestClient() {
testClient(RestClient.class, "ribbon.restclient.enabled", RibbonLoadBalancingHttpClient.class,
OkHttpLoadBalancingClient.class);
}
@Test
public void testEnableOkHttpClient() {
testClient(OkHttpLoadBalancingClient.class, "ribbon.okhttp.enabled", RibbonLoadBalancingHttpClient.class,
RestClient.class);
}
void testClient(Class<?> clientType, String property, Class<?>... excludedTypes) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(RibbonAutoConfiguration.class,
RibbonClientConfiguration.class);
if (property != null) {
EnvironmentTestUtils.addEnvironment(context, property);
}
context.refresh();
context.getBean(clientType);
for (Class<?> excludedType : excludedTypes) {
assertThat("has "+excludedType.getSimpleName()+ " instance", hasInstance(context, excludedType), is(false));
}
context.close();
}
private <T> boolean hasInstance(ListableBeanFactory lbf, Class<T> requiredType) {
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(lbf,
requiredType).length > 0;
} }
static class TestRestClient extends OverrideRestClient { static class TestRestClient extends OverrideRestClient {
......
...@@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.ribbon; ...@@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.ribbon;
import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy; import org.apache.http.client.params.CookiePolicy;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration; import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
...@@ -28,6 +27,7 @@ import com.netflix.niws.client.http.RestClient; ...@@ -28,6 +27,7 @@ import com.netflix.niws.client.http.RestClient;
import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment;
/** /**
* @author Dave Syer * @author Dave Syer
...@@ -41,7 +41,7 @@ public class SpringClientFactoryTests { ...@@ -41,7 +41,7 @@ public class SpringClientFactoryTests {
SpringClientFactory factory = new SpringClientFactory(); SpringClientFactory factory = new SpringClientFactory();
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class); RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2"); addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
factory.setApplicationContext(parent); factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory
.getLoadBalancerContext("foo").getRetryHandler(); .getLoadBalancerContext("foo").getRetryHandler();
...@@ -54,8 +54,10 @@ public class SpringClientFactoryTests { ...@@ -54,8 +54,10 @@ public class SpringClientFactoryTests {
@Test @Test
public void testCookiePolicy() { public void testCookiePolicy() {
SpringClientFactory factory = new SpringClientFactory(); SpringClientFactory factory = new SpringClientFactory();
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class); addEnvironment(parent, "ribbon.restclient.enabled=true");
parent.register(RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
parent.refresh();
factory.setApplicationContext(parent); factory.setApplicationContext(parent);
RestClient client = factory.getClient("foo", RestClient.class); RestClient client = factory.getClient("foo", RestClient.class);
ApacheHttpClient4 jerseyClient = (ApacheHttpClient4) client.getJerseyClient(); ApacheHttpClient4 jerseyClient = (ApacheHttpClient4) client.getJerseyClient();
......
/*
* Copyright 2013-2016 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;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
/**
* @author Spencer Gibb
*/
public class ZuulProxyConfigurationTests {
@Test
public void testDefaultsToApacheHttpClient() {
testClient(HttpClientRibbonCommandFactory.class, null);
testClient(HttpClientRibbonCommandFactory.class, "zuul.ribbon.httpclient.enabled=true");
testClient(HttpClientRibbonCommandFactory.class, "ribbon.httpclient.enabled=true");
}
@Test
public void testEnableRestClient() {
testClient(RestClientRibbonCommandFactory.class, "zuul.ribbon.restclient.enabled=true");
testClient(RestClientRibbonCommandFactory.class, "ribbon.restclient.enabled=true");
}
@Test
public void testEnableOkHttpClient() {
testClient(OkHttpRibbonCommandFactory.class, "zuul.ribbon.okhttp.enabled=true");
testClient(OkHttpRibbonCommandFactory.class, "ribbon.okhttp.enabled=true");
}
void testClient(Class<?> clientType, String property) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TestConfig.class, ZuulProxyConfiguration.class);
if (property != null) {
EnvironmentTestUtils.addEnvironment(context, property);
}
context.refresh();
RibbonCommandFactory factory = context.getBean(RibbonCommandFactory.class);
assertThat("RibbonCommandFactory is wrong type for property: "+property, factory, is(instanceOf(clientType)));
context.close();
}
static class TestConfig {
@Bean
ServerProperties serverProperties() {
return new ServerProperties();
}
@Bean
SpringClientFactory springClientFactory() {
return mock(SpringClientFactory.class);
}
@Bean
DiscoveryClient discoveryClient() {
return mock(DiscoveryClient.class);
}
}
}
...@@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.web.ErrorAttributes; ...@@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
...@@ -200,10 +201,10 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { ...@@ -200,10 +201,10 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase {
@Bean @Bean
public RibbonLoadBalancingHttpClient ribbonClient(IClientConfig config, public RibbonLoadBalancingHttpClient ribbonClient(IClientConfig config,
ILoadBalancer loadBalancer, RetryHandler retryHandler) { ILoadBalancer loadBalancer, RetryHandler retryHandler) {
final RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(); final RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(config,
new DefaultServerIntrospector());
client.setLoadBalancer(loadBalancer); client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler); client.setRetryHandler(retryHandler);
client.initWithNiwsConfig(config);
return client; return client;
} }
......
...@@ -88,7 +88,7 @@ import lombok.SneakyThrows; ...@@ -88,7 +88,7 @@ import lombok.SneakyThrows;
"zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**",
"zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header", "zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header",
"zuul.routes.rnd: /rnd/**", "rnd.ribbon.listOfServers: ${random.value}", "zuul.routes.rnd: /rnd/**", "rnd.ribbon.listOfServers: ${random.value}",
"zuul.removeSemicolonContent: false" }) "zuul.removeSemicolonContent: false", "ribbon.restclient.enabled=true"})
@DirtiesContext @DirtiesContext
public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase {
......
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