com.netflix.niws.client.http.RestClient Maven / Gradle / Ivy
/*
*
* Copyright 2013 Netflix, Inc.
*
* 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 com.netflix.niws.client.http;
import java.io.File;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.KeyStore;
import java.util.Collection;
import java.util.Map;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.UserTokenHandler;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnRouteParams;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.client.config.IClientConfigKey;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.client.ssl.AbstractSslContextFactory;
import com.netflix.client.ssl.ClientSslSocketFactoryException;
import com.netflix.client.ssl.URLSslContextFactory;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.http4.NFHttpClient;
import com.netflix.http4.NFHttpClientConstants;
import com.netflix.http4.NFHttpClientFactory;
import com.netflix.http4.NFHttpMethodRetryHandler;
import com.netflix.http4.ssl.KeyStoreAwareSocketFactory;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.util.Pair;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import com.sun.jersey.client.apache4.ApacheHttpClient4Handler;
import com.sun.jersey.client.apache4.config.ApacheHttpClient4Config;
import com.sun.jersey.client.apache4.config.DefaultApacheHttpClient4Config;
/**
* A client that is essentially a wrapper around Jersey client. By default, it uses HttpClient for underlying HTTP communication.
* Application can set its own Jersey client with this class, but doing so will void all client configurations set in {@link IClientConfig}.
*
* @deprecated Please see ribbon-rxnetty module for the Netty based client.
*
* @author awang
*
*/
@Deprecated
public class RestClient extends AbstractLoadBalancerAwareClient {
private Client restClient;
private HttpClient httpClient4;
private IClientConfig ncc;
private String restClientName;
private boolean enableConnectionPoolCleanerTask = false;
private DynamicIntProperty connIdleEvictTimeMilliSeconds;
private int connectionCleanerRepeatInterval;
private int maxConnectionsperHost;
private int maxTotalConnections;
private int connectionTimeout;
private int readTimeout;
private String proxyHost;
private int proxyPort;
private boolean isSecure;
private boolean isHostnameValidationRequired;
private boolean isClientAuthRequired;
private boolean ignoreUserToken;
private ApacheHttpClient4Config config;
boolean bFollowRedirects = DefaultClientConfigImpl.DEFAULT_FOLLOW_REDIRECTS;
private static final Logger logger = LoggerFactory.getLogger(RestClient.class);
public RestClient() {
super(null);
}
public RestClient(ILoadBalancer lb) {
super(lb);
restClientName = "default";
}
public RestClient(ILoadBalancer lb, IClientConfig ncc) {
super(lb, ncc);
initWithNiwsConfig(ncc);
}
public RestClient(IClientConfig ncc) {
super(null, ncc);
initWithNiwsConfig(ncc);
}
public RestClient(ILoadBalancer lb, Client jerseyClient) {
super(lb);
this.restClient = jerseyClient;
this.setRetryHandler(new HttpClientLoadBalancerErrorHandler());
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
super.initWithNiwsConfig(clientConfig);
this.ncc = clientConfig;
this.restClientName = ncc.getClientName();
this.isSecure = getBooleanFromConfig(ncc, CommonClientConfigKey.IsSecure, this.isSecure);
this.isHostnameValidationRequired = getBooleanFromConfig(ncc, CommonClientConfigKey.IsHostnameValidationRequired, this.isHostnameValidationRequired);
this.isClientAuthRequired = getBooleanFromConfig(ncc, CommonClientConfigKey.IsClientAuthRequired, this.isClientAuthRequired);
this.bFollowRedirects = getBooleanFromConfig(ncc, CommonClientConfigKey.FollowRedirects, true);
this.ignoreUserToken = getBooleanFromConfig(ncc, CommonClientConfigKey.IgnoreUserTokenInConnectionPoolForSecureClient, this.ignoreUserToken);
this.config = new DefaultApacheHttpClient4Config();
this.config.getProperties().put(
ApacheHttpClient4Config.PROPERTY_CONNECT_TIMEOUT,
Integer.parseInt(String.valueOf(ncc.getProperty(CommonClientConfigKey.ConnectTimeout))));
this.config.getProperties().put(
ApacheHttpClient4Config.PROPERTY_READ_TIMEOUT,
Integer.parseInt(String.valueOf(ncc.getProperty(CommonClientConfigKey.ReadTimeout))));
this.restClient = apacheHttpClientSpecificInitialization();
this.setRetryHandler(new HttpClientLoadBalancerErrorHandler(ncc));
}
protected Client apacheHttpClientSpecificInitialization() {
httpClient4 = NFHttpClientFactory.getNamedNFHttpClient(restClientName, this.ncc, true);
if (httpClient4 instanceof AbstractHttpClient) {
// DONT use our NFHttpClient's default Retry Handler since we have
// retry handling (same server/next server) in RestClient itself
((AbstractHttpClient) httpClient4).setHttpRequestRetryHandler(new NFHttpMethodRetryHandler(restClientName, 0, false, 0));
} else {
logger.warn("Unexpected error: Unable to disable NFHttpClient "
+ "retry handler, this most likely will not cause an "
+ "issue but probably should be looked at");
}
HttpParams httpClientParams = httpClient4.getParams();
// initialize Connection Manager cleanup facility
NFHttpClient nfHttpClient = (NFHttpClient) httpClient4;
// should we enable connection cleanup for idle connections?
try {
enableConnectionPoolCleanerTask = Boolean.parseBoolean(ncc.getProperty(CommonClientConfigKey.ConnectionPoolCleanerTaskEnabled,
NFHttpClientConstants.DEFAULT_CONNECTIONIDLE_TIMETASK_ENABLED).toString());
nfHttpClient.getConnPoolCleaner().setEnableConnectionPoolCleanerTask(enableConnectionPoolCleanerTask);
} catch (Exception e1) {
throw new IllegalArgumentException("Invalid value for property:"
+ CommonClientConfigKey.ConnectionPoolCleanerTaskEnabled, e1);
}
if (enableConnectionPoolCleanerTask) {
try {
connectionCleanerRepeatInterval = Integer
.parseInt(String.valueOf(ncc.getProperty(CommonClientConfigKey.ConnectionCleanerRepeatInterval,
NFHttpClientConstants.DEFAULT_CONNECTION_IDLE_TIMERTASK_REPEAT_IN_MSECS)));
nfHttpClient.getConnPoolCleaner().setConnectionCleanerRepeatInterval(connectionCleanerRepeatInterval);
} catch (Exception e1) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.ConnectionCleanerRepeatInterval, e1);
}
try {
int iConnIdleEvictTimeMilliSeconds = Integer
.parseInt(""
+ ncc
.getProperty(CommonClientConfigKey.ConnIdleEvictTimeMilliSeconds,
NFHttpClientConstants.DEFAULT_CONNECTIONIDLE_TIME_IN_MSECS));
connIdleEvictTimeMilliSeconds = DynamicPropertyFactory.getInstance().getIntProperty(
restClientName
+ ".nfhttpclient.connIdleEvictTimeMilliSeconds",
iConnIdleEvictTimeMilliSeconds);
nfHttpClient.setConnIdleEvictTimeMilliSeconds(connIdleEvictTimeMilliSeconds);
} catch (Exception e1) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.ConnIdleEvictTimeMilliSeconds,
e1);
}
nfHttpClient.initConnectionCleanerTask();
}
try {
maxConnectionsperHost = Integer
.parseInt(""
+ ncc
.getProperty(CommonClientConfigKey.MaxHttpConnectionsPerHost,
maxConnectionsperHost));
ClientConnectionManager connMgr = httpClient4.getConnectionManager();
if (connMgr instanceof ThreadSafeClientConnManager) {
((ThreadSafeClientConnManager) connMgr)
.setDefaultMaxPerRoute(maxConnectionsperHost);
}
} catch (Exception e1) {
throw new IllegalArgumentException("Invalid value for property:"
+ CommonClientConfigKey.MaxHttpConnectionsPerHost, e1);
}
try {
maxTotalConnections = Integer
.parseInt(""
+ ncc
.getProperty(CommonClientConfigKey.MaxTotalHttpConnections,
maxTotalConnections));
ClientConnectionManager connMgr = httpClient4
.getConnectionManager();
if (connMgr instanceof ThreadSafeClientConnManager) {
((ThreadSafeClientConnManager) connMgr)
.setMaxTotal(maxTotalConnections);
}
} catch (Exception e1) {
throw new IllegalArgumentException("Invalid value for property:"
+ CommonClientConfigKey.MaxTotalHttpConnections, e1);
}
try {
connectionTimeout = Integer.parseInt(""
+ ncc.getProperty(CommonClientConfigKey.ConnectTimeout,
connectionTimeout));
HttpConnectionParams.setConnectionTimeout(httpClientParams,
connectionTimeout);
} catch (Exception e1) {
throw new IllegalArgumentException("Invalid value for property:"
+ CommonClientConfigKey.ConnectTimeout, e1);
}
try {
readTimeout = Integer.parseInt(""
+ ncc.getProperty(CommonClientConfigKey.ReadTimeout,
readTimeout));
HttpConnectionParams.setSoTimeout(httpClientParams, readTimeout);
} catch (Exception e1) {
throw new IllegalArgumentException("Invalid value for property:"
+ CommonClientConfigKey.ReadTimeout, e1);
}
// httpclient 4 seems to only have one buffer size controlling both
// send/receive - so let's take the bigger of the two values and use
// it as buffer size
int bufferSize = Integer.MIN_VALUE;
if (ncc.getProperty(CommonClientConfigKey.ReceiveBufferSize) != null) {
try {
bufferSize = Integer
.parseInt(""
+ ncc
.getProperty(CommonClientConfigKey.ReceiveBufferSize));
} catch (Exception e) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.ReceiveBufferSize,
e);
}
if (ncc.getProperty(CommonClientConfigKey.SendBufferSize) != null) {
try {
int sendBufferSize = Integer
.parseInt(""
+ ncc
.getProperty(CommonClientConfigKey.SendBufferSize));
if (sendBufferSize > bufferSize) {
bufferSize = sendBufferSize;
}
} catch (Exception e) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.SendBufferSize,
e);
}
}
}
if (bufferSize != Integer.MIN_VALUE) {
HttpConnectionParams.setSocketBufferSize(httpClientParams,
bufferSize);
}
if (ncc.getProperty(CommonClientConfigKey.StaleCheckingEnabled) != null) {
try {
HttpConnectionParams
.setStaleCheckingEnabled(httpClientParams,
Boolean.parseBoolean(ncc.getProperty(CommonClientConfigKey.StaleCheckingEnabled, false).toString()));
} catch (Exception e) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.StaleCheckingEnabled,
e);
}
}
if (ncc.getProperty(CommonClientConfigKey.Linger) != null) {
try {
HttpConnectionParams.setLinger(httpClientParams,
Integer.parseInt(""
+ ncc.getProperty(CommonClientConfigKey.Linger)));
} catch (Exception e) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.Linger,
e);
}
}
if (ncc.getProperty(CommonClientConfigKey.ProxyHost) != null) {
try {
proxyHost = (String) ncc
.getProperty(CommonClientConfigKey.ProxyHost);
proxyPort = Integer.parseInt(""
+ ncc.getProperty(CommonClientConfigKey.ProxyPort));
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
httpClient4
.getParams()
.setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
} catch (Exception e) {
throw new IllegalArgumentException(
"Invalid value for property:"
+ CommonClientConfigKey.ProxyHost,
e);
}
}
if (isSecure) {
final URL trustStoreUrl = getResourceForOptionalProperty(CommonClientConfigKey.TrustStore);
final URL keyStoreUrl = getResourceForOptionalProperty(CommonClientConfigKey.KeyStore);
final ClientConnectionManager currentManager = httpClient4.getConnectionManager();
AbstractSslContextFactory abstractFactory = null;
if ( // if client auth is required, need both a truststore and a keystore to warrant configuring
// if client is not is not required, we only need a keystore OR a truststore to warrant configuring
(isClientAuthRequired && (trustStoreUrl != null && keyStoreUrl != null))
||
(!isClientAuthRequired && (trustStoreUrl != null || keyStoreUrl != null))
) {
try {
abstractFactory = new URLSslContextFactory(trustStoreUrl,
(String) ncc.getProperty(CommonClientConfigKey.TrustStorePassword),
keyStoreUrl,
(String) ncc.getProperty(CommonClientConfigKey.KeyStorePassword));
} catch (ClientSslSocketFactoryException e) {
throw new IllegalArgumentException("Unable to configure custom secure socket factory", e);
}
}
KeyStoreAwareSocketFactory awareSocketFactory;
try {
awareSocketFactory = isHostnameValidationRequired ? new KeyStoreAwareSocketFactory(abstractFactory) :
new KeyStoreAwareSocketFactory(abstractFactory, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
currentManager.getSchemeRegistry().register(new Scheme(
"https",443, awareSocketFactory));
} catch (Exception e) {
throw new IllegalArgumentException("Unable to configure custom secure socket factory", e);
}
}
// Warning that if user tokens are used (i.e. ignoreUserToken == false) this may be prevent SSL connections from being
// reused, which is generally not the intent for long-living proxy connections and the like.
// See http://hc.apache.org/httpcomponents-client-ga/tutorial/html/advanced.html
if (ignoreUserToken) {
((DefaultHttpClient) httpClient4).setUserTokenHandler(new UserTokenHandler() {
@Override
public Object getUserToken(HttpContext context) {
return null;
}
});
}
// custom SSL Factory handler
String customSSLFactoryClassName = (String) ncc.getProperty(CommonClientConfigKey.CustomSSLSocketFactoryClassName);
if(customSSLFactoryClassName != null){
try{
SSLSocketFactory customSocketFactory = (SSLSocketFactory) ClientFactory.instantiateInstanceWithClientConfig(customSSLFactoryClassName, ncc);
httpClient4.getConnectionManager().getSchemeRegistry().register(new Scheme(
"https",443, customSocketFactory));
}catch(Exception e){
throw new IllegalArgumentException("Invalid value associated with property:"
+ CommonClientConfigKey.CustomSSLSocketFactoryClassName, e);
}
}
ApacheHttpClient4Handler handler = new ApacheHttpClient4Handler(httpClient4, new BasicCookieStore(), false);
return new ApacheHttpClient4(handler, config);
}
public void resetSSLSocketFactory(AbstractSslContextFactory abstractContextFactory){
try {
KeyStoreAwareSocketFactory awareSocketFactory = isHostnameValidationRequired ? new KeyStoreAwareSocketFactory(abstractContextFactory) :
new KeyStoreAwareSocketFactory(abstractContextFactory, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
httpClient4.getConnectionManager().getSchemeRegistry().register(new Scheme(
"https",443, awareSocketFactory));
} catch (Exception e) {
throw new IllegalArgumentException("Unable to configure custom secure socket factory", e);
}
}
public KeyStore getKeyStore(){
SchemeRegistry registry = httpClient4.getConnectionManager().getSchemeRegistry();
if(! registry.getSchemeNames().contains("https")){
throw new IllegalStateException("Registry does not include an 'https' entry.");
}
SchemeSocketFactory awareSocketFactory = httpClient4.getConnectionManager().getSchemeRegistry().getScheme("https").getSchemeSocketFactory();
if(awareSocketFactory instanceof KeyStoreAwareSocketFactory){
return ((KeyStoreAwareSocketFactory) awareSocketFactory).getKeyStore();
}else{
throw new IllegalStateException("Cannot extract keystore from scheme socket factory of type: " + awareSocketFactory.getClass().getName());
}
}
public static URL getResource(String resourceName)
{
URL url = null;
// attempt to load from the context classpath
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
url = loader.getResource(resourceName);
}
if (url == null) {
// attempt to load from the system classpath
url = ClassLoader.getSystemResource(resourceName);
}
if (url == null) {
// attempt to load from the system classpath
url = ConfigurationManager.class.getResource(resourceName);
}
if (url == null) {
// attempt to load from the system classpath
url = ConfigurationManager.class.getClassLoader().getResource(resourceName);
}
if (url == null) {
try {
resourceName = URLDecoder.decode(resourceName, "UTF-8");
url = (new File(resourceName)).toURI().toURL();
} catch (Exception e) {
logger.error("Problem loading resource", e);
}
}
return url;
}
public Client getJerseyClient() {
return restClient;
}
public void setJerseyClient(Client c) {
restClient = c;
}
private URL getResourceForOptionalProperty(final IClientConfigKey configKey) {
final String propValue = (String) ncc.getProperty(configKey);
URL result = null;
if (propValue != null) {
result = getResource(propValue);
if (result == null) {
throw new IllegalArgumentException("No resource found for " + configKey + ": "
+ propValue);
}
}
return result;
}
public HttpResponse execute(HttpRequest task) throws Exception {
return execute(task, null);
}
@Override
public HttpResponse execute(HttpRequest task, IClientConfig requestConfig) throws Exception {
IClientConfig config = (requestConfig == null) ? task.getOverrideConfig() : requestConfig;
return execute(task.getVerb(), task.getUri(),
task.getHeaders(), task.getQueryParams(), config, task.getEntity());
}
private boolean getBooleanFromConfig(IClientConfig overriddenClientConfig, IClientConfigKey key, boolean defaultValue){
if(overriddenClientConfig != null && overriddenClientConfig.containsProperty(key)){
defaultValue = Boolean.parseBoolean(overriddenClientConfig.getProperty(key).toString());
}
return defaultValue;
}
@Override
protected int getDefaultPortFromScheme(String scheme) {
int port = super.getDefaultPortFromScheme(scheme);
if (port < 0) {
return 80;
} else {
return port;
}
}
@Override
protected Pair deriveSchemeAndPortFromPartialUri(URI uri) {
boolean isSecure = getBooleanFromConfig(ncc, CommonClientConfigKey.IsSecure, this.isSecure);
String scheme = uri.getScheme();
if (scheme != null) {
isSecure = scheme.equalsIgnoreCase("https");
}
int port = uri.getPort();
if (port < 0 && !isSecure){
port = 80;
} else if (port < 0 && isSecure){
port = 443;
}
if (scheme == null){
if (isSecure) {
scheme = "https";
} else {
scheme = "http";
}
}
return new Pair(scheme, port);
}
private HttpResponse execute(HttpRequest.Verb verb, URI uri,
Map> headers, Map> params,
IClientConfig overriddenClientConfig, Object requestEntity) throws Exception {
HttpClientResponse thisResponse = null;
boolean bbFollowRedirects = bFollowRedirects;
// read overriden props
if (overriddenClientConfig != null
// set whether we should auto follow redirects
&& overriddenClientConfig.getProperty(CommonClientConfigKey.FollowRedirects)!=null){
// use default directive from overall config
Boolean followRedirects = Boolean.valueOf(""+overriddenClientConfig.getProperty(CommonClientConfigKey.FollowRedirects, bFollowRedirects));
bbFollowRedirects = followRedirects.booleanValue();
}
restClient.setFollowRedirects(bbFollowRedirects);
if (logger.isDebugEnabled()) {
logger.debug("RestClient sending new Request(" + verb
+ ": ) " + uri);
}
WebResource xResource = restClient.resource(uri.toString());
if (params != null) {
for (Map.Entry> entry: params.entrySet()) {
String name = entry.getKey();
for (String value: entry.getValue()) {
xResource = xResource.queryParam(name, value);
}
}
}
ClientResponse jerseyResponse;
Builder b = xResource.getRequestBuilder();
if (headers != null) {
for (Map.Entry> entry: headers.entrySet()) {
String name = entry.getKey();
for (String value: entry.getValue()) {
b = b.header(name, value);
}
}
}
Object entity = requestEntity;
switch (verb) {
case GET:
jerseyResponse = b.get(ClientResponse.class);
break;
case POST:
jerseyResponse = b.post(ClientResponse.class, entity);
break;
case PUT:
jerseyResponse = b.put(ClientResponse.class, entity);
break;
case DELETE:
jerseyResponse = b.delete(ClientResponse.class);
break;
case HEAD:
jerseyResponse = b.head();
break;
case OPTIONS:
jerseyResponse = b.options(ClientResponse.class);
break;
default:
throw new ClientException(
ClientException.ErrorType.GENERAL,
"You have to one of the REST verbs such as GET, POST etc.");
}
thisResponse = new HttpClientResponse(jerseyResponse, uri, overriddenClientConfig);
if (thisResponse.getStatus() == 503){
thisResponse.close();
throw new ClientException(ClientException.ErrorType.SERVER_THROTTLED);
}
return thisResponse;
}
@Override
protected boolean isRetriableException(Throwable e) {
if (e instanceof ClientException
&& ((ClientException)e).getErrorType() == ClientException.ErrorType.SERVER_THROTTLED){
return false;
}
boolean shouldRetry = isConnectException(e) || isSocketException(e);
return shouldRetry;
}
@Override
protected boolean isCircuitBreakerException(Throwable e) {
if (e instanceof ClientException) {
ClientException clientException = (ClientException) e;
if (clientException.getErrorType() == ClientException.ErrorType.SERVER_THROTTLED) {
return true;
}
}
return isConnectException(e) || isSocketException(e);
}
private static boolean isSocketException(Throwable e) {
int levelCount = 0;
while (e != null && levelCount < 10) {
if ((e instanceof SocketException) || (e instanceof SocketTimeoutException)) {
return true;
}
e = e.getCause();
levelCount++;
}
return false;
}
private static boolean isConnectException(Throwable e) {
int levelCount = 0;
while (e != null && levelCount < 10) {
if ((e instanceof SocketException)
|| ((e instanceof org.apache.http.conn.ConnectTimeoutException)
&& !(e instanceof org.apache.http.conn.ConnectionPoolTimeoutException))) {
return true;
}
e = e.getCause();
levelCount++;
}
return false;
}
@Override
protected Pair deriveHostAndPortFromVipAddress(String vipAddress)
throws URISyntaxException, ClientException {
if (!vipAddress.contains("http")) {
vipAddress = "http://" + vipAddress;
}
return super.deriveHostAndPortFromVipAddress(vipAddress);
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
HttpRequest request, IClientConfig requestConfig) {
if (!request.isRetriable()) {
return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(), requestConfig);
}
if (this.ncc.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
if (request.getVerb() != HttpRequest.Verb.GET) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig);
} else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
}
public void shutdown() {
ILoadBalancer lb = this.getLoadBalancer();
if (lb instanceof BaseLoadBalancer) {
((BaseLoadBalancer) lb).shutdown();
}
NFHttpClientFactory.shutdownNFHttpClient(restClientName);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy