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:
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.
=== 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
It's OK to share headers between services in the same system, but you
......
......@@ -16,12 +16,18 @@
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.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
......@@ -30,6 +36,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfigurati
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
......@@ -79,7 +86,7 @@ public class RibbonAutoConfiguration {
@Configuration
@ConditionalOnClass(HttpRequest.class)
@ConditionalOnProperty(value = "ribbon.http.client.enabled", matchIfMissing = false)
@ConditionalOnRibbonRestClient
protected static class RibbonClientConfig {
@Autowired
......@@ -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;
import org.apache.http.client.params.CookiePolicy;
import org.springframework.beans.factory.annotation.Autowired;
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.ConditionalOnProperty;
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.Configuration;
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.RetryHandler;
import com.netflix.client.config.DefaultClientConfigImpl;
......@@ -112,27 +116,75 @@ public class RibbonClientConfiguration {
return serverList;
}
/**
* 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
* therefore created lazily if ever another component requires it.
*
* @param config the configuration to use by the underlying Ribbon instance
* @param loadBalancer the load balancer to use by the underlying Ribbon instance
* @param serverIntrospector server introspector to use by the underlying Ribbon instance
* @param retryHandler retry handler to use by the underlying Ribbon instance
* @return a {@link RestClient} instances backed by Ribbon
*/
@Bean
@Lazy
@ConditionalOnMissingBean
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer,
ServerIntrospector serverIntrospector, RetryHandler retryHandler) {
RestClient client = new OverrideRestClient(config, serverIntrospector);
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + this.name, client);
return client;
@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
* in the application context. It is not required for Ribbon to work properly and is
* therefore created lazily if ever another component requires it.
*
* @param config the configuration to use by the underlying Ribbon instance
* @param loadBalancer the load balancer to use by the underlying Ribbon instance
* @param serverIntrospector server introspector to use by the underlying Ribbon instance
* @param retryHandler retry handler to use by the underlying Ribbon instance
* @return a {@link RestClient} instances backed by Ribbon
*/
@Bean
@Lazy
@ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer,
ServerIntrospector serverIntrospector, RetryHandler retryHandler) {
RestClient client = new OverrideRestClient(config, serverIntrospector);
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
}
@Bean
......
......@@ -16,33 +16,55 @@
package org.springframework.cloud.netflix.ribbon.apache;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
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.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
*/
//TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClient
public class RibbonLoadBalancingHttpClient
extends
AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse> {
private final HttpClient delegate = HttpClientBuilder.create().disableCookieManagement().build();
private final IClientConfig config;
private final ServerIntrospector serverIntrospector;
@Deprecated
public RibbonLoadBalancingHttpClient() {
super();
this.config = new DefaultClientConfigImpl();
this.serverIntrospector = new DefaultServerIntrospector();
}
@Deprecated
public RibbonLoadBalancingHttpClient(final ILoadBalancer 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
......@@ -76,4 +98,10 @@ public class RibbonLoadBalancingHttpClient
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;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
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.web.util.UriComponentsBuilder;
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 okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded;
/**
* @author Spencer Gibb
......@@ -35,13 +42,28 @@ import com.netflix.loadbalancer.ILoadBalancer;
public class OkHttpLoadBalancingClient
extends AbstractLoadBalancingClient<OkHttpRibbonRequest, OkHttpRibbonResponse> {
private final OkHttpClient delegate = new OkHttpClient();
private final IClientConfig config;
private final ServerIntrospector serverIntrospector;
@Deprecated
public OkHttpLoadBalancingClient() {
super();
config = new DefaultClientConfigImpl();
serverIntrospector = new DefaultServerIntrospector();
}
@Deprecated
public OkHttpLoadBalancingClient(final ILoadBalancer lb) {
super(lb);
config = new DefaultClientConfigImpl();
serverIntrospector = new DefaultServerIntrospector();
}
public OkHttpLoadBalancingClient(IClientConfig config,
ServerIntrospector serverIntrospector) {
this.config = config;
this.serverIntrospector = serverIntrospector;
initWithNiwsConfig(config);
}
@Override
......@@ -87,4 +109,11 @@ public class OkHttpLoadBalancingClient
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 @@
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.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
......@@ -52,6 +58,7 @@ import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
......@@ -84,7 +91,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
@Configuration
@ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true)
@ConditionalOnRibbonHttpClient
protected static class HttpClientRibbonConfiguration {
@Bean
......@@ -96,7 +103,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
@Configuration
@ConditionalOnProperty("zuul.ribbon.restclient.enabled")
@ConditionalOnRibbonRestClient
protected static class RestClientRibbonConfiguration {
@Bean
......@@ -108,7 +115,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
@Configuration
@ConditionalOnProperty("zuul.ribbon.okhttp.enabled")
@ConditionalOnRibbonOkHttpClient
@ConditionalOnClass(name = "okhttp3.OkHttpClient")
protected static class OkHttpRibbonConfiguration {
......@@ -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
@Bean
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator,
......
......@@ -17,17 +17,27 @@
package org.springframework.cloud.netflix.ribbon;
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.Test;
import org.mockito.Mock;
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 com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
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.junit.Assert.assertThat;
......@@ -82,11 +92,11 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(true);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config,
this.inspector);
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(uri, is(new URI("https://foo:7777/")));
for (AbstractLoadBalancerAwareClient client : clients()) {
URI uri = client.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(getReason(client), uri, is(new URI("https://foo:7777/")));
}
}
@Test
......@@ -94,11 +104,15 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(false);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config,
this.inspector);
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(uri, is(new URI("http://foo:7777/")));
for (AbstractLoadBalancerAwareClient client : clients()) {
URI uri = client.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(getReason(client), uri, is(new URI("http://foo:7777/")));
}
}
String getReason(AbstractLoadBalancerAwareClient client) {
return client.getClass().getSimpleName()+" failed";
}
@Test
......@@ -106,11 +120,57 @@ public class RibbonClientConfigurationTests {
Server server = new Server("foo", 7777);
when(this.inspector.isSecure(server)).thenReturn(true);
OverrideRestClient overrideRestClient = new OverrideRestClient(this.config,
this.inspector);
URI uri = overrideRestClient.reconstructURIWithServer(server,
new URI("http://foo/%20bar"));
assertThat(uri, is(new URI("https://foo:7777/%20bar")));
for (AbstractLoadBalancerAwareClient client : clients()) {
URI uri = client.reconstructURIWithServer(server,
new URI("http://foo/%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 {
......
......@@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.ribbon;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.junit.Test;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
......@@ -28,6 +27,7 @@ import com.netflix.niws.client.http.RestClient;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import static org.junit.Assert.assertEquals;
import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment;
/**
* @author Dave Syer
......@@ -41,7 +41,7 @@ public class SpringClientFactoryTests {
SpringClientFactory factory = new SpringClientFactory();
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory
.getLoadBalancerContext("foo").getRetryHandler();
......@@ -54,8 +54,10 @@ public class SpringClientFactoryTests {
@Test
public void testCookiePolicy() {
SpringClientFactory factory = new SpringClientFactory();
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
addEnvironment(parent, "ribbon.restclient.enabled=true");
parent.register(RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
parent.refresh();
factory.setApplicationContext(parent);
RestClient client = factory.getClient("foo", RestClient.class);
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;
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.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
......@@ -200,10 +201,10 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase {
@Bean
public RibbonLoadBalancingHttpClient ribbonClient(IClientConfig config,
ILoadBalancer loadBalancer, RetryHandler retryHandler) {
final RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient();
final RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(config,
new DefaultServerIntrospector());
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
client.initWithNiwsConfig(config);
return client;
}
......
......@@ -88,7 +88,7 @@ import lombok.SneakyThrows;
"zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**",
"zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header",
"zuul.routes.rnd: /rnd/**", "rnd.ribbon.listOfServers: ${random.value}",
"zuul.removeSemicolonContent: false" })
"zuul.removeSemicolonContent: false", "ribbon.restclient.enabled=true"})
@DirtiesContext
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