23
23
import java .util .List ;
24
24
import java .util .concurrent .TimeUnit ;
25
25
import java .util .function .Consumer ;
26
+ import java .util .function .Function ;
26
27
27
28
import org .apache .hc .client5 .http .classic .HttpClient ;
28
29
import org .apache .hc .client5 .http .impl .DefaultRedirectStrategy ;
32
33
import org .apache .hc .client5 .http .protocol .RedirectStrategy ;
33
34
import org .apache .hc .client5 .http .ssl .DefaultClientTlsStrategy ;
34
35
import org .apache .hc .client5 .http .ssl .DefaultHostnameVerifier ;
36
+ import org .apache .hc .client5 .http .ssl .TlsSocketStrategy ;
35
37
import org .apache .hc .core5 .http .HttpRequest ;
36
38
import org .apache .hc .core5 .http .HttpResponse ;
37
39
import org .apache .hc .core5 .http .io .SocketConfig ;
42
44
import org .springframework .boot .ssl .SslBundle ;
43
45
import org .springframework .boot .ssl .SslOptions ;
44
46
import org .springframework .http .client .HttpComponentsClientHttpRequestFactory ;
47
+ import org .springframework .util .Assert ;
45
48
import org .springframework .util .ClassUtils ;
46
49
47
50
/**
55
58
public final class HttpComponentsClientHttpRequestFactoryBuilder
56
59
extends AbstractClientHttpRequestFactoryBuilder <HttpComponentsClientHttpRequestFactory > {
57
60
61
+ private final Consumer <HttpClientBuilder > httpClientCustomizer ;
62
+
63
+ private final Consumer <PoolingHttpClientConnectionManagerBuilder > connectionManagerCustomizer ;
64
+
65
+ private final Consumer <SocketConfig .Builder > socketConfigCustomizer ;
66
+
67
+ private final Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ;
68
+
58
69
HttpComponentsClientHttpRequestFactoryBuilder () {
59
- this (Collections .emptyList ());
70
+ this (Collections .emptyList (), emptyCustomizer (), emptyCustomizer (), emptyCustomizer (),
71
+ HttpComponentsClientHttpRequestFactoryBuilder ::createTlsSocketStrategy );
60
72
}
61
73
62
74
private HttpComponentsClientHttpRequestFactoryBuilder (
63
- List <Consumer <HttpComponentsClientHttpRequestFactory >> customizers ) {
75
+ List <Consumer <HttpComponentsClientHttpRequestFactory >> customizers ,
76
+ Consumer <HttpClientBuilder > httpClientCustomizer ,
77
+ Consumer <PoolingHttpClientConnectionManagerBuilder > connectionManagerCustomizer ,
78
+ Consumer <SocketConfig .Builder > socketConfigCustomizer ,
79
+ Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ) {
64
80
super (customizers );
81
+ this .httpClientCustomizer = httpClientCustomizer ;
82
+ this .connectionManagerCustomizer = connectionManagerCustomizer ;
83
+ this .socketConfigCustomizer = socketConfigCustomizer ;
84
+ this .tlsSocketStrategyFactory = tlsSocketStrategyFactory ;
65
85
}
66
86
67
87
@ Override
68
88
public HttpComponentsClientHttpRequestFactoryBuilder withCustomizer (
69
89
Consumer <HttpComponentsClientHttpRequestFactory > customizer ) {
70
- return new HttpComponentsClientHttpRequestFactoryBuilder (mergedCustomizers (customizer ));
90
+ return new HttpComponentsClientHttpRequestFactoryBuilder (mergedCustomizers (customizer ),
91
+ this .httpClientCustomizer , this .connectionManagerCustomizer , this .socketConfigCustomizer ,
92
+ this .tlsSocketStrategyFactory );
71
93
}
72
94
73
95
@ Override
74
96
public HttpComponentsClientHttpRequestFactoryBuilder withCustomizers (
75
97
Collection <Consumer <HttpComponentsClientHttpRequestFactory >> customizers ) {
76
- return new HttpComponentsClientHttpRequestFactoryBuilder (mergedCustomizers (customizers ));
98
+ return new HttpComponentsClientHttpRequestFactoryBuilder (mergedCustomizers (customizers ),
99
+ this .httpClientCustomizer , this .connectionManagerCustomizer , this .socketConfigCustomizer ,
100
+ this .tlsSocketStrategyFactory );
101
+ }
102
+
103
+ /**
104
+ * Return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} that applies
105
+ * additional customization to the underlying {@link HttpClientBuilder}.
106
+ * @param httpClientCustomizer the customizer to apply
107
+ * @return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} instance
108
+ */
109
+ public HttpComponentsClientHttpRequestFactoryBuilder withHttpClientCustomizer (
110
+ Consumer <HttpClientBuilder > httpClientCustomizer ) {
111
+ Assert .notNull (httpClientCustomizer , "'httpClientCustomizer' must not be null" );
112
+ return new HttpComponentsClientHttpRequestFactoryBuilder (getCustomizers (),
113
+ this .httpClientCustomizer .andThen (httpClientCustomizer ), this .connectionManagerCustomizer ,
114
+ this .socketConfigCustomizer , this .tlsSocketStrategyFactory );
115
+ }
116
+
117
+ /**
118
+ * Return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} that applies
119
+ * additional customization to the underlying
120
+ * {@link PoolingHttpClientConnectionManagerBuilder}.
121
+ * @param connectionManagerCustomizer the customizer to apply
122
+ * @return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} instance
123
+ */
124
+ public HttpComponentsClientHttpRequestFactoryBuilder withConnectionManagerCustomizer (
125
+ Consumer <PoolingHttpClientConnectionManagerBuilder > connectionManagerCustomizer ) {
126
+ Assert .notNull (connectionManagerCustomizer , "'connectionManagerCustomizer' must not be null" );
127
+ return new HttpComponentsClientHttpRequestFactoryBuilder (getCustomizers (), this .httpClientCustomizer ,
128
+ this .connectionManagerCustomizer .andThen (connectionManagerCustomizer ), this .socketConfigCustomizer ,
129
+ this .tlsSocketStrategyFactory );
130
+ }
131
+
132
+ /**
133
+ * Return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} that applies
134
+ * additional customization to the underlying
135
+ * {@link org.apache.hc.core5.http.io.SocketConfig.Builder}.
136
+ * @param socketConfigCustomizer the customizer to apply
137
+ * @return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} instance
138
+ */
139
+ public HttpComponentsClientHttpRequestFactoryBuilder withSocketConfigCustomizer (
140
+ Consumer <SocketConfig .Builder > socketConfigCustomizer ) {
141
+ Assert .notNull (socketConfigCustomizer , "'socketConfigCustomizer' must not be null" );
142
+ return new HttpComponentsClientHttpRequestFactoryBuilder (getCustomizers (), this .httpClientCustomizer ,
143
+ this .connectionManagerCustomizer , this .socketConfigCustomizer .andThen (socketConfigCustomizer ),
144
+ this .tlsSocketStrategyFactory );
145
+ }
146
+
147
+ /**
148
+ * Return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} with a
149
+ * replacement {@link TlsSocketStrategy} factory.
150
+ * @param tlsSocketStrategyFactory the new factory used to create a
151
+ * {@link TlsSocketStrategy} for a given {@link SslBundle}
152
+ * @return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} instance
153
+ */
154
+ public HttpComponentsClientHttpRequestFactoryBuilder withTlsSocketStrategyFactory (
155
+ Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ) {
156
+ Assert .notNull (tlsSocketStrategyFactory , "'tlsSocketStrategyFactory' must not be null" );
157
+ return new HttpComponentsClientHttpRequestFactoryBuilder (getCustomizers (), this .httpClientCustomizer ,
158
+ this .connectionManagerCustomizer , this .socketConfigCustomizer , tlsSocketStrategyFactory );
77
159
}
78
160
79
161
@ Override
@@ -87,11 +169,12 @@ protected HttpComponentsClientHttpRequestFactory createClientHttpRequestFactory(
87
169
}
88
170
89
171
private HttpClient createHttpClient (ClientHttpRequestFactorySettings settings ) {
90
- return HttpClientBuilder .create ()
172
+ HttpClientBuilder builder = HttpClientBuilder .create ()
91
173
.useSystemProperties ()
92
174
.setRedirectStrategy (asRedirectStrategy (settings .redirects ()))
93
- .setConnectionManager (createConnectionManager (settings ))
94
- .build ();
175
+ .setConnectionManager (createConnectionManager (settings ));
176
+ this .httpClientCustomizer .accept (builder );
177
+ return builder .build ();
95
178
}
96
179
97
180
private RedirectStrategy asRedirectStrategy (Redirects redirects ) {
@@ -102,23 +185,31 @@ private RedirectStrategy asRedirectStrategy(Redirects redirects) {
102
185
}
103
186
104
187
private PoolingHttpClientConnectionManager createConnectionManager (ClientHttpRequestFactorySettings settings ) {
105
- PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder .create ();
188
+ PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder .create ()
189
+ .useSystemProperties ();
190
+ PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
191
+ builder .setDefaultSocketConfig (createSocketConfig (settings ));
192
+ map .from (settings ::sslBundle ).as (this .tlsSocketStrategyFactory ).to (builder ::setTlsSocketStrategy );
193
+ this .connectionManagerCustomizer .accept (builder );
194
+ return builder .build ();
195
+ }
196
+
197
+ private SocketConfig createSocketConfig (ClientHttpRequestFactorySettings settings ) {
198
+ SocketConfig .Builder builder = SocketConfig .custom ();
106
199
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
107
- map .from (settings ::readTimeout ).as (this ::createSocketConfig ).to (builder ::setDefaultSocketConfig );
108
- map .from (settings ::sslBundle ).as (this ::createTlsSocketStrategy ).to (builder ::setTlsSocketStrategy );
109
- return builder .useSystemProperties ().build ();
200
+ map .from (settings ::readTimeout )
201
+ .asInt (Duration ::toMillis )
202
+ .to ((timeout ) -> builder .setSoTimeout (timeout , TimeUnit .MILLISECONDS ));
203
+ this .socketConfigCustomizer .accept (builder );
204
+ return builder .build ();
110
205
}
111
206
112
- private DefaultClientTlsStrategy createTlsSocketStrategy (SslBundle sslBundle ) {
207
+ private static TlsSocketStrategy createTlsSocketStrategy (SslBundle sslBundle ) {
113
208
SslOptions options = sslBundle .getOptions ();
114
209
return new DefaultClientTlsStrategy (sslBundle .createSslContext (), options .getEnabledProtocols (),
115
210
options .getCiphers (), null , new DefaultHostnameVerifier ());
116
211
}
117
212
118
- private SocketConfig createSocketConfig (Duration readTimeout ) {
119
- return SocketConfig .custom ().setSoTimeout ((int ) readTimeout .toMillis (), TimeUnit .MILLISECONDS ).build ();
120
- }
121
-
122
213
/**
123
214
* {@link RedirectStrategy} that never follows redirects.
124
215
*/
0 commit comments