Add support for OkHttp and Netty for HTTP connections.

This commit is contained in:
Scott Frederick
2017-06-05 19:49:48 -05:00
parent 5419dff5eb
commit d4fda5762b
4 changed files with 204 additions and 5 deletions

View File

@@ -39,7 +39,25 @@
<artifactId>httpclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -55,6 +55,9 @@
<properties>
<jackson.version>2.8.7</jackson.version>
<httpclient.version>4.5.3</httpclient.version>
<okhttp.version>2.7.5</okhttp.version>
<okhttp3.version>3.6.0</okhttp3.version>
<netty.version>4.1.8.Final</netty.version>
</properties>
<dependencyManagement>
@@ -87,6 +90,27 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp3.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>