Skip to content

Commit 1b6103b

Browse files
author
Ryan Baxter
authored
Allows for custom Http Client builders (spring-projects#313)
1 parent 13237ee commit 1b6103b

File tree

9 files changed

+183
-10
lines changed

9 files changed

+183
-10
lines changed

docs/src/main/asciidoc/spring-cloud-commons.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,8 @@ if the OK HTTP jar is on the classpath. In addition, Spring Cloud Commons provi
612612
the connection managers used by both clients, `ApacheHttpClientConnectionManagerFactory` for the Apache
613613
HTTP client and `OkHttpClientConnectionPoolFactory` for the OK HTTP client. You can provide
614614
your own implementation of these beans if you would like to customize how the HTTP clients are created
615-
in downstream projects. You can also disable the creation of these beans by setting
615+
in downstream projects. In addition, if you provide a bean of type `HttpClientBuilder` and/or `OkHttpClient.Builder`,
616+
the default factories will use these builders as the basis for the builders returned to downstream projects.
617+
You can also disable the creation of these beans by setting
616618
`spring.cloud.httpclientfactories.apache.enabled` or `spring.cloud.httpclientfactories.ok.enabled` to
617619
`false`.

spring-cloud-commons/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666

6767
<properties>
6868
<okhttp3.version>3.6.0</okhttp3.version>
69-
<apachehttpclient.version>4.5.1</apachehttpclient.version>
69+
<apachehttpclient.version>4.5.4</apachehttpclient.version>
7070
</properties>
7171
<dependencies>
7272
<dependency>

spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactory.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@
88
*/
99
public class DefaultApacheHttpClientFactory implements ApacheHttpClientFactory {
1010

11+
private HttpClientBuilder builder;
12+
13+
public DefaultApacheHttpClientFactory(HttpClientBuilder builder) {
14+
this.builder = builder;
15+
}
16+
1117
/**
1218
* A default {@link HttpClientBuilder}. The {@link HttpClientBuilder} returned will
1319
* have content compression disabled, cookie management disabled, and use system properties.
1420
*/
1521
@Override
1622
public HttpClientBuilder createBuilder() {
17-
return HttpClientBuilder.create().disableContentCompression()
23+
return this.builder.disableContentCompression()
1824
.disableCookieManagement().useSystemProperties();
1925
}
2026
}

spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactory.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@ public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
1919

2020
private static final Log LOG = LogFactory.getLog(DefaultOkHttpClientFactory.class);
2121

22+
private OkHttpClient.Builder builder;
23+
24+
public DefaultOkHttpClientFactory(OkHttpClient.Builder builder) {
25+
this.builder = builder;
26+
}
27+
2228
@Override
2329
public OkHttpClient.Builder createBuilder(boolean disableSslValidation) {
24-
OkHttpClient.Builder builder = new OkHttpClient.Builder();
2530
if (disableSslValidation) {
2631
try {
2732
X509TrustManager disabledTrustManager = new DisableValidationTrustManager();

spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/HttpClientConfiguration.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import okhttp3.OkHttpClient;
44

5+
import org.apache.http.impl.client.HttpClientBuilder;
56
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
67
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
78
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -26,8 +27,14 @@ public ApacheHttpClientConnectionManagerFactory connManFactory() {
2627

2728
@Bean
2829
@ConditionalOnMissingBean
29-
public ApacheHttpClientFactory apacheHttpClientFactory() {
30-
return new DefaultApacheHttpClientFactory();
30+
public HttpClientBuilder apacheHttpClientBuilder() {
31+
return HttpClientBuilder.create();
32+
}
33+
34+
@Bean
35+
@ConditionalOnMissingBean
36+
public ApacheHttpClientFactory apacheHttpClientFactory(HttpClientBuilder builder) {
37+
return new DefaultApacheHttpClientFactory(builder);
3138
}
3239
}
3340

@@ -44,8 +51,14 @@ public OkHttpClientConnectionPoolFactory connPoolFactory() {
4451

4552
@Bean
4653
@ConditionalOnMissingBean
47-
public OkHttpClientFactory okHttpClientFactory() {
48-
return new DefaultOkHttpClientFactory();
54+
public OkHttpClient.Builder okHttpClientBuilder() {
55+
return new OkHttpClient.Builder();
56+
}
57+
58+
@Bean
59+
@ConditionalOnMissingBean
60+
public OkHttpClientFactory okHttpClientFactory(OkHttpClient.Builder builder) {
61+
return new DefaultOkHttpClientFactory(builder);
4962
}
5063
}
5164
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2013-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.cloud.commons.httpclient;
17+
18+
import org.apache.http.impl.client.HttpClientBuilder;
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.boot.SpringApplication;
23+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
24+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
25+
import org.springframework.boot.test.context.SpringBootTest;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.test.context.junit4.SpringRunner;
29+
30+
import static org.junit.Assert.assertTrue;
31+
32+
/**
33+
* @author Ryan Baxter
34+
*/
35+
@RunWith(SpringRunner.class)
36+
@SpringBootTest(classes = CustomHttpClientBuilderApplication.class)
37+
public class CustomHttpClientBuilderConfigurationTests {
38+
39+
@Autowired
40+
ApacheHttpClientFactory apacheHttpClientFactory;
41+
42+
@Test
43+
public void testCustomBuilder() {
44+
HttpClientBuilder builder = apacheHttpClientFactory.createBuilder();
45+
assertTrue(CustomHttpClientBuilderApplication.MyHttpClientBuilder.class.isInstance(builder));
46+
}
47+
}
48+
49+
@Configuration
50+
@EnableAutoConfiguration
51+
class CustomHttpClientBuilderApplication {
52+
53+
public static void main(String[] args) {
54+
SpringApplication.run(MyApplication.class, args);
55+
}
56+
57+
@Configuration
58+
@AutoConfigureBefore(value = HttpClientConfiguration.class)
59+
static class MyConfig {
60+
61+
@Bean
62+
public MyHttpClientBuilder builder() {
63+
return new MyHttpClientBuilder();
64+
}
65+
66+
}
67+
68+
static class MyHttpClientBuilder extends HttpClientBuilder {
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2013-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.cloud.commons.httpclient;
17+
18+
import okhttp3.OkHttpClient;
19+
20+
import java.lang.reflect.Field;
21+
import java.util.concurrent.TimeUnit;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.SpringApplication;
26+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
27+
import org.springframework.boot.test.context.SpringBootTest;
28+
import org.springframework.context.annotation.Bean;
29+
import org.springframework.context.annotation.Configuration;
30+
import org.springframework.test.context.junit4.SpringRunner;
31+
import org.springframework.util.ReflectionUtils;
32+
33+
import static org.junit.Assert.assertEquals;
34+
35+
/**
36+
* @author Ryan Baxter
37+
*/
38+
@RunWith(SpringRunner.class)
39+
@SpringBootTest(classes = CustomOkHttpClientBuilderApplication.class)
40+
public class CustomOkHttpClientBuilderConfigurationTests {
41+
42+
@Autowired
43+
private OkHttpClientFactory okHttpClientFactory;
44+
45+
@Test
46+
public void testCustomBuilder() {
47+
OkHttpClient.Builder builder = okHttpClientFactory.createBuilder(false);
48+
Integer timeout = getField(builder, "connectTimeout");
49+
assertEquals(1, timeout.intValue());
50+
}
51+
52+
protected <T> T getField(Object target, String name) {
53+
Field field = ReflectionUtils.findField(target.getClass(), name);
54+
ReflectionUtils.makeAccessible(field);
55+
Object value = ReflectionUtils.getField(field, target);
56+
return (T) value;
57+
}
58+
59+
}
60+
61+
@Configuration
62+
@EnableAutoConfiguration
63+
class CustomOkHttpClientBuilderApplication {
64+
65+
public static void main(String[] args) {
66+
SpringApplication.run(MyApplication.class, args);
67+
}
68+
69+
@Configuration
70+
static class MyConfig {
71+
72+
@Bean
73+
public OkHttpClient.Builder builder() {
74+
return new OkHttpClient.Builder().connectTimeout(1, TimeUnit.MILLISECONDS);
75+
}
76+
}
77+
}

spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactoryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class DefaultApacheHttpClientFactoryTests {
2222
public void createClient() throws Exception {
2323
final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100)
2424
.setConnectTimeout(200).setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
25-
CloseableHttpClient httpClient = new DefaultApacheHttpClientFactory().createBuilder().
25+
CloseableHttpClient httpClient = new DefaultApacheHttpClientFactory(HttpClientBuilder.create()).createBuilder().
2626
setConnectionManager(mock(HttpClientConnectionManager.class)).
2727
setDefaultRequestConfig(requestConfig).build();
2828
Assertions.assertThat(httpClient).isInstanceOf(Configurable.class);

spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactoryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
public class DefaultOkHttpClientFactoryTest {
1919
@Test
2020
public void create() throws Exception {
21-
DefaultOkHttpClientFactory okHttpClientFactory = new DefaultOkHttpClientFactory();
21+
DefaultOkHttpClientFactory okHttpClientFactory = new DefaultOkHttpClientFactory(new OkHttpClient.Builder());
2222
DefaultOkHttpClientConnectionPoolFactory poolFactory = new DefaultOkHttpClientConnectionPoolFactory();
2323
ConnectionPool pool = poolFactory.create(4, 5, TimeUnit.DAYS);
2424
OkHttpClient httpClient = okHttpClientFactory.createBuilder(true).

0 commit comments

Comments
 (0)