|
18 | 18 |
|
19 | 19 | import java.io.IOException;
|
20 | 20 | import java.net.URI;
|
| 21 | +import java.security.KeyManagementException; |
| 22 | +import java.security.KeyStoreException; |
| 23 | +import java.security.NoSuchAlgorithmException; |
| 24 | +import java.time.Duration; |
21 | 25 | import java.util.Arrays;
|
22 | 26 | import java.util.HashSet;
|
23 | 27 | import java.util.Map;
|
24 | 28 | import java.util.Set;
|
| 29 | +import java.util.concurrent.TimeUnit; |
25 | 30 |
|
26 | 31 | import javax.net.ssl.SSLContext;
|
27 | 32 |
|
28 | 33 | import org.apache.hc.client5.http.classic.HttpClient;
|
29 | 34 | import org.apache.hc.client5.http.config.RequestConfig;
|
30 | 35 | import org.apache.hc.client5.http.cookie.StandardCookieSpec;
|
| 36 | +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; |
31 | 37 | import org.apache.hc.client5.http.impl.classic.HttpClients;
|
32 | 38 | import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
33 | 39 | import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
34 | 40 | import org.apache.hc.client5.http.protocol.HttpClientContext;
|
35 | 41 | import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
36 | 42 | import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
|
37 | 43 | import org.apache.hc.client5.http.ssl.TrustSelfSignedStrategy;
|
| 44 | +import org.apache.hc.core5.http.io.SocketConfig; |
38 | 45 | import org.apache.hc.core5.http.protocol.HttpContext;
|
39 | 46 | import org.apache.hc.core5.http.ssl.TLS;
|
40 | 47 | import org.apache.hc.core5.ssl.SSLContextBuilder;
|
41 | 48 |
|
| 49 | +import org.springframework.boot.web.client.ClientHttpRequestFactorySettings; |
42 | 50 | import org.springframework.boot.web.client.RestTemplateBuilder;
|
43 | 51 | import org.springframework.boot.web.client.RootUriTemplateHandler;
|
44 | 52 | import org.springframework.core.ParameterizedTypeReference;
|
@@ -138,8 +146,8 @@ public TestRestTemplate(RestTemplateBuilder builder, String username, String pas
|
138 | 146 | if (httpClientOptions != null) {
|
139 | 147 | ClientHttpRequestFactory requestFactory = builder.buildRequestFactory();
|
140 | 148 | if (requestFactory instanceof HttpComponentsClientHttpRequestFactory) {
|
141 |
| - builder = builder |
142 |
| - .requestFactory(() -> new CustomHttpComponentsClientHttpRequestFactory(httpClientOptions)); |
| 149 | + builder = builder.requestFactory( |
| 150 | + (settings) -> new CustomHttpComponentsClientHttpRequestFactory(httpClientOptions, settings)); |
143 | 151 | }
|
144 | 152 | }
|
145 | 153 | if (username != null || password != null) {
|
@@ -1000,43 +1008,71 @@ protected static class CustomHttpComponentsClientHttpRequestFactory extends Http
|
1000 | 1008 |
|
1001 | 1009 | private final boolean enableRedirects;
|
1002 | 1010 |
|
1003 |
| - public CustomHttpComponentsClientHttpRequestFactory(HttpClientOption[] httpClientOptions) { |
| 1011 | + public CustomHttpComponentsClientHttpRequestFactory(HttpClientOption[] httpClientOptions, |
| 1012 | + ClientHttpRequestFactorySettings settings) { |
1004 | 1013 | Set<HttpClientOption> options = new HashSet<>(Arrays.asList(httpClientOptions));
|
1005 | 1014 | this.cookieSpec = (options.contains(HttpClientOption.ENABLE_COOKIES) ? StandardCookieSpec.STRICT
|
1006 | 1015 | : StandardCookieSpec.IGNORE);
|
1007 | 1016 | this.enableRedirects = options.contains(HttpClientOption.ENABLE_REDIRECTS);
|
1008 |
| - if (options.contains(HttpClientOption.SSL)) { |
1009 |
| - setHttpClient(createSslHttpClient()); |
| 1017 | + boolean ssl = options.contains(HttpClientOption.SSL); |
| 1018 | + if (settings.readTimeout() != null || ssl) { |
| 1019 | + setHttpClient(createHttpClient(settings.readTimeout(), ssl)); |
| 1020 | + } |
| 1021 | + if (settings.connectTimeout() != null) { |
| 1022 | + setConnectTimeout((int) settings.connectTimeout().toMillis()); |
| 1023 | + } |
| 1024 | + if (settings.bufferRequestBody() != null) { |
| 1025 | + setBufferRequestBody(settings.bufferRequestBody()); |
1010 | 1026 | }
|
1011 | 1027 | }
|
1012 | 1028 |
|
1013 |
| - private HttpClient createSslHttpClient() { |
| 1029 | + private HttpClient createHttpClient(Duration readTimeout, boolean ssl) { |
1014 | 1030 | try {
|
1015 |
| - SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) |
1016 |
| - .build(); |
1017 |
| - SSLConnectionSocketFactory socketFactory = SSLConnectionSocketFactoryBuilder.create() |
1018 |
| - .setSslContext(sslContext).setTlsVersions(TLS.V_1_3, TLS.V_1_2).build(); |
1019 |
| - PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder |
1020 |
| - .create().setSSLSocketFactory(socketFactory).build(); |
1021 |
| - |
1022 |
| - return HttpClients.custom().setConnectionManager(connectionManager) |
1023 |
| - .setDefaultRequestConfig(getRequestConfig()).build(); |
| 1031 | + HttpClientBuilder builder = HttpClients.custom(); |
| 1032 | + builder.setConnectionManager(createConnectionManager(readTimeout, ssl)); |
| 1033 | + builder.setDefaultRequestConfig(createRequestConfig()); |
| 1034 | + return builder.build(); |
1024 | 1035 | }
|
1025 | 1036 | catch (Exception ex) {
|
1026 |
| - throw new IllegalStateException("Unable to create SSL HttpClient", ex); |
| 1037 | + throw new IllegalStateException("Unable to create customized HttpClient", ex); |
| 1038 | + } |
| 1039 | + } |
| 1040 | + |
| 1041 | + private PoolingHttpClientConnectionManager createConnectionManager(Duration readTimeout, boolean ssl) |
| 1042 | + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { |
| 1043 | + PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create(); |
| 1044 | + if (ssl) { |
| 1045 | + builder.setSSLSocketFactory(createSocketFactory()); |
| 1046 | + } |
| 1047 | + if (readTimeout != null) { |
| 1048 | + SocketConfig socketConfig = SocketConfig.custom() |
| 1049 | + .setSoTimeout((int) readTimeout.toMillis(), TimeUnit.MILLISECONDS).build(); |
| 1050 | + builder.setDefaultSocketConfig(socketConfig); |
1027 | 1051 | }
|
| 1052 | + return builder.build(); |
| 1053 | + } |
| 1054 | + |
| 1055 | + private SSLConnectionSocketFactory createSocketFactory() |
| 1056 | + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { |
| 1057 | + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) |
| 1058 | + .build(); |
| 1059 | + return SSLConnectionSocketFactoryBuilder.create().setSslContext(sslContext) |
| 1060 | + .setTlsVersions(TLS.V_1_3, TLS.V_1_2).build(); |
1028 | 1061 | }
|
1029 | 1062 |
|
1030 | 1063 | @Override
|
1031 | 1064 | protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
|
1032 | 1065 | HttpClientContext context = HttpClientContext.create();
|
1033 |
| - context.setRequestConfig(getRequestConfig()); |
| 1066 | + context.setRequestConfig(createRequestConfig()); |
1034 | 1067 | return context;
|
1035 | 1068 | }
|
1036 | 1069 |
|
1037 |
| - protected RequestConfig getRequestConfig() { |
1038 |
| - return RequestConfig.custom().setCookieSpec(this.cookieSpec).setAuthenticationEnabled(false) |
1039 |
| - .setRedirectsEnabled(this.enableRedirects).build(); |
| 1070 | + protected RequestConfig createRequestConfig() { |
| 1071 | + RequestConfig.Builder builder = RequestConfig.custom(); |
| 1072 | + builder.setCookieSpec(this.cookieSpec); |
| 1073 | + builder.setAuthenticationEnabled(false); |
| 1074 | + builder.setRedirectsEnabled(this.enableRedirects); |
| 1075 | + return builder.build(); |
1040 | 1076 | }
|
1041 | 1077 |
|
1042 | 1078 | }
|
|
0 commit comments