Centralizing HTTP client creation and configuration
This commit is contained in:
@@ -18,14 +18,24 @@ package org.springframework.cloud.netflix.feign;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.netflix.feign.support.FeignHttpClientProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -34,12 +44,17 @@ import feign.Feign;
|
||||
import feign.httpclient.ApacheHttpClient;
|
||||
import feign.okhttp.OkHttpClient;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import com.netflix.client.config.CommonClientConfigKey;
|
||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Julien Roy
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@EnableConfigurationProperties({FeignHttpClientProperties.class})
|
||||
public class FeignAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
@@ -86,17 +101,51 @@ public class FeignAutoConfiguration {
|
||||
@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
|
||||
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
||||
protected static class HttpClientFeignConfiguration {
|
||||
private final Timer connectionManagerTimer = new Timer(
|
||||
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
||||
|
||||
@Autowired(required = false)
|
||||
private HttpClient httpClient;
|
||||
private RegistryBuilder registryBuilder;
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@Bean
|
||||
public HttpClientConnectionManager connectionManager(ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
final HttpClientConnectionManager connectionManager = connectionManagerFactory.newConnectionManager(false, httpClientProperties.getMaxConnections(),
|
||||
httpClientProperties.getMaxConnectionsPerRoute(), httpClientProperties.getTimeToLive(),
|
||||
httpClientProperties.getTimeToLiveUnit(),
|
||||
registryBuilder);
|
||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
connectionManager.closeExpiredConnections();
|
||||
}
|
||||
}, 30000, httpClientProperties.getConnectionTimerRepeat());
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory, HttpClientConnectionManager httpClientConnectionManager,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
RequestConfig defaultRequestConfig = RequestConfig.custom().
|
||||
setConnectTimeout(httpClientProperties.getConnectionTimeout()).
|
||||
setRedirectsEnabled(httpClientProperties.isFollowRedirects()).
|
||||
build();
|
||||
this.httpClient = httpClientFactory.createClient(defaultRequestConfig, httpClientConnectionManager);
|
||||
return this.httpClient;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Client.class)
|
||||
public Client feignClient() {
|
||||
if (this.httpClient != null) {
|
||||
return new ApacheHttpClient(this.httpClient);
|
||||
}
|
||||
return new ApacheHttpClient();
|
||||
public Client feignClient(HttpClient httpClient) {
|
||||
return new ApacheHttpClient(httpClient);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() throws Exception {
|
||||
connectionManagerTimer.cancel();
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,22 @@
|
||||
package org.springframework.cloud.netflix.feign.ribbon;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.support.FeignHttpClientProperties;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -38,6 +46,10 @@ import feign.Request;
|
||||
import feign.httpclient.ApacheHttpClient;
|
||||
import feign.okhttp.OkHttpClient;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
* Autoconfiguration to be activated if Feign is in use and needs to be use Ribbon as a
|
||||
* load balancer.
|
||||
@@ -47,6 +59,7 @@ import feign.okhttp.OkHttpClient;
|
||||
@ConditionalOnClass({ ILoadBalancer.class, Feign.class })
|
||||
@Configuration
|
||||
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
||||
@EnableConfigurationProperties({FeignHttpClientProperties.class})
|
||||
public class FeignRibbonClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -84,22 +97,54 @@ public class FeignRibbonClientAutoConfiguration {
|
||||
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
||||
protected static class HttpClientFeignLoadBalancedConfiguration {
|
||||
|
||||
private final Timer connectionManagerTimer = new Timer(
|
||||
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@Autowired(required = false)
|
||||
private HttpClient httpClient;
|
||||
private RegistryBuilder registryBuilder;
|
||||
|
||||
@Bean
|
||||
public HttpClientConnectionManager connectionManager(ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
final HttpClientConnectionManager connectionManager = connectionManagerFactory.newConnectionManager(false, httpClientProperties.getMaxConnections(),
|
||||
httpClientProperties.getMaxConnectionsPerRoute(), httpClientProperties.getTimeToLive(),
|
||||
httpClientProperties.getTimeToLiveUnit(),
|
||||
registryBuilder);
|
||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
connectionManager.closeExpiredConnections();
|
||||
}
|
||||
}, 30000, httpClientProperties.getConnectionTimerRepeat());
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory, HttpClientConnectionManager httpClientConnectionManager,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
RequestConfig defaultRequestConfig = RequestConfig.custom().
|
||||
setConnectTimeout(httpClientProperties.getConnectionTimeout()).
|
||||
setRedirectsEnabled(httpClientProperties.isFollowRedirects()).
|
||||
build();
|
||||
this.httpClient = httpClientFactory.createClient(defaultRequestConfig, httpClientConnectionManager);
|
||||
return this.httpClient;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Client.class)
|
||||
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
||||
SpringClientFactory clientFactory) {
|
||||
ApacheHttpClient delegate;
|
||||
if (this.httpClient != null) {
|
||||
delegate = new ApacheHttpClient(this.httpClient);
|
||||
}
|
||||
else {
|
||||
delegate = new ApacheHttpClient();
|
||||
}
|
||||
SpringClientFactory clientFactory, HttpClient httpClient) {
|
||||
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
|
||||
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() throws Exception {
|
||||
connectionManagerTimer.cancel();
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
*
|
||||
* * 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.feign.support;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "feign.httpclient")
|
||||
public class FeignHttpClientProperties {
|
||||
public static final boolean DEFAULT_DISABLE_SSL_VALIDATION = false;
|
||||
public static final int DEFAULT_MAX_CONNECTIONS = 200;
|
||||
public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 50;
|
||||
public static final long DEFAULT_TIME_TO_LIVE = 900L;
|
||||
public static final TimeUnit DEFAULT_TIME_TO_LIVE_UNIT = TimeUnit.SECONDS;
|
||||
public static final boolean DEFAULT_FOLLOW_REDIRECTS = true;
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 2000;
|
||||
public static final int DEFAULT_CONNECTION_TIMER_REPEAT = 3000;
|
||||
|
||||
private boolean disableSslValidation = DEFAULT_DISABLE_SSL_VALIDATION;
|
||||
private int maxConnections = DEFAULT_MAX_CONNECTIONS;
|
||||
private int maxConnectionsPerRoute = DEFAULT_MAX_CONNECTIONS_PER_ROUTE;
|
||||
private long timeToLive = DEFAULT_TIME_TO_LIVE;
|
||||
private TimeUnit timeToLiveUnit = DEFAULT_TIME_TO_LIVE_UNIT;
|
||||
private boolean followRedirects = DEFAULT_FOLLOW_REDIRECTS;
|
||||
private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
|
||||
private int connectionTimerRepeat = DEFAULT_CONNECTION_TIMER_REPEAT;
|
||||
|
||||
public int getConnectionTimerRepeat() {
|
||||
return connectionTimerRepeat;
|
||||
}
|
||||
|
||||
public void setConnectionTimerRepeat(int connectionTimerRepeat) {
|
||||
this.connectionTimerRepeat = connectionTimerRepeat;
|
||||
}
|
||||
|
||||
public boolean isDisableSslValidation() {
|
||||
return disableSslValidation;
|
||||
}
|
||||
|
||||
public void setDisableSslValidation(boolean disableSslValidation) {
|
||||
this.disableSslValidation = disableSslValidation;
|
||||
}
|
||||
|
||||
public int getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
public void setMaxConnections(int maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
public int getMaxConnectionsPerRoute() {
|
||||
return maxConnectionsPerRoute;
|
||||
}
|
||||
|
||||
public void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) {
|
||||
this.maxConnectionsPerRoute = maxConnectionsPerRoute;
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public void setTimeToLive(long timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeToLiveUnit() {
|
||||
return timeToLiveUnit;
|
||||
}
|
||||
|
||||
public void setTimeToLiveUnit(TimeUnit timeToLiveUnit) {
|
||||
this.timeToLiveUnit = timeToLiveUnit;
|
||||
}
|
||||
|
||||
public boolean isFollowRedirects() {
|
||||
return followRedirects;
|
||||
}
|
||||
|
||||
public void setFollowRedirects(boolean followRedirects) {
|
||||
this.followRedirects = followRedirects;
|
||||
}
|
||||
|
||||
public int getConnectionTimeout() {
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
public void setConnectionTimeout(int connectionTimeout) {
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,19 @@
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.params.ClientPNames;
|
||||
import org.apache.http.client.params.CookiePolicy;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -30,17 +38,22 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient;
|
||||
import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient;
|
||||
import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient;
|
||||
import org.springframework.cloud.netflix.ribbon.okhttp.RetryableOkHttpLoadBalancingClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
import com.netflix.client.AbstractLoadBalancerAwareClient;
|
||||
import com.netflix.client.DefaultLoadBalancerRetryHandler;
|
||||
import com.netflix.client.RetryHandler;
|
||||
import com.netflix.client.config.CommonClientConfigKey;
|
||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.ConfigurationBasedServerList;
|
||||
@@ -70,6 +83,7 @@ import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttps
|
||||
@SuppressWarnings("deprecation")
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@Import(HttpClientConfiguration.class)
|
||||
public class RibbonClientConfiguration {
|
||||
|
||||
@Value("${ribbon.client.name}")
|
||||
@@ -121,6 +135,71 @@ public class RibbonClientConfiguration {
|
||||
return serverList;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)
|
||||
protected static class ApacheHttpClientConfiguration {
|
||||
private final Timer connectionManagerTimer = new Timer(
|
||||
"RibbonApacheHttpClientConfiguration.connectionManagerTimer", true);
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@Autowired(required = false)
|
||||
private RegistryBuilder registryBuilder;
|
||||
|
||||
@Bean
|
||||
public HttpClientConnectionManager httpClientConnectionManager(IClientConfig config,
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory httpClientFactory) {
|
||||
Integer maxTotalConnections = config.getPropertyAsInteger(CommonClientConfigKey.MaxTotalConnections,
|
||||
DefaultClientConfigImpl.DEFAULT_MAX_TOTAL_CONNECTIONS);
|
||||
Integer maxConnectionsPerHost = config.getPropertyAsInteger(CommonClientConfigKey.MaxConnectionsPerHost,
|
||||
DefaultClientConfigImpl.DEFAULT_MAX_CONNECTIONS_PER_HOST);
|
||||
Integer timerRepeat = config.getPropertyAsInteger(CommonClientConfigKey.ConnectionCleanerRepeatInterval,
|
||||
DefaultClientConfigImpl.DEFAULT_CONNECTION_IDLE_TIMERTASK_REPEAT_IN_MSECS);
|
||||
Object timeToLiveObj = config.getProperty(CommonClientConfigKey.PoolKeepAliveTime);
|
||||
Long timeToLive = DefaultClientConfigImpl.DEFAULT_POOL_KEEP_ALIVE_TIME;
|
||||
Object ttlUnitObj = config.getProperty(CommonClientConfigKey.PoolKeepAliveTimeUnits);
|
||||
TimeUnit ttlUnit = DefaultClientConfigImpl.DEFAULT_POOL_KEEP_ALIVE_TIME_UNITS;
|
||||
if(timeToLiveObj instanceof Long) {
|
||||
timeToLive = (Long)timeToLiveObj;
|
||||
}
|
||||
if(ttlUnitObj instanceof TimeUnit) {
|
||||
ttlUnit = (TimeUnit)ttlUnitObj;
|
||||
}
|
||||
final HttpClientConnectionManager connectionManager = connectionManagerFactory.newConnectionManager(false, maxTotalConnections,
|
||||
maxConnectionsPerHost, timeToLive, ttlUnit, registryBuilder);
|
||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
connectionManager.closeExpiredConnections();
|
||||
}
|
||||
}, 30000, timerRepeat);
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory,
|
||||
HttpClientConnectionManager connectionManager, IClientConfig config) {
|
||||
Boolean followRedirects = config.getPropertyAsBoolean(
|
||||
CommonClientConfigKey.FollowRedirects,
|
||||
DefaultClientConfigImpl.DEFAULT_FOLLOW_REDIRECTS);
|
||||
Integer connectTimeout = config.getPropertyAsInteger(
|
||||
CommonClientConfigKey.ConnectTimeout,
|
||||
DefaultClientConfigImpl.DEFAULT_CONNECT_TIMEOUT);
|
||||
RequestConfig defaultRequestConfig = RequestConfig.custom().
|
||||
setConnectTimeout(connectTimeout).
|
||||
setRedirectsEnabled(followRedirects).
|
||||
build();
|
||||
this.httpClient = httpClientFactory.createClient(defaultRequestConfig, connectionManager);
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() throws Exception {
|
||||
connectionManagerTimer.cancel();
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)
|
||||
protected static class HttpClientRibbonConfiguration {
|
||||
@@ -132,8 +211,8 @@ public class RibbonClientConfiguration {
|
||||
@ConditionalOnMissingClass(value = "org.springframework.retry.support.RetryTemplate")
|
||||
public RibbonLoadBalancingHttpClient ribbonLoadBalancingHttpClient(
|
||||
IClientConfig config, ServerIntrospector serverIntrospector,
|
||||
ILoadBalancer loadBalancer, RetryHandler retryHandler) {
|
||||
RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(
|
||||
ILoadBalancer loadBalancer, RetryHandler retryHandler, CloseableHttpClient httpClient) {
|
||||
RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(httpClient,
|
||||
config, serverIntrospector);
|
||||
client.setLoadBalancer(loadBalancer);
|
||||
client.setRetryHandler(retryHandler);
|
||||
@@ -147,8 +226,9 @@ public class RibbonClientConfiguration {
|
||||
public RetryableRibbonLoadBalancingHttpClient retryableRibbonLoadBalancingHttpClient(
|
||||
IClientConfig config, ServerIntrospector serverIntrospector,
|
||||
ILoadBalancer loadBalancer, RetryHandler retryHandler,
|
||||
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
|
||||
RetryableRibbonLoadBalancingHttpClient client = new RetryableRibbonLoadBalancingHttpClient(
|
||||
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory,
|
||||
CloseableHttpClient httpClient) {
|
||||
RetryableRibbonLoadBalancingHttpClient client = new RetryableRibbonLoadBalancingHttpClient(httpClient,
|
||||
config, serverIntrospector, loadBalancedRetryPolicyFactory);
|
||||
client.setLoadBalancer(loadBalancer);
|
||||
client.setRetryHandler(retryHandler);
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy;
|
||||
@@ -50,10 +51,17 @@ import com.netflix.loadbalancer.Server;
|
||||
public class RetryableRibbonLoadBalancingHttpClient extends RibbonLoadBalancingHttpClient implements ServiceInstanceChooser {
|
||||
private LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory =
|
||||
new LoadBalancedRetryPolicyFactory.NeverRetryFactory();
|
||||
public RetryableRibbonLoadBalancingHttpClient(IClientConfig config, ServerIntrospector serverIntrospector, LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
|
||||
|
||||
public RetryableRibbonLoadBalancingHttpClient(IClientConfig config, ServerIntrospector serverIntrospector,
|
||||
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
|
||||
super(config, serverIntrospector);
|
||||
this.loadBalancedRetryPolicyFactory = loadBalancedRetryPolicyFactory;
|
||||
}
|
||||
public RetryableRibbonLoadBalancingHttpClient(CloseableHttpClient delegate, IClientConfig config, ServerIntrospector serverIntrospector,
|
||||
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
|
||||
super(delegate, config, serverIntrospector);
|
||||
this.loadBalancedRetryPolicyFactory = loadBalancedRetryPolicyFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RibbonApacheHttpResponse execute(final RibbonApacheHttpRequest request, final IClientConfig configOverride) throws Exception {
|
||||
|
||||
@@ -20,12 +20,11 @@ import com.netflix.client.RequestSpecificRetryHandler;
|
||||
import com.netflix.client.RetryHandler;
|
||||
import com.netflix.client.config.CommonClientConfigKey;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
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.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
|
||||
import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient;
|
||||
@@ -41,27 +40,17 @@ import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttps
|
||||
*/
|
||||
//TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClient
|
||||
public class RibbonLoadBalancingHttpClient extends
|
||||
AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse, HttpClient> {
|
||||
|
||||
@Deprecated
|
||||
public RibbonLoadBalancingHttpClient() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public RibbonLoadBalancingHttpClient(final ILoadBalancer lb) {
|
||||
super(lb);
|
||||
}
|
||||
AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse, CloseableHttpClient> {
|
||||
|
||||
public RibbonLoadBalancingHttpClient(IClientConfig config, ServerIntrospector serverIntrospector) {
|
||||
super(config, serverIntrospector);
|
||||
}
|
||||
|
||||
public RibbonLoadBalancingHttpClient(HttpClient delegate, IClientConfig config, ServerIntrospector serverIntrospector) {
|
||||
public RibbonLoadBalancingHttpClient(CloseableHttpClient delegate, IClientConfig config, ServerIntrospector serverIntrospector) {
|
||||
super(delegate, config, serverIntrospector);
|
||||
}
|
||||
|
||||
protected HttpClient createDelegate(IClientConfig config) {
|
||||
protected CloseableHttpClient createDelegate(IClientConfig config) {
|
||||
return HttpClientBuilder.create()
|
||||
// already defaults to 0 in builder, so resetting to 0 won't hurt
|
||||
.setMaxConnTotal(config.getPropertyAsInteger(CommonClientConfigKey.MaxTotalConnections, 0))
|
||||
|
||||
@@ -32,6 +32,9 @@ import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
|
||||
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
|
||||
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
@@ -59,7 +62,8 @@ import org.springframework.context.annotation.Import;
|
||||
@Configuration
|
||||
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
|
||||
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
|
||||
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class })
|
||||
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,
|
||||
HttpClientConfiguration.class})
|
||||
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
|
||||
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
|
||||
|
||||
@@ -102,8 +106,10 @@ public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SimpleHostRoutingFilter.class)
|
||||
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) {
|
||||
return new SimpleHostRoutingFilter(helper, zuulProperties);
|
||||
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties,
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory httpClientFactory) {
|
||||
return new SimpleHostRoutingFilter(helper, zuulProperties, connectionManagerFactory, httpClientFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -19,9 +19,6 @@ package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -30,9 +27,6 @@ import java.util.TimerTask;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -41,32 +35,21 @@ import org.apache.http.Header;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolException;
|
||||
import org.apache.http.client.RedirectStrategy;
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
|
||||
@@ -80,8 +63,6 @@ import org.springframework.util.StringUtils;
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.HTTPS_SCHEME;
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.HTTP_SCHEME;
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SIMPLE_HOST_ROUTING_FILTER_ORDER;
|
||||
|
||||
@@ -105,7 +86,9 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
|
||||
private ProxyRequestHelper helper;
|
||||
private Host hostProperties;
|
||||
private PoolingHttpClientConnectionManager connectionManager;
|
||||
private ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
|
||||
private ApacheHttpClientFactory httpClientFactory;
|
||||
private HttpClientConnectionManager connectionManager;
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@EventListener
|
||||
@@ -130,16 +113,23 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties properties) {
|
||||
public SimpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties properties,
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory httpClientFactory) {
|
||||
this.helper = helper;
|
||||
this.hostProperties = properties.getHost();
|
||||
this.sslHostnameValidationEnabled = properties.isSslHostnameValidationEnabled();
|
||||
this.forceOriginalQueryStringEncoding = properties
|
||||
.isForceOriginalQueryStringEncoding();
|
||||
this.connectionManagerFactory = connectionManagerFactory;
|
||||
this.httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void initialize() {
|
||||
this.connectionManager = connectionManagerFactory.newConnectionManager(this.sslHostnameValidationEnabled,
|
||||
this.hostProperties.getMaxTotalConnections(), this.hostProperties.getMaxPerRouteConnections(),
|
||||
this.hostProperties.getTimeToLive(), this.hostProperties.getTimeUnit(), null);
|
||||
this.httpClient = newClient();
|
||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
@@ -201,50 +191,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PoolingHttpClientConnectionManager newConnectionManager() {
|
||||
try {
|
||||
final SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates,
|
||||
String s) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates,
|
||||
String s) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
} }, new SecureRandom());
|
||||
|
||||
RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder
|
||||
.<ConnectionSocketFactory> create()
|
||||
.register(HTTP_SCHEME, PlainConnectionSocketFactory.INSTANCE);
|
||||
if (this.sslHostnameValidationEnabled) {
|
||||
registryBuilder.register(HTTPS_SCHEME,
|
||||
new SSLConnectionSocketFactory(sslContext));
|
||||
}
|
||||
else {
|
||||
registryBuilder.register(HTTPS_SCHEME, new SSLConnectionSocketFactory(
|
||||
sslContext, NoopHostnameVerifier.INSTANCE));
|
||||
}
|
||||
final Registry<ConnectionSocketFactory> registry = registryBuilder.build();
|
||||
|
||||
this.connectionManager = new PoolingHttpClientConnectionManager(registry, null, null, null,
|
||||
hostProperties.getTimeToLive(), hostProperties.getTimeUnit());
|
||||
this.connectionManager
|
||||
.setMaxTotal(this.hostProperties.getMaxTotalConnections());
|
||||
this.connectionManager.setDefaultMaxPerRoute(
|
||||
this.hostProperties.getMaxPerRouteConnections());
|
||||
return this.connectionManager;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
protected HttpClientConnectionManager getConnectionManager() {
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
protected CloseableHttpClient newClient() {
|
||||
@@ -252,30 +200,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
.setSocketTimeout(this.hostProperties.getSocketTimeoutMillis())
|
||||
.setConnectTimeout(this.hostProperties.getConnectTimeoutMillis())
|
||||
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
if (!this.sslHostnameValidationEnabled) {
|
||||
httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
|
||||
}
|
||||
return httpClientBuilder.setConnectionManager(newConnectionManager())
|
||||
.disableContentCompression()
|
||||
.useSystemProperties().setDefaultRequestConfig(requestConfig)
|
||||
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
|
||||
.setRedirectStrategy(new RedirectStrategy() {
|
||||
@Override
|
||||
public boolean isRedirected(HttpRequest request,
|
||||
HttpResponse response, HttpContext context)
|
||||
throws ProtocolException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpUriRequest getRedirect(HttpRequest request,
|
||||
HttpResponse response, HttpContext context)
|
||||
throws ProtocolException {
|
||||
return null;
|
||||
}
|
||||
}).build();
|
||||
return httpClientFactory.createClient(requestConfig, this.connectionManager);
|
||||
}
|
||||
|
||||
private CloseableHttpResponse forward(CloseableHttpClient httpclient, String verb,
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
*
|
||||
* * 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;
|
||||
|
||||
import feign.Client;
|
||||
import feign.httpclient.ApacheHttpClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockingDetails;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientFactory;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
import org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient;
|
||||
import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommand;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockingDetails;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = HttpClientConfigurationTestApp.class, value = {"feign.okhttp.enabled: false",
|
||||
"ribbon.eureka.enabled = false"})
|
||||
@DirtiesContext
|
||||
public class HttpClientConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
|
||||
|
||||
@Autowired
|
||||
ApacheHttpClientFactory httpClientFactory;
|
||||
|
||||
@Autowired
|
||||
SimpleHostRoutingFilter simpleHostRoutingFilter;
|
||||
|
||||
@Autowired
|
||||
LoadBalancerFeignClient feignClient;
|
||||
|
||||
@Autowired
|
||||
HttpClientRibbonCommandFactory httpClientRibbonCommandFactory;
|
||||
|
||||
@Test
|
||||
public void testFactories() {
|
||||
assertTrue(ApacheHttpClientConnectionManagerFactory.class.isInstance(connectionManagerFactory));
|
||||
assertTrue(HttpClientConfigurationTestApp.MyApacheHttpClientConnectionManagerFactory.class.isInstance(connectionManagerFactory));
|
||||
assertTrue(ApacheHttpClientFactory.class.isInstance(httpClientFactory));
|
||||
assertTrue(HttpClientConfigurationTestApp.MyApacheHttpClientFactory.class.isInstance(httpClientFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpClientSimpleHostRoutingFilter() {
|
||||
PoolingHttpClientConnectionManager connectionManager = getField(simpleHostRoutingFilter, "connectionManager");
|
||||
MockingDetails connectionManagerDetails = mockingDetails(connectionManager);
|
||||
assertTrue(connectionManagerDetails.isMock());
|
||||
CloseableHttpClient httpClient = getField(simpleHostRoutingFilter, "httpClient");
|
||||
MockingDetails httpClientDetails = mockingDetails(httpClient);
|
||||
assertTrue(httpClientDetails.isMock());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpClientWithFeign() {
|
||||
Client delegate = feignClient.getDelegate();
|
||||
assertTrue(ApacheHttpClient.class.isInstance(delegate));
|
||||
ApacheHttpClient apacheHttpClient = (ApacheHttpClient)delegate;
|
||||
HttpClient httpClient = getField(apacheHttpClient, "client");
|
||||
MockingDetails httpClientDetails = mockingDetails(httpClient);
|
||||
assertTrue(httpClientDetails.isMock());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRibbonLoadBalancingHttpClient() {
|
||||
RibbonCommandContext context = new RibbonCommandContext("foo"," GET", "http://localhost",
|
||||
false, new LinkedMultiValueMap<String, String>(), new LinkedMultiValueMap<String, String>(),
|
||||
null, new ArrayList<RibbonRequestCustomizer>(), 0l);
|
||||
HttpClientRibbonCommand command = httpClientRibbonCommandFactory.create(context);
|
||||
RibbonLoadBalancingHttpClient ribbonClient = command.getClient();
|
||||
CloseableHttpClient httpClient = getField(ribbonClient, "delegate");
|
||||
MockingDetails httpClientDetails = mockingDetails(httpClient);
|
||||
assertTrue(httpClientDetails.isMock());
|
||||
}
|
||||
|
||||
protected <T> T getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
Object value = ReflectionUtils.getField(field, target);
|
||||
return (T)value;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
@EnableFeignClients(clients = {HttpClientConfigurationTestApp.FooClient.class})
|
||||
@EnableZuulProxy
|
||||
class HttpClientConfigurationTestApp {
|
||||
|
||||
@RequestMapping
|
||||
public String index() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
static class MyApacheHttpClientConnectionManagerFactory extends DefaultApacheHttpClientConnectionManagerFactory {
|
||||
@Override
|
||||
public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation, int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive, TimeUnit timeUnit, RegistryBuilder registry) {
|
||||
return mock(PoolingHttpClientConnectionManager.class);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyApacheHttpClientFactory extends DefaultApacheHttpClientFactory {
|
||||
@Override
|
||||
public CloseableHttpClient createClient(RequestConfig requestConfig, HttpClientConnectionManager connectionManager) {
|
||||
CloseableHttpClient client = mock(CloseableHttpClient.class);
|
||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
doReturn(statusLine).when(response).getStatusLine();
|
||||
Header[] headers = new BasicHeader[0];
|
||||
doReturn(headers).when(response).getAllHeaders();
|
||||
try {
|
||||
doReturn(response).when(client).execute(any(HttpUriRequest.class));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MyConfig {
|
||||
|
||||
@Bean
|
||||
public ApacheHttpClientFactory apacheHttpClientFactory() {
|
||||
return new MyApacheHttpClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApacheHttpClientConnectionManagerFactory connectionManagerFactory() {
|
||||
return new MyApacheHttpClientConnectionManagerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(name="foo", serviceId = "foo")
|
||||
static interface FooClient {}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.ClassPathExclusions;
|
||||
import org.springframework.cloud.FilteredClassPathRunner;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.encoding.FeignAcceptGzipEncodingAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.encoding.FeignAcceptGzipEncodingInterceptor;
|
||||
@@ -58,7 +59,7 @@ public class FeignCompressionTests {
|
||||
context = new SpringApplicationBuilder().properties("feign.compression.response.enabled=true",
|
||||
"feign.compression.request.enabled=true", "feign.okhttp.enabled=false").sources(PropertyPlaceholderAutoConfiguration.class,
|
||||
ArchaiusAutoConfiguration.class, FeignAutoConfiguration.class, PlainConfig.class, FeignContentGzipEncodingAutoConfiguration.class,
|
||||
FeignAcceptGzipEncodingAutoConfiguration.class).web(false).run();
|
||||
FeignAcceptGzipEncodingAutoConfiguration.class, HttpClientConfiguration.class).web(false).run();
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* * 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.feign.support;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class FeignHttpClientPropertiesTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
public void clear() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaults() {
|
||||
setupContext();
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_CONNECTION_TIMEOUT, getProperties().getConnectionTimeout());
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS, getProperties().getMaxConnections());
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS_PER_ROUTE, getProperties().getMaxConnectionsPerRoute());
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_TIME_TO_LIVE, getProperties().getTimeToLive());
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_DISABLE_SSL_VALIDATION, getProperties().isDisableSslValidation());
|
||||
assertEquals(FeignHttpClientProperties.DEFAULT_FOLLOW_REDIRECTS, getProperties().isFollowRedirects());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomization() {
|
||||
addEnvironment(this.context, "feign.httpclient.maxConnections=2",
|
||||
"feign.httpclient.connectionTimeout=2",
|
||||
"feign.httpclient.maxConnectionsPerRoute=2",
|
||||
"feign.httpclient.timeToLive=2",
|
||||
"feign.httpclient.disableSslValidation=true",
|
||||
"feign.httpclient.followRedirects=false");
|
||||
setupContext();
|
||||
assertEquals(2, getProperties().getMaxConnections());
|
||||
assertEquals(2, getProperties().getConnectionTimeout());
|
||||
assertEquals(2, getProperties().getMaxConnectionsPerRoute());
|
||||
assertEquals(2L, getProperties().getTimeToLive());
|
||||
assertTrue(getProperties().isDisableSslValidation());
|
||||
assertFalse(getProperties().isFollowRedirects());
|
||||
}
|
||||
|
||||
private void setupContext() {
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
}
|
||||
|
||||
private FeignHttpClientProperties getProperties() {
|
||||
return this.context.getBean(FeignHttpClientProperties.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
protected static class TestConfiguration {
|
||||
@Bean
|
||||
FeignHttpClientProperties zuulProperties() {
|
||||
return new FeignHttpClientProperties() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.feign.valid;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
@@ -45,7 +46,7 @@ public class FeignClientValidationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(FeignAutoConfiguration.class)
|
||||
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
@EnableFeignClients(clients = GoodUrlConfiguration.Client.class)
|
||||
protected static class GoodUrlConfiguration {
|
||||
|
||||
@@ -67,7 +68,7 @@ public class FeignClientValidationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(FeignAutoConfiguration.class)
|
||||
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
@EnableFeignClients(clients = PlaceholderUrlConfiguration.Client.class)
|
||||
protected static class PlaceholderUrlConfiguration {
|
||||
|
||||
@@ -92,7 +93,7 @@ public class FeignClientValidationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(FeignAutoConfiguration.class)
|
||||
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
@EnableFeignClients(clients = GoodServiceIdConfiguration.Client.class)
|
||||
protected static class GoodServiceIdConfiguration {
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClientsPreprocessorIntegrationTests.TestConfiguration;
|
||||
@@ -66,7 +67,7 @@ public class RibbonClientsPreprocessorIntegrationTests {
|
||||
@Configuration
|
||||
@RibbonClients(@RibbonClient(name = "foo", configuration = FooConfiguration.class))
|
||||
@Import({ UtilAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
ArchaiusAutoConfiguration.class, RibbonAutoConfiguration.class })
|
||||
ArchaiusAutoConfiguration.class, RibbonAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
protected static class TestConfiguration {
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ 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.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
@@ -69,7 +70,7 @@ public class SpringClientFactoryTests {
|
||||
public void testConfigureRetry() {
|
||||
SpringClientFactory factory = new SpringClientFactory();
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
|
||||
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class);
|
||||
RibbonAutoConfiguration.class, ArchaiusAutoConfiguration.class, HttpClientConfiguration.class);
|
||||
addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
|
||||
factory.setApplicationContext(parent);
|
||||
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.ribbon.CachingSpringLoadBalancerFactory;
|
||||
import org.springframework.cloud.netflix.feign.ribbon.FeignLoadBalancer;
|
||||
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration;
|
||||
@@ -45,7 +46,7 @@ import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = {RibbonAutoConfiguration.class, RibbonClientConfiguration.class, LoadBalancerAutoConfiguration.class,
|
||||
FeignRibbonClientAutoConfiguration.class})
|
||||
FeignRibbonClientAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
public class SpringRetryEnabledTests implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -169,7 +170,7 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
@Test
|
||||
public void testNeverRetry() throws Exception {
|
||||
ServerIntrospector introspector = mock(ServerIntrospector.class);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
HttpResponse response = mock(HttpResponse.class);
|
||||
doThrow(new IOException("boom")).when(delegate).execute(any(HttpUriRequest.class));
|
||||
DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
|
||||
@@ -220,8 +221,8 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
int port = 80;
|
||||
HttpMethod method = HttpMethod.GET;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
final HttpResponse response = mock(HttpResponse.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
final CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
doReturn(statusLine).when(response).getStatusLine();
|
||||
@@ -252,8 +253,8 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
int port = 80;
|
||||
HttpMethod method = HttpMethod.GET;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
final HttpResponse response = mock(HttpResponse.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
final CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
doReturn(statusLine).when(response).getStatusLine();
|
||||
@@ -285,7 +286,7 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
int port = 80;
|
||||
HttpMethod method = HttpMethod.POST;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
final CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
@@ -318,7 +319,7 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
int port = 80;
|
||||
HttpMethod method = HttpMethod.POST;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
final CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
doThrow(new IOException("boom")).doThrow(new IOException("boom again")).doReturn(response).
|
||||
when(delegate).execute(any(HttpUriRequest.class));
|
||||
@@ -353,8 +354,8 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
int port = 80;
|
||||
HttpMethod method = HttpMethod.GET;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
final HttpResponse response = mock(HttpResponse.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
final CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
doReturn(statusLine).when(response).getStatusLine();
|
||||
@@ -442,13 +443,13 @@ public class RibbonLoadBalancingHttpClientTests {
|
||||
String host = serviceName;
|
||||
int port = 80;
|
||||
URI uri = new URI("http://" + host + ":" + port);
|
||||
HttpClient delegate = mock(HttpClient.class);
|
||||
CloseableHttpClient delegate = mock(CloseableHttpClient.class);
|
||||
RibbonLoadBalancingHttpClient client = factory.getClient("service",
|
||||
RibbonLoadBalancingHttpClient.class);
|
||||
|
||||
ReflectionTestUtils.setField(client, "delegate", delegate);
|
||||
ReflectionTestUtils.setField(client, "lb", loadBalancer);
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
CloseableHttpResponse httpResponse = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
doReturn(200).when(statusLine).getStatusCode();
|
||||
doReturn(statusLine).when(httpResponse).getStatusLine();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.netflix.ribbon.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||
@@ -40,7 +41,7 @@ import com.netflix.loadbalancer.ServerListSubsetFilter;
|
||||
*/
|
||||
@Configuration
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, RibbonAutoConfiguration.class })
|
||||
UtilAutoConfiguration.class, RibbonAutoConfiguration.class, HttpClientConfiguration.class})
|
||||
@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
|
||||
public class RibbonClientDefaultConfigurationTestsConfig {
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.impl.client.BasicCookieStore;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
@@ -38,6 +39,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientFactory;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.cloud.netflix.zuul.RoutesMvcEndpoint;
|
||||
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
|
||||
@@ -210,16 +214,23 @@ class SampleCustomZuulProxyApplication {
|
||||
@EnableZuulProxy
|
||||
protected static class CustomZuulProxyConfig {
|
||||
|
||||
@Bean
|
||||
public ApacheHttpClientFactory customHttpClientFactory() {
|
||||
return new CustomApacheHttpClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper,
|
||||
ZuulProperties zuulProperties) {
|
||||
return new CustomHostRoutingFilter(helper, zuulProperties);
|
||||
ZuulProperties zuulProperties, ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory httpClientFactory) {
|
||||
return new CustomHostRoutingFilter(helper, zuulProperties, connectionManagerFactory, httpClientFactory);
|
||||
}
|
||||
|
||||
private class CustomHostRoutingFilter extends SimpleHostRoutingFilter {
|
||||
public CustomHostRoutingFilter(ProxyRequestHelper helper,
|
||||
ZuulProperties zuulProperties) {
|
||||
super(helper, zuulProperties);
|
||||
ZuulProperties zuulProperties, ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory httpClientFactory) {
|
||||
super(helper, zuulProperties, connectionManagerFactory, httpClientFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,13 +238,13 @@ class SampleCustomZuulProxyApplication {
|
||||
super.addIgnoredHeaders("X-Ignored");
|
||||
return super.run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class CustomApacheHttpClientFactory extends DefaultApacheHttpClientFactory {
|
||||
@Override
|
||||
protected CloseableHttpClient newClient() {
|
||||
// Custom client with cookie support.
|
||||
// In practice, we would want a custom cookie store using a multimap with
|
||||
// a user key.
|
||||
return HttpClients.custom().setConnectionManager(newConnectionManager())
|
||||
public CloseableHttpClient createClient(RequestConfig requestConfig, HttpClientConnectionManager connectionManager) {
|
||||
return HttpClients.custom().setConnectionManager(connectionManager)
|
||||
.setDefaultCookieStore(new BasicCookieStore())
|
||||
.setDefaultRequestConfig(RequestConfig.custom()
|
||||
.setCookieSpec(CookieSpecs.DEFAULT).build())
|
||||
|
||||
@@ -47,6 +47,10 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon
|
||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientConnectionManagerFactory;
|
||||
import org.springframework.cloud.commons.httpclient.DefaultApacheHttpClientFactory;
|
||||
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
|
||||
@@ -113,7 +117,7 @@ public class SimpleHostRoutingFilterTests {
|
||||
"zuul.host.maxPerRouteConnections=10", "zuul.host.timeToLive=5",
|
||||
"zuul.host.timeUnit=SECONDS");
|
||||
setupContext();
|
||||
PoolingHttpClientConnectionManager connMgr = getFilter().newConnectionManager();
|
||||
PoolingHttpClientConnectionManager connMgr = (PoolingHttpClientConnectionManager)getFilter().getConnectionManager();
|
||||
assertEquals(100, connMgr.getMaxTotal());
|
||||
assertEquals(10, connMgr.getDefaultMaxPerRoute());
|
||||
Object pool = getField(connMgr, "pool");
|
||||
@@ -148,7 +152,7 @@ public class SimpleHostRoutingFilterTests {
|
||||
@Test
|
||||
public void defaultPropertiesAreApplied() {
|
||||
setupContext();
|
||||
PoolingHttpClientConnectionManager connMgr = getFilter().newConnectionManager();
|
||||
PoolingHttpClientConnectionManager connMgr = (PoolingHttpClientConnectionManager)getFilter().getConnectionManager();
|
||||
|
||||
assertEquals(200, connMgr.getMaxTotal());
|
||||
assertEquals(20, connMgr.getDefaultMaxPerRoute());
|
||||
@@ -222,8 +226,16 @@ public class SimpleHostRoutingFilterTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
SimpleHostRoutingFilter simpleHostRoutingFilter(ZuulProperties zuulProperties) {
|
||||
return new SimpleHostRoutingFilter(new ProxyRequestHelper(), zuulProperties);
|
||||
ApacheHttpClientFactory clientFactory() {return new DefaultApacheHttpClientFactory(); }
|
||||
|
||||
@Bean
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory() { return new DefaultApacheHttpClientConnectionManagerFactory(); }
|
||||
|
||||
@Bean
|
||||
SimpleHostRoutingFilter simpleHostRoutingFilter(ZuulProperties zuulProperties,
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||
ApacheHttpClientFactory clientFactory) {
|
||||
return new SimpleHostRoutingFilter(new ProxyRequestHelper(), zuulProperties, connectionManagerFactory, clientFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user