2222import java .util .function .Consumer ;
2323import java .util .function .Function ;
2424
25+ import org .apache .hc .client5 .http .config .ConnectionConfig ;
2526import org .apache .hc .client5 .http .config .RequestConfig ;
2627import org .apache .hc .client5 .http .impl .classic .CloseableHttpClient ;
2728import org .apache .hc .client5 .http .impl .classic .HttpClientBuilder ;
@@ -52,23 +53,27 @@ public final class HttpComponentsHttpClientBuilder {
5253
5354 private final Consumer <SocketConfig .Builder > socketConfigCustomizer ;
5455
56+ private final Consumer <ConnectionConfig .Builder > connectionConfigCustomizer ;
57+
5558 private final Consumer <RequestConfig .Builder > defaultRequestConfigCustomizer ;
5659
5760 private final Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ;
5861
5962 public HttpComponentsHttpClientBuilder () {
60- this (Empty .consumer (), Empty .consumer (), Empty .consumer (), Empty .consumer (),
63+ this (Empty .consumer (), Empty .consumer (), Empty .consumer (), Empty .consumer (), Empty . consumer (),
6164 HttpComponentsSslBundleTlsStrategy ::get );
6265 }
6366
6467 private HttpComponentsHttpClientBuilder (Consumer <HttpClientBuilder > customizer ,
6568 Consumer <PoolingHttpClientConnectionManagerBuilder > connectionManagerCustomizer ,
6669 Consumer <SocketConfig .Builder > socketConfigCustomizer ,
70+ Consumer <ConnectionConfig .Builder > connectionConfigCustomizer ,
6771 Consumer <RequestConfig .Builder > defaultRequestConfigCustomizer ,
6872 Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ) {
6973 this .customizer = customizer ;
7074 this .connectionManagerCustomizer = connectionManagerCustomizer ;
7175 this .socketConfigCustomizer = socketConfigCustomizer ;
76+ this .connectionConfigCustomizer = connectionConfigCustomizer ;
7277 this .defaultRequestConfigCustomizer = defaultRequestConfigCustomizer ;
7378 this .tlsSocketStrategyFactory = tlsSocketStrategyFactory ;
7479 }
@@ -82,8 +87,8 @@ private HttpComponentsHttpClientBuilder(Consumer<HttpClientBuilder> customizer,
8287 public HttpComponentsHttpClientBuilder withCustomizer (Consumer <HttpClientBuilder > customizer ) {
8388 Assert .notNull (customizer , "'customizer' must not be null" );
8489 return new HttpComponentsHttpClientBuilder (this .customizer .andThen (customizer ),
85- this .connectionManagerCustomizer , this .socketConfigCustomizer , this .defaultRequestConfigCustomizer ,
86- this .tlsSocketStrategyFactory );
90+ this .connectionManagerCustomizer , this .socketConfigCustomizer , this .connectionConfigCustomizer ,
91+ this .defaultRequestConfigCustomizer , this . tlsSocketStrategyFactory );
8792 }
8893
8994 /**
@@ -97,7 +102,7 @@ public HttpComponentsHttpClientBuilder withConnectionManagerCustomizer(
97102 Assert .notNull (connectionManagerCustomizer , "'connectionManagerCustomizer' must not be null" );
98103 return new HttpComponentsHttpClientBuilder (this .customizer ,
99104 this .connectionManagerCustomizer .andThen (connectionManagerCustomizer ), this .socketConfigCustomizer ,
100- this .defaultRequestConfigCustomizer , this .tlsSocketStrategyFactory );
105+ this .connectionConfigCustomizer , this . defaultRequestConfigCustomizer , this .tlsSocketStrategyFactory );
101106 }
102107
103108 /**
@@ -111,8 +116,24 @@ public HttpComponentsHttpClientBuilder withSocketConfigCustomizer(
111116 Consumer <SocketConfig .Builder > socketConfigCustomizer ) {
112117 Assert .notNull (socketConfigCustomizer , "'socketConfigCustomizer' must not be null" );
113118 return new HttpComponentsHttpClientBuilder (this .customizer , this .connectionManagerCustomizer ,
114- this .socketConfigCustomizer .andThen (socketConfigCustomizer ), this .defaultRequestConfigCustomizer ,
115- this .tlsSocketStrategyFactory );
119+ this .socketConfigCustomizer .andThen (socketConfigCustomizer ), this .connectionConfigCustomizer ,
120+ this .defaultRequestConfigCustomizer , this .tlsSocketStrategyFactory );
121+ }
122+
123+ /**
124+ * Return a new {@link HttpComponentsHttpClientBuilder} that applies additional
125+ * customization to the underlying
126+ * {@link org.apache.hc.client5.http.config.ConnectionConfig.Builder}.
127+ * @param connectionConfigCustomizer the customizer to apply
128+ * @return a new {@link HttpComponentsHttpClientBuilder} instance
129+ * @since 3.5.8
130+ */
131+ public HttpComponentsHttpClientBuilder withConnectionConfigCustomizer (
132+ Consumer <ConnectionConfig .Builder > connectionConfigCustomizer ) {
133+ Assert .notNull (connectionConfigCustomizer , "'connectionConfigCustomizer' must not be null" );
134+ return new HttpComponentsHttpClientBuilder (this .customizer , this .connectionManagerCustomizer ,
135+ this .socketConfigCustomizer .andThen (this .socketConfigCustomizer ), this .connectionConfigCustomizer ,
136+ this .defaultRequestConfigCustomizer , this .tlsSocketStrategyFactory );
116137 }
117138
118139 /**
@@ -128,7 +149,8 @@ public HttpComponentsHttpClientBuilder withTlsSocketStrategyFactory(
128149 Function <SslBundle , TlsSocketStrategy > tlsSocketStrategyFactory ) {
129150 Assert .notNull (tlsSocketStrategyFactory , "'tlsSocketStrategyFactory' must not be null" );
130151 return new HttpComponentsHttpClientBuilder (this .customizer , this .connectionManagerCustomizer ,
131- this .socketConfigCustomizer , this .defaultRequestConfigCustomizer , tlsSocketStrategyFactory );
152+ this .socketConfigCustomizer , this .connectionConfigCustomizer , this .defaultRequestConfigCustomizer ,
153+ tlsSocketStrategyFactory );
132154 }
133155
134156 /**
@@ -143,7 +165,7 @@ public HttpComponentsHttpClientBuilder withDefaultRequestConfigCustomizer(
143165 Consumer <RequestConfig .Builder > defaultRequestConfigCustomizer ) {
144166 Assert .notNull (defaultRequestConfigCustomizer , "'defaultRequestConfigCustomizer' must not be null" );
145167 return new HttpComponentsHttpClientBuilder (this .customizer , this .connectionManagerCustomizer ,
146- this .socketConfigCustomizer ,
168+ this .socketConfigCustomizer , this . connectionConfigCustomizer ,
147169 this .defaultRequestConfigCustomizer .andThen (defaultRequestConfigCustomizer ),
148170 this .tlsSocketStrategyFactory );
149171 }
@@ -155,7 +177,6 @@ public HttpComponentsHttpClientBuilder withDefaultRequestConfigCustomizer(
155177 */
156178 public CloseableHttpClient build (HttpClientSettings settings ) {
157179 settings = (settings != null ) ? settings : HttpClientSettings .DEFAULTS ;
158- Assert .isTrue (settings .connectTimeout () == null , "'settings' must not have a 'connectTimeout'" );
159180 HttpClientBuilder builder = HttpClientBuilder .create ()
160181 .useSystemProperties ()
161182 .setRedirectStrategy (HttpComponentsRedirectStrategy .get (settings .redirects ()))
@@ -169,19 +190,29 @@ private PoolingHttpClientConnectionManager createConnectionManager(HttpClientSet
169190 PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder .create ()
170191 .useSystemProperties ();
171192 PropertyMapper map = PropertyMapper .get ();
172- builder .setDefaultSocketConfig (createSocketConfig (settings ));
193+ builder .setDefaultSocketConfig (createSocketConfig ());
194+ builder .setDefaultConnectionConfig (createConnectionConfig (settings ));
173195 map .from (settings ::sslBundle ).as (this .tlsSocketStrategyFactory ).whenNonNull ().to (builder ::setTlsSocketStrategy );
174196 this .connectionManagerCustomizer .accept (builder );
175197 return builder .build ();
176198 }
177199
178- private SocketConfig createSocketConfig (HttpClientSettings settings ) {
200+ private SocketConfig createSocketConfig () {
179201 SocketConfig .Builder builder = SocketConfig .custom ();
202+ this .socketConfigCustomizer .accept (builder );
203+ return builder .build ();
204+ }
205+
206+ private ConnectionConfig createConnectionConfig (HttpClientSettings settings ) {
207+ ConnectionConfig .Builder builder = ConnectionConfig .custom ();
180208 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
209+ map .from (settings ::connectTimeout )
210+ .as (Duration ::toMillis )
211+ .to ((timeout ) -> builder .setConnectTimeout (timeout , TimeUnit .MILLISECONDS ));
181212 map .from (settings ::readTimeout )
182213 .asInt (Duration ::toMillis )
183- .to ((timeout ) -> builder .setSoTimeout (timeout , TimeUnit .MILLISECONDS ));
184- this .socketConfigCustomizer .accept (builder );
214+ .to ((timeout ) -> builder .setSocketTimeout (timeout , TimeUnit .MILLISECONDS ));
215+ this .connectionConfigCustomizer .accept (builder );
185216 return builder .build ();
186217 }
187218
0 commit comments