OK HTTP client factory implementations
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link OkHttpClientConnectionPoolFactory}.
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientConnectionPoolFactory implements OkHttpClientConnectionPoolFactory {
|
||||
|
||||
@Override
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
|
||||
return new ConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link OkHttpClientFactory}.
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(DefaultOkHttpClientFactory.class);
|
||||
|
||||
@Override
|
||||
public OkHttpClient create(boolean disableSslValidation, long connectTimeout,
|
||||
TimeUnit connectTimeoutUnit, boolean followRedirects, long readTimeout,
|
||||
TimeUnit readTimeoutUnit, ConnectionPool connectionPool,
|
||||
SSLSocketFactory sslSocketFactory, X509TrustManager x509TrustManager) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout(connectTimeout, connectTimeoutUnit)
|
||||
.followRedirects(followRedirects)
|
||||
.readTimeout(readTimeout, readTimeoutUnit).connectionPool(connectionPool)
|
||||
.connectionPool(connectionPool);
|
||||
if (disableSslValidation) {
|
||||
try {
|
||||
X509TrustManager disabledTrustManager = new DisableValidationTrustManager();
|
||||
TrustManager[] trustManagers = new TrustManager[1];
|
||||
trustManagers[0] = disabledTrustManager;
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustManagers, new java.security.SecureRandom());
|
||||
SSLSocketFactory disabledSSLSocketFactory = sslContext.getSocketFactory();
|
||||
builder.sslSocketFactory(disabledSSLSocketFactory, disabledTrustManager);
|
||||
builder.hostnameVerifier(new TrustAllHostnames());
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
|
||||
}
|
||||
catch (KeyManagementException e) {
|
||||
LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
|
||||
}
|
||||
}
|
||||
if (sslSocketFactory != null && x509TrustManager != null) {
|
||||
builder.sslSocketFactory(sslSocketFactory, x509TrustManager);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -27,4 +30,22 @@ public class HttpClientConfiguration {
|
||||
return new DefaultApacheHttpClientFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "spring.cloud.httpclient.ok.enabled")
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
static class OkHttpClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public OkHttpClientConnectionPoolFactory connPoolFactory() {
|
||||
return new DefaultOkHttpClientConnectionPoolFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public OkHttpClientFactory okHttpClientFactory() {
|
||||
return new DefaultOkHttpClientFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Creates {@link ConnectionPool}s for {@link okhttp3.OkHttpClient}s
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface OkHttpClientConnectionPoolFactory {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConnectionPool}.
|
||||
* @param maxIdleConnections number of max idle connections to allow
|
||||
* @param keepAliveDuration amount of time to keep connections alive
|
||||
* @param timeUnit the time unit for the keep alive duration
|
||||
* @return A new {@link ConnectionPool}
|
||||
*/
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* Creates new {@link OkHttpClient}s.
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface OkHttpClientFactory {
|
||||
|
||||
/**
|
||||
* Creates a new {@link OkHttpClient}.
|
||||
* @param disableSslValidation To disable SSL validation
|
||||
* @param connectTimeout Connection timeout duration
|
||||
* @param connectTimeoutUnit Connection timeout time unit
|
||||
* @param followRedirects Whether to follow redirects
|
||||
* @param readTimeout Read timeout duration
|
||||
* @param readTimeoutUnit Read timeout time unit
|
||||
* @param connectionPool The connection pool to use
|
||||
* @param sslSocketFactory The socket factory to use, can be {@code null}
|
||||
* @param x509TrustManager The trust manager to use, can be {@code null}
|
||||
* @return A new {@link OkHttpClient}
|
||||
*/
|
||||
public OkHttpClient create(boolean disableSslValidation, long connectTimeout,
|
||||
TimeUnit connectTimeoutUnit, boolean followRedirects, long readTimeout,
|
||||
TimeUnit readTimeoutUnit, ConnectionPool connectionPool,
|
||||
SSLSocketFactory sslSocketFactory, X509TrustManager x509TrustManager);
|
||||
|
||||
/**
|
||||
* A {@link X509TrustManager} that does not validate SSL certificates.
|
||||
*/
|
||||
public static class DisableValidationTrustManager implements 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 new X509Certificate[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link HostnameVerifier} that does not validate any hostnames.
|
||||
*/
|
||||
public static class TrustAllHostnames implements HostnameVerifier {
|
||||
|
||||
@Override
|
||||
public boolean verify(String s, SSLSession sslSession) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
@@ -21,7 +26,7 @@ import static org.junit.Assert.assertTrue;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = CustomApplication.class)
|
||||
@SpringBootTest(classes = CustomApplication.class, properties = {"spring.cloud.httpclient.ok.enabled: true"})
|
||||
public class CustomHttpClientConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
@@ -30,6 +35,12 @@ public class CustomHttpClientConfigurationTests {
|
||||
@Autowired
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
|
||||
|
||||
@Autowired
|
||||
OkHttpClientFactory okHttpClientFactory;
|
||||
|
||||
@Autowired
|
||||
OkHttpClientConnectionPoolFactory okHttpClientConnectionPoolFactory;
|
||||
|
||||
@Test
|
||||
public void connManFactory() throws Exception {
|
||||
assertTrue(ApacheHttpClientConnectionManagerFactory.class
|
||||
@@ -45,6 +56,18 @@ public class CustomHttpClientConfigurationTests {
|
||||
.isInstance(httpClientFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionPoolFactory() throws Exception {
|
||||
assertTrue(OkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
|
||||
assertTrue(CustomApplication.MyOkHttpConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void okHttpClientFactory() throws Exception {
|
||||
assertTrue(OkHttpClientFactory.class.isInstance(okHttpClientFactory));
|
||||
assertTrue(CustomApplication.MyOkHttpClientFactory.class.isInstance(okHttpClientFactory));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -64,10 +87,20 @@ class CustomApplication {
|
||||
}
|
||||
|
||||
@Bean
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory() {
|
||||
public ApacheHttpClientConnectionManagerFactory connectionManagerFactory() {
|
||||
return new MyApacheHttpClientConnectionManagerFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OkHttpClientConnectionPoolFactory connectionPoolFactory() {
|
||||
return new MyOkHttpConnectionPoolFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OkHttpClientFactory okHttpClientFactory() {
|
||||
return new MyOkHttpClientFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyApacheHttpClientFactory implements ApacheHttpClientFactory {
|
||||
@@ -90,4 +123,23 @@ class CustomApplication {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyOkHttpClientFactory implements OkHttpClientFactory {
|
||||
|
||||
@Override
|
||||
public OkHttpClient create(boolean disableSslValidation, long connectTimeout,
|
||||
TimeUnit connectTimeoutUnit, boolean followRedirects, long readTimeout,
|
||||
TimeUnit readTimeoutUnit, ConnectionPool connectionPool,
|
||||
SSLSocketFactory sslSocketFactory, X509TrustManager x509TrustManager) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyOkHttpConnectionPoolFactory implements OkHttpClientConnectionPoolFactory {
|
||||
|
||||
@Override
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import static org.junit.Assert.*;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = MyApplication.class)
|
||||
@SpringBootTest(classes = MyApplication.class, properties = {"spring.cloud.httpclient.ok.enabled: true"})
|
||||
public class DefaultHttpClientConfigurationTests {
|
||||
@Autowired
|
||||
ApacheHttpClientFactory httpClientFactory;
|
||||
@@ -23,6 +23,12 @@ public class DefaultHttpClientConfigurationTests {
|
||||
@Autowired
|
||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
|
||||
|
||||
@Autowired
|
||||
OkHttpClientFactory okHttpClientFactory;
|
||||
|
||||
@Autowired
|
||||
OkHttpClientConnectionPoolFactory okHttpClientConnectionPoolFactory;
|
||||
|
||||
@Test
|
||||
public void connManFactory() throws Exception {
|
||||
assertTrue(ApacheHttpClientConnectionManagerFactory.class
|
||||
@@ -36,6 +42,18 @@ public class DefaultHttpClientConfigurationTests {
|
||||
assertTrue(ApacheHttpClientFactory.class.isInstance(httpClientFactory));
|
||||
assertTrue(DefaultApacheHttpClientFactory.class.isInstance(httpClientFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connPoolFactory() throws Exception {
|
||||
assertTrue(OkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
|
||||
assertTrue(DefaultOkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOkHttpClientFactory() throws Exception {
|
||||
assertTrue(OkHttpClientFactory.class.isInstance(okHttpClientFactory));
|
||||
assertTrue(DefaultOkHttpClientFactory.class.isInstance(okHttpClientFactory));
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientConnectionPoolFactoryTest {
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
DefaultOkHttpClientConnectionPoolFactory connectionPoolFactory = new DefaultOkHttpClientConnectionPoolFactory();
|
||||
ConnectionPool connectionPool = connectionPoolFactory.create(2,
|
||||
3, TimeUnit.MILLISECONDS);
|
||||
int idleConnections = getField(connectionPool, "maxIdleConnections");
|
||||
long keepAliveDuration = getField(connectionPool, "keepAliveDurationNs");
|
||||
assertEquals(2, idleConnections);
|
||||
assertEquals(TimeUnit.MILLISECONDS.toNanos(3), keepAliveDuration);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientFactoryTest {
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
DefaultOkHttpClientFactory okHttpClientFactory = new DefaultOkHttpClientFactory();
|
||||
DefaultOkHttpClientConnectionPoolFactory poolFactory = new DefaultOkHttpClientConnectionPoolFactory();
|
||||
ConnectionPool pool = poolFactory.create(4, 5, TimeUnit.DAYS);
|
||||
OkHttpClient httpClient = okHttpClientFactory.create(true, 2,
|
||||
TimeUnit.MILLISECONDS, true, 3, TimeUnit.HOURS, pool, null, null);
|
||||
int connectTimeout = getField(httpClient, "connectTimeout");
|
||||
assertEquals(2, connectTimeout);
|
||||
int readTimeout = getField(httpClient, "readTimeout");
|
||||
assertEquals(TimeUnit.HOURS.toMillis(3), readTimeout);
|
||||
boolean followRedirects = getField(httpClient, "followRedirects");
|
||||
assertTrue(followRedirects);
|
||||
ConnectionPool poolFromClient = getField(httpClient, "connectionPool");
|
||||
assertEquals(pool, poolFromClient);
|
||||
HostnameVerifier hostnameVerifier = getField(httpClient, "hostnameVerifier");
|
||||
assertTrue(OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user