From d4fda5762b5ba5ecbdce0712a83edec95b426c6e Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Mon, 5 Jun 2017 19:49:48 -0500 Subject: [PATCH] Add support for OkHttp and Netty for HTTP connections. --- spring-credhub-core/pom.xml | 20 ++- .../ClientHttpRequestFactoryFactory.java | 130 +++++++++++++++++- .../ClientHttpRequestFactoryFactoryTests.java | 35 ++++- spring-credhub-dependencies/pom.xml | 24 ++++ 4 files changed, 204 insertions(+), 5 deletions(-) diff --git a/spring-credhub-core/pom.xml b/spring-credhub-core/pom.xml index dfcbb84..6b5b32e 100644 --- a/spring-credhub-core/pom.xml +++ b/spring-credhub-core/pom.xml @@ -39,7 +39,25 @@ httpclient true - + + + com.squareup.okhttp + okhttp + true + + + + com.squareup.okhttp3 + okhttp + true + + + + io.netty + netty-all + true + + org.springframework spring-test diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactory.java b/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactory.java index ccf5067..02e389b 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactory.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactory.java @@ -18,7 +18,15 @@ package org.springframework.credhub.configuration; import java.io.IOException; import java.security.GeneralSecurityException; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; + +import com.squareup.okhttp.OkHttpClient; +import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.JdkSslContext; +import io.netty.handler.ssl.SslContext; +import okhttp3.OkHttpClient.Builder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.client.config.RequestConfig; @@ -28,12 +36,13 @@ import org.apache.http.impl.client.HttpClients; import org.springframework.credhub.support.ClientOptions; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.Netty4ClientHttpRequestFactory; +import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; +import org.springframework.http.client.OkHttpClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import javax.net.ssl.SSLContext; - /** * Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components, * OkHttp, Netty and the JDK HTTP client (in that order). This factory configures a @@ -49,6 +58,18 @@ public class ClientHttpRequestFactoryFactory { "org.apache.http.client.HttpClient", ClientHttpRequestFactoryFactory.class.getClassLoader()); + private static final boolean OKHTTP_PRESENT = ClassUtils.isPresent( + "com.squareup.okhttp.OkHttpClient", + ClientHttpRequestFactoryFactory.class.getClassLoader()); + + private static final boolean OKHTTP3_PRESENT = ClassUtils.isPresent( + "okhttp3.OkHttpClient", + ClientHttpRequestFactoryFactory.class.getClassLoader()); + + private static final boolean NETTY_PRESENT = ClassUtils.isPresent( + "io.netty.channel.nio.NioEventLoopGroup", + ClientHttpRequestFactoryFactory.class.getClassLoader()); + /** * Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions}. * @@ -65,6 +86,21 @@ public class ClientHttpRequestFactoryFactory { logger.info("Using Apache HttpComponents HttpClient for HTTP connections"); return HttpComponents.usingHttpComponents(options); } + + if (OKHTTP3_PRESENT) { + logger.info("Using OkHttp3 for HTTP connections"); + return OkHttp3.usingOkHttp3(options); + } + + if (OKHTTP_PRESENT) { + logger.info("Using OkHttp for HTTP connections"); + return OkHttp.usingOkHttp(options); + } + + if (NETTY_PRESENT) { + logger.info("Using Netty for HTTP connections"); + return Netty.usingNetty(options); + } } catch (Exception e) { logger.warn("Exception caught while configuring HTTP connections", e); @@ -94,6 +130,9 @@ public class ClientHttpRequestFactoryFactory { /** * {@link ClientHttpRequestFactory} using Apache HttpComponents. + * + * @author Mark Paluch + * @author Scott Frederick */ static class HttpComponents { static ClientHttpRequestFactory usingHttpComponents(ClientOptions options) @@ -118,4 +157,91 @@ public class ClientHttpRequestFactoryFactory { return new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build()); } } + + /** + * {@link ClientHttpRequestFactory} using {@link OkHttpClient}. + * + * @author Mark Paluch + * @author Scott Frederick + */ + static class OkHttp { + static ClientHttpRequestFactory usingOkHttp(ClientOptions options) + throws IOException, GeneralSecurityException { + + final OkHttpClient okHttpClient = new OkHttpClient(); + okHttpClient.setSslSocketFactory(SSLContext.getDefault().getSocketFactory()); + + OkHttpClientHttpRequestFactory requestFactory = + new OkHttpClientHttpRequestFactory(okHttpClient) { + @Override + public void destroy() throws IOException { + if (okHttpClient.getCache() != null) { + okHttpClient.getCache().close(); + } + + okHttpClient.getDispatcher().getExecutorService().shutdown(); + } + }; + + if (options.getConnectionTimeout() != null) { + requestFactory.setConnectTimeout(options.getConnectionTimeout()); + } + if (options.getReadTimeout() != null) { + requestFactory.setReadTimeout(options.getReadTimeout()); + } + + return requestFactory; + } + } + + /** + * {@link ClientHttpRequestFactory} using {@link OkHttpClient}. + * + * @author Mark Paluch + * @author Scott Frederick + */ + static class OkHttp3 { + static ClientHttpRequestFactory usingOkHttp3(ClientOptions options) + throws IOException, GeneralSecurityException { + + Builder builder = new Builder() + .sslSocketFactory(SSLContext.getDefault().getSocketFactory()); + + if (options.getConnectionTimeout() != null) { + builder.connectTimeout(options.getConnectionTimeout(), TimeUnit.MILLISECONDS); + } + if (options.getReadTimeout() != null) { + builder.readTimeout(options.getReadTimeout(), TimeUnit.MILLISECONDS); + } + + return new OkHttp3ClientHttpRequestFactory(builder.build()); + } + } + + /** + * {@link ClientHttpRequestFactory} using Netty. + * + * @author Mark Paluch + * @author Scott Frederick + */ + static class Netty { + + static ClientHttpRequestFactory usingNetty(ClientOptions options) + throws IOException, GeneralSecurityException { + + SslContext sslContext = new JdkSslContext(SSLContext.getDefault(), true, ClientAuth.REQUIRE); + + final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory(); + requestFactory.setSslContext(sslContext); + + if (options.getConnectionTimeout() != null) { + requestFactory.setConnectTimeout(options.getConnectionTimeout()); + } + if (options.getReadTimeout() != null) { + requestFactory.setReadTimeout(options.getReadTimeout()); + } + + return requestFactory; + } + } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactoryTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactoryTests.java index b67dbdd..5ebc3e4 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactoryTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/configuration/ClientHttpRequestFactoryFactoryTests.java @@ -24,15 +24,20 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.credhub.support.ClientOptions; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.Netty4ClientHttpRequestFactory; +import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; +import org.springframework.http.client.OkHttpClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertThat; import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.HttpComponents.usingHttpComponents; import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.HttpURLConnection.usingJdk; +import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.Netty.usingNetty; +import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.OkHttp.usingOkHttp; +import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.OkHttp3.usingOkHttp3; public class ClientHttpRequestFactoryFactoryTests { - @Test public void jdkDefaultClientCreated() throws Exception { ClientHttpRequestFactory factory = usingJdk(new ClientOptions()); @@ -42,7 +47,6 @@ public class ClientHttpRequestFactoryFactoryTests { @Test public void httpComponentsClientCreated() throws Exception { - ClientHttpRequestFactory factory = usingHttpComponents(new ClientOptions()); assertThat(factory, instanceOf(HttpComponentsClientHttpRequestFactory.class)); @@ -53,4 +57,31 @@ public class ClientHttpRequestFactoryFactoryTests { ((DisposableBean) factory).destroy(); } + + @Test + public void okHttpClientCreated() throws Exception { + ClientHttpRequestFactory factory = usingOkHttp(new ClientOptions()); + + assertThat(factory, instanceOf(OkHttpClientHttpRequestFactory.class)); + + ((DisposableBean) factory).destroy(); + } + + @Test + public void okHttp3ClientCreated() throws Exception { + ClientHttpRequestFactory factory = usingOkHttp3(new ClientOptions()); + + assertThat(factory, instanceOf(OkHttp3ClientHttpRequestFactory.class)); + + ((DisposableBean) factory).destroy(); + } + + @Test + public void nettyClientCreated() throws Exception { + ClientHttpRequestFactory factory = usingNetty(new ClientOptions()); + + assertThat(factory, instanceOf(Netty4ClientHttpRequestFactory.class)); + + ((DisposableBean) factory).destroy(); + } } \ No newline at end of file diff --git a/spring-credhub-dependencies/pom.xml b/spring-credhub-dependencies/pom.xml index c8ad599..afb12a4 100644 --- a/spring-credhub-dependencies/pom.xml +++ b/spring-credhub-dependencies/pom.xml @@ -55,6 +55,9 @@ 2.8.7 4.5.3 + 2.7.5 + 3.6.0 + 4.1.8.Final @@ -87,6 +90,27 @@ + + + com.squareup.okhttp + okhttp + ${okhttp.version} + true + + + + com.squareup.okhttp3 + okhttp + ${okhttp3.version} + true + + + + io.netty + netty-all + ${netty.version} + true +