diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java index 8c3a9f5123..751dfa9d5c 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java @@ -70,6 +70,9 @@ final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpR return this.httpRequest.getURI(); } + HttpContext getHttpContext() { + return httpContext; + } @Override protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java index 9aabb66a36..5edb555678 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java @@ -113,6 +113,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest public void setConnectTimeout(int timeout) { Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value"); this.connectTimeout = timeout; + setLegacyConnectionTimeout(getHttpClient(), connectTimeout); } /** @@ -123,6 +124,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest public void setReadTimeout(int timeout) { Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value"); this.socketTimeout= timeout; + setLegacyReadTimeout(getHttpClient(), socketTimeout); } /** @@ -222,6 +224,44 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest return null; } + /** + * Apply the specified custom connection timeout for deprecated {@link HttpClient} + * instances. + *

As from HttpClient 4.3, default parameters have to be set in a + * {@link RequestConfig} instance instead of setting the parameters + * on the client. + *

Unfortunately, this behaviour is not backward compatible and older + * {@link HttpClient} implementations will ignore the {@link RequestConfig} + * object set in the context. + *

If the specified client is an older implementation, we set the + * custom connection timeout through the deprecated API. Otherwise, we just + * return as it is set per request with newer clients + * @param client the client to handle + * @param connectionTimeout the custom connection timeout + */ + @SuppressWarnings("deprecation") + private void setLegacyConnectionTimeout(HttpClient client, int connectionTimeout) { + if (org.apache.http.impl.client.AbstractHttpClient.class.isInstance(client)) { + client.getParams().setIntParameter( + org.apache.http.params.CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout); + } + } + + /** + * Apply the specified read timeout for deprecated {@link HttpClient} + * instances. + * @param client the client to handle + * @param readTimeout the custom read timeout + * @see #setLegacyConnectionTimeout(org.apache.http.client.HttpClient, int) + */ + @SuppressWarnings("deprecation") + private void setLegacyReadTimeout(HttpClient client, int readTimeout) { + if (org.apache.http.impl.client.AbstractHttpClient.class.isInstance(client)) { + client.getParams().setIntParameter( + org.apache.http.params.CoreConnectionPNames.SO_TIMEOUT, readTimeout); + } + } + /** * Shutdown hook that closes the underlying * {@link org.apache.http.conn.HttpClientConnectionManager ClientConnectionManager}'s diff --git a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java index 0eabc67d93..5f4442f653 100644 --- a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,16 @@ package org.springframework.http.client; +import static org.junit.Assert.*; + +import java.net.URI; + +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.params.CoreConnectionPNames; import org.junit.Test; import org.springframework.http.HttpMethod; @@ -32,4 +42,36 @@ public class HttpComponentsClientHttpRequestFactoryTests extends AbstractHttpReq assertHttpMethod("patch", HttpMethod.PATCH); } + @SuppressWarnings("deprecation") + @Test + public void assertLegacyCustomConfig() { + HttpClient httpClient = new DefaultHttpClient(); // Does not support RequestConfig + HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient); + hrf.setConnectTimeout(1234); + assertEquals(1234, httpClient.getParams().getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 0)); + + hrf.setReadTimeout(4567); + assertEquals(4567, httpClient.getParams().getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0)); + } + + @Test + public void assertCustomConfig() throws Exception { + HttpClient httpClient = HttpClientBuilder.create().build(); + HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient); + hrf.setConnectTimeout(1234); + hrf.setReadTimeout(4567); + + URI uri = new URI(baseUrl + "/status/ok"); + HttpComponentsClientHttpRequest request = (HttpComponentsClientHttpRequest) + hrf.createRequest(uri, HttpMethod.GET); + + Object config = request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG); + assertNotNull("Request config should be set", config); + assertTrue("Wrong request config type" + config.getClass().getName(), + RequestConfig.class.isInstance(config)); + RequestConfig requestConfig = (RequestConfig) config; + assertEquals("Wrong custom connection timeout", 1234, requestConfig.getConnectTimeout()); + assertEquals("Wrong custom socket timeout", 4567, requestConfig.getSocketTimeout()); + + } }