23
23
import java .util .concurrent .TimeUnit ;
24
24
import java .util .function .Supplier ;
25
25
26
+ import javax .net .ssl .SSLSocketFactory ;
27
+ import javax .net .ssl .TrustManager ;
28
+ import javax .net .ssl .X509TrustManager ;
29
+
30
+ import okhttp3 .OkHttpClient ;
26
31
import org .apache .hc .client5 .http .classic .HttpClient ;
27
32
import org .apache .hc .client5 .http .impl .classic .HttpClientBuilder ;
28
33
import org .apache .hc .client5 .http .impl .io .PoolingHttpClientConnectionManager ;
29
34
import org .apache .hc .client5 .http .impl .io .PoolingHttpClientConnectionManagerBuilder ;
35
+ import org .apache .hc .client5 .http .ssl .DefaultHostnameVerifier ;
36
+ import org .apache .hc .client5 .http .ssl .SSLConnectionSocketFactory ;
30
37
import org .apache .hc .core5 .http .io .SocketConfig ;
31
38
32
39
import org .springframework .boot .context .properties .PropertyMapper ;
40
+ import org .springframework .boot .ssl .SslBundle ;
41
+ import org .springframework .boot .ssl .SslOptions ;
33
42
import org .springframework .http .client .AbstractClientHttpRequestFactoryWrapper ;
34
43
import org .springframework .http .client .ClientHttpRequestFactory ;
35
44
import org .springframework .http .client .HttpComponentsClientHttpRequestFactory ;
36
45
import org .springframework .http .client .OkHttp3ClientHttpRequestFactory ;
37
46
import org .springframework .http .client .SimpleClientHttpRequestFactory ;
38
47
import org .springframework .util .Assert ;
39
48
import org .springframework .util .ClassUtils ;
49
+ import org .springframework .util .CollectionUtils ;
40
50
import org .springframework .util .ReflectionUtils ;
41
51
42
52
/**
45
55
*
46
56
* @author Andy Wilkinson
47
57
* @author Phillip Webb
58
+ * @author Scott Frederick
48
59
* @since 3.0.0
49
60
*/
50
61
public final class ClientHttpRequestFactories {
@@ -134,25 +145,39 @@ private static <T extends ClientHttpRequestFactory> T createRequestFactory(Class
134
145
static class HttpComponents {
135
146
136
147
static HttpComponentsClientHttpRequestFactory get (ClientHttpRequestFactorySettings settings ) {
137
- HttpComponentsClientHttpRequestFactory requestFactory = createRequestFactory (settings .readTimeout ());
148
+ HttpComponentsClientHttpRequestFactory requestFactory = createRequestFactory (settings .readTimeout (),
149
+ settings .sslBundle ());
138
150
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
139
151
map .from (settings ::connectTimeout ).asInt (Duration ::toMillis ).to (requestFactory ::setConnectTimeout );
140
152
map .from (settings ::bufferRequestBody ).to (requestFactory ::setBufferRequestBody );
141
153
return requestFactory ;
142
154
}
143
155
144
- private static HttpComponentsClientHttpRequestFactory createRequestFactory (Duration readTimeout ) {
145
- return ( readTimeout != null ) ? new HttpComponentsClientHttpRequestFactory ( createHttpClient ( readTimeout ))
146
- : new HttpComponentsClientHttpRequestFactory ();
156
+ private static HttpComponentsClientHttpRequestFactory createRequestFactory (Duration readTimeout ,
157
+ SslBundle sslBundle ) {
158
+ return new HttpComponentsClientHttpRequestFactory (createHttpClient ( readTimeout , sslBundle ) );
147
159
}
148
160
149
- private static HttpClient createHttpClient (Duration readTimeout ) {
150
- SocketConfig socketConfig = SocketConfig .custom ()
151
- .setSoTimeout ((int ) readTimeout .toMillis (), TimeUnit .MILLISECONDS )
152
- .build ();
153
- PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder .create ()
154
- .setDefaultSocketConfig (socketConfig )
155
- .build ();
161
+ private static HttpClient createHttpClient (Duration readTimeout , SslBundle sslBundle ) {
162
+ PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder
163
+ .create ();
164
+ if (readTimeout != null ) {
165
+ SocketConfig socketConfig = SocketConfig .custom ()
166
+ .setSoTimeout ((int ) readTimeout .toMillis (), TimeUnit .MILLISECONDS )
167
+ .build ();
168
+ connectionManagerBuilder .setDefaultSocketConfig (socketConfig );
169
+ }
170
+ if (sslBundle != null ) {
171
+ SslOptions options = sslBundle .getOptions ();
172
+ String [] enabledProtocols = (!CollectionUtils .isEmpty (options .getEnabledProtocols ()))
173
+ ? options .getEnabledProtocols ().toArray (String []::new ) : null ;
174
+ String [] ciphers = (!CollectionUtils .isEmpty (options .getCiphers ()))
175
+ ? options .getCiphers ().toArray (String []::new ) : null ;
176
+ SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory (sslBundle .createSslContext (),
177
+ enabledProtocols , ciphers , new DefaultHostnameVerifier ());
178
+ connectionManagerBuilder .setSSLSocketFactory (socketFactory );
179
+ }
180
+ PoolingHttpClientConnectionManager connectionManager = connectionManagerBuilder .build ();
156
181
return HttpClientBuilder .create ().setConnectionManager (connectionManager ).build ();
157
182
}
158
183
@@ -166,13 +191,27 @@ static class OkHttp {
166
191
static OkHttp3ClientHttpRequestFactory get (ClientHttpRequestFactorySettings settings ) {
167
192
Assert .state (settings .bufferRequestBody () == null ,
168
193
() -> "OkHttp3ClientHttpRequestFactory does not support request body buffering" );
169
- OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory ( );
194
+ OkHttp3ClientHttpRequestFactory requestFactory = createRequestFactory ( settings . sslBundle () );
170
195
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
171
196
map .from (settings ::connectTimeout ).asInt (Duration ::toMillis ).to (requestFactory ::setConnectTimeout );
172
197
map .from (settings ::readTimeout ).asInt (Duration ::toMillis ).to (requestFactory ::setReadTimeout );
173
198
return requestFactory ;
174
199
}
175
200
201
+ private static OkHttp3ClientHttpRequestFactory createRequestFactory (SslBundle sslBundle ) {
202
+ if (sslBundle != null ) {
203
+ SSLSocketFactory socketFactory = sslBundle .createSslContext ().getSocketFactory ();
204
+ TrustManager [] trustManagers = sslBundle .getManagers ().getTrustManagers ();
205
+ Assert .state (trustManagers .length == 1 ,
206
+ "Trust material must be provided in the SSL bundle for OkHttp3ClientHttpRequestFactory" );
207
+ OkHttpClient client = new OkHttpClient .Builder ()
208
+ .sslSocketFactory (socketFactory , (X509TrustManager ) trustManagers [0 ])
209
+ .build ();
210
+ return new OkHttp3ClientHttpRequestFactory (client );
211
+ }
212
+ return new OkHttp3ClientHttpRequestFactory ();
213
+ }
214
+
176
215
}
177
216
178
217
/**
0 commit comments