Add setReadTimeout and setConnectTimeout to RestTemplateBuilder

Closes gh-6346
This commit is contained in:
Andy Wilkinson 2016-07-13 16:40:32 +01:00
parent 9fdef15d50
commit f84f31b47d
4 changed files with 322 additions and 37 deletions

View File

@ -52,6 +52,21 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>18.0</version> <version>18.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.38.Final</version>
</dependency>
<dependency> <dependency>
<groupId>io.spring.gradle</groupId> <groupId>io.spring.gradle</groupId>
<artifactId>dependency-management-plugin</artifactId> <artifactId>dependency-management-plugin</artifactId>

View File

@ -271,6 +271,16 @@
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
@ -306,6 +316,11 @@
<artifactId>mariadb-java-client</artifactId> <artifactId>mariadb-java-client</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>

View File

@ -16,6 +16,8 @@
package org.springframework.boot.web.client; package org.springframework.boot.web.client;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -26,6 +28,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.client.support.BasicAuthorizationInterceptor; import org.springframework.http.client.support.BasicAuthorizationInterceptor;
@ -33,6 +36,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplateHandler; import org.springframework.web.util.UriTemplateHandler;
@ -51,6 +55,7 @@ import org.springframework.web.util.UriTemplateHandler;
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
* @since 1.4.0 * @since 1.4.0
*/ */
public class RestTemplateBuilder { public class RestTemplateBuilder {
@ -84,7 +89,9 @@ public class RestTemplateBuilder {
private final BasicAuthorizationInterceptor basicAuthorization; private final BasicAuthorizationInterceptor basicAuthorization;
private final Set<RestTemplateCustomizer> customizers; private final Set<RestTemplateCustomizer> restTemplateCustomizers;
private final Set<RequestFactoryCustomizer> requestFactoryCustomizers;
/** /**
* Create a new {@link RestTemplateBuilder} instance. * Create a new {@link RestTemplateBuilder} instance.
@ -100,8 +107,9 @@ public class RestTemplateBuilder {
this.uriTemplateHandler = null; this.uriTemplateHandler = null;
this.errorHandler = null; this.errorHandler = null;
this.basicAuthorization = null; this.basicAuthorization = null;
this.customizers = Collections.unmodifiableSet( this.restTemplateCustomizers = Collections.unmodifiableSet(
new LinkedHashSet<RestTemplateCustomizer>(Arrays.asList(customizers))); new LinkedHashSet<RestTemplateCustomizer>(Arrays.asList(customizers)));
this.requestFactoryCustomizers = Collections.<RequestFactoryCustomizer>emptySet();
} }
private RestTemplateBuilder(boolean detectRequestFactory, String rootUri, private RestTemplateBuilder(boolean detectRequestFactory, String rootUri,
@ -109,7 +117,8 @@ public class RestTemplateBuilder {
ClientHttpRequestFactory requestFactory, ClientHttpRequestFactory requestFactory,
UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler, UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler,
BasicAuthorizationInterceptor basicAuthorization, BasicAuthorizationInterceptor basicAuthorization,
Set<RestTemplateCustomizer> customizers) { Set<RestTemplateCustomizer> restTemplateCustomizers,
Set<RequestFactoryCustomizer> requestFactoryCustomizers) {
super(); super();
this.detectRequestFactory = detectRequestFactory; this.detectRequestFactory = detectRequestFactory;
this.rootUri = rootUri; this.rootUri = rootUri;
@ -118,7 +127,8 @@ public class RestTemplateBuilder {
this.uriTemplateHandler = uriTemplateHandler; this.uriTemplateHandler = uriTemplateHandler;
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.basicAuthorization = basicAuthorization; this.basicAuthorization = basicAuthorization;
this.customizers = customizers; this.restTemplateCustomizers = restTemplateCustomizers;
this.requestFactoryCustomizers = requestFactoryCustomizers;
} }
/** /**
@ -131,7 +141,8 @@ public class RestTemplateBuilder {
public RestTemplateBuilder detectRequestFactory(boolean detectRequestFactory) { public RestTemplateBuilder detectRequestFactory(boolean detectRequestFactory) {
return new RestTemplateBuilder(detectRequestFactory, this.rootUri, return new RestTemplateBuilder(detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.customizers); this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -143,7 +154,8 @@ public class RestTemplateBuilder {
public RestTemplateBuilder rootUri(String rootUri) { public RestTemplateBuilder rootUri(String rootUri) {
return new RestTemplateBuilder(this.detectRequestFactory, rootUri, return new RestTemplateBuilder(this.detectRequestFactory, rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.customizers); this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -173,7 +185,8 @@ public class RestTemplateBuilder {
Collections.unmodifiableSet( Collections.unmodifiableSet(
new LinkedHashSet<HttpMessageConverter<?>>(messageConverters)), new LinkedHashSet<HttpMessageConverter<?>>(messageConverters)),
this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.requestFactory, this.uriTemplateHandler, this.errorHandler,
this.basicAuthorization, this.customizers); this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -202,7 +215,7 @@ public class RestTemplateBuilder {
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
append(this.messageConverters, messageConverters), this.requestFactory, append(this.messageConverters, messageConverters), this.requestFactory,
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
this.customizers); this.restTemplateCustomizers, this.requestFactoryCustomizers);
} }
/** /**
@ -217,7 +230,8 @@ public class RestTemplateBuilder {
Collections.unmodifiableSet(new LinkedHashSet<HttpMessageConverter<?>>( Collections.unmodifiableSet(new LinkedHashSet<HttpMessageConverter<?>>(
new RestTemplate().getMessageConverters())), new RestTemplate().getMessageConverters())),
this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.requestFactory, this.uriTemplateHandler, this.errorHandler,
this.basicAuthorization, this.customizers); this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -242,7 +256,8 @@ public class RestTemplateBuilder {
Assert.notNull(requestFactory, "RequestFactory must not be null"); Assert.notNull(requestFactory, "RequestFactory must not be null");
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, requestFactory, this.uriTemplateHandler, this.messageConverters, requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.customizers); this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -255,7 +270,8 @@ public class RestTemplateBuilder {
Assert.notNull(uriTemplateHandler, "UriTemplateHandler must not be null"); Assert.notNull(uriTemplateHandler, "UriTemplateHandler must not be null");
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, uriTemplateHandler, this.messageConverters, this.requestFactory, uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.customizers); this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -268,7 +284,8 @@ public class RestTemplateBuilder {
Assert.notNull(errorHandler, "ErrorHandler must not be null"); Assert.notNull(errorHandler, "ErrorHandler must not be null");
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
errorHandler, this.basicAuthorization, this.customizers); errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
this.requestFactoryCustomizers);
} }
/** /**
@ -282,14 +299,14 @@ public class RestTemplateBuilder {
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, new BasicAuthorizationInterceptor(username, password), this.errorHandler, new BasicAuthorizationInterceptor(username, password),
this.customizers); this.restTemplateCustomizers, this.requestFactoryCustomizers);
} }
/** /**
* Set the {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied * Set the {@link RestTemplateCustomizer RestTemplateCustomizers} that should be
* to the {@link RestTemplate}. Customizers are applied in the order that they were * applied to the {@link RestTemplate}. Customizers are applied in the order that they
* added after builder configuration has been applied. Setting this value will replace * were added after builder configuration has been applied. Setting this value will
* any previously configured customizers. * replace any previously configured customizers.
* @param restTemplateCustomizers the customizers to set * @param restTemplateCustomizers the customizers to set
* @return a new builder instance * @return a new builder instance
* @see #additionalCustomizers(RestTemplateCustomizer...) * @see #additionalCustomizers(RestTemplateCustomizer...)
@ -302,10 +319,10 @@ public class RestTemplateBuilder {
} }
/** /**
* Set the {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied * Set the {@link RestTemplateCustomizer RestTemplateCustomizers} that should be
* to the {@link RestTemplate}. Customizers are applied in the order that they were * applied to the {@link RestTemplate}. Customizers are applied in the order that they
* added after builder configuration has been applied. Setting this value will replace * were added after builder configuration has been applied. Setting this value will
* any previously configured customizers. * replace any previously configured customizers.
* @param restTemplateCustomizers the customizers to set * @param restTemplateCustomizers the customizers to set
* @return a new builder instance * @return a new builder instance
* @see #additionalCustomizers(RestTemplateCustomizer...) * @see #additionalCustomizers(RestTemplateCustomizer...)
@ -318,13 +335,14 @@ public class RestTemplateBuilder {
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.errorHandler, this.basicAuthorization,
Collections.unmodifiableSet(new LinkedHashSet<RestTemplateCustomizer>( Collections.unmodifiableSet(new LinkedHashSet<RestTemplateCustomizer>(
restTemplateCustomizers))); restTemplateCustomizers)),
this.requestFactoryCustomizers);
} }
/** /**
* Add {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied to * Add {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied
* the {@link RestTemplate}. Customizers are applied in the order that they were added * to the {@link RestTemplate}. Customizers are applied in the order that they were
* after builder configuration has been applied. * added after builder configuration has been applied.
* @param restTemplateCustomizers the customizers to add * @param restTemplateCustomizers the customizers to add
* @return a new builder instance * @return a new builder instance
* @see #customizers(RestTemplateCustomizer...) * @see #customizers(RestTemplateCustomizer...)
@ -337,9 +355,9 @@ public class RestTemplateBuilder {
} }
/** /**
* Add {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied to * Add {@link RestTemplateCustomizer RestTemplateCustomizers} that should be applied
* the {@link RestTemplate}. Customizers are applied in the order that they were added * to the {@link RestTemplate}. Customizers are applied in the order that they were
* after builder configuration has been applied. * added after builder configuration has been applied.
* @param customizers the customizers to add * @param customizers the customizers to add
* @return a new builder instance * @return a new builder instance
* @see #customizers(RestTemplateCustomizer...) * @see #customizers(RestTemplateCustomizer...)
@ -350,7 +368,38 @@ public class RestTemplateBuilder {
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.errorHandler, this.basicAuthorization,
append(this.customizers, customizers)); append(this.restTemplateCustomizers, customizers),
this.requestFactoryCustomizers);
}
/**
* Sets the connect timeout in milliseconds on the underlying
* {@link ClientHttpRequestFactory}.
*
* @param connectTimeout the connect timeout in milliseconds
* @return a new builder instance.
*/
public RestTemplateBuilder setConnectTimeout(int connectTimeout) {
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
append(this.requestFactoryCustomizers,
new ConnectTimeoutRequestFactoryCustomizer(connectTimeout)));
}
/**
* Sets the read timeout in milliseconds on the underlying
* {@link ClientHttpRequestFactory}.
*
* @param readTimeout the read timeout in milliseconds
* @return a new builder instance.
*/
public RestTemplateBuilder setReadTimeout(int readTimeout) {
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
append(this.requestFactoryCustomizers,
new ReadTimeoutRequestFactoryCustomizer(readTimeout)));
} }
/** /**
@ -386,12 +435,7 @@ public class RestTemplateBuilder {
* @see RestTemplateBuilder#build(Class) * @see RestTemplateBuilder#build(Class)
*/ */
public <T extends RestTemplate> T configure(T restTemplate) { public <T extends RestTemplate> T configure(T restTemplate) {
if (this.requestFactory != null) { configureRequestFactory(restTemplate);
restTemplate.setRequestFactory(this.requestFactory);
}
else if (this.detectRequestFactory) {
restTemplate.setRequestFactory(detectRequestFactory());
}
if (!CollectionUtils.isEmpty(this.messageConverters)) { if (!CollectionUtils.isEmpty(this.messageConverters)) {
restTemplate.setMessageConverters( restTemplate.setMessageConverters(
new ArrayList<HttpMessageConverter<?>>(this.messageConverters)); new ArrayList<HttpMessageConverter<?>>(this.messageConverters));
@ -408,14 +452,47 @@ public class RestTemplateBuilder {
if (this.basicAuthorization != null) { if (this.basicAuthorization != null) {
restTemplate.getInterceptors().add(this.basicAuthorization); restTemplate.getInterceptors().add(this.basicAuthorization);
} }
if (!CollectionUtils.isEmpty(this.customizers)) { if (!CollectionUtils.isEmpty(this.restTemplateCustomizers)) {
for (RestTemplateCustomizer customizer : this.customizers) { for (RestTemplateCustomizer customizer : this.restTemplateCustomizers) {
customizer.customize(restTemplate); customizer.customize(restTemplate);
} }
} }
return restTemplate; return restTemplate;
} }
private void configureRequestFactory(RestTemplate restTemplate) {
ClientHttpRequestFactory requestFactory = null;
if (this.requestFactory != null) {
requestFactory = unwrapRequestFactoryIfNecessary(this.requestFactory);
}
else if (this.detectRequestFactory) {
requestFactory = detectRequestFactory();
}
if (requestFactory != null) {
for (RequestFactoryCustomizer customizer : this.requestFactoryCustomizers) {
customizer.customize(requestFactory);
}
restTemplate.setRequestFactory(requestFactory);
}
}
private ClientHttpRequestFactory unwrapRequestFactoryIfNecessary(
ClientHttpRequestFactory requestFactory) {
if (!(requestFactory instanceof AbstractClientHttpRequestFactoryWrapper)) {
return requestFactory;
}
ClientHttpRequestFactory unwrappedRequestFactory = requestFactory;
Field field = ReflectionUtils.findField(
AbstractClientHttpRequestFactoryWrapper.class, "requestFactory");
ReflectionUtils.makeAccessible(field);
do {
unwrappedRequestFactory = (ClientHttpRequestFactory) ReflectionUtils
.getField(field, unwrappedRequestFactory);
}
while (unwrappedRequestFactory instanceof AbstractClientHttpRequestFactoryWrapper);
return unwrappedRequestFactory;
}
private ClientHttpRequestFactory detectRequestFactory() { private ClientHttpRequestFactory detectRequestFactory() {
for (Map.Entry<String, String> candidate : REQUEST_FACTORY_CANDIDATES for (Map.Entry<String, String> candidate : REQUEST_FACTORY_CANDIDATES
.entrySet()) { .entrySet()) {
@ -429,6 +506,13 @@ public class RestTemplateBuilder {
return new SimpleClientHttpRequestFactory(); return new SimpleClientHttpRequestFactory();
} }
private <T> Set<T> append(Set<T> set, T addition) {
Set<T> result = new LinkedHashSet<T>(
set == null ? Collections.<T>emptySet() : set);
result.add(addition);
return Collections.unmodifiableSet(result);
}
private <T> Set<T> append(Set<T> set, Collection<? extends T> additions) { private <T> Set<T> append(Set<T> set, Collection<? extends T> additions) {
Set<T> result = new LinkedHashSet<T>( Set<T> result = new LinkedHashSet<T>(
set == null ? Collections.<T>emptySet() : set); set == null ? Collections.<T>emptySet() : set);
@ -436,4 +520,57 @@ public class RestTemplateBuilder {
return Collections.unmodifiableSet(result); return Collections.unmodifiableSet(result);
} }
private interface RequestFactoryCustomizer {
void customize(ClientHttpRequestFactory factory);
}
private static abstract class TimeoutConfiguringRequestFactoryCustomizer
implements RequestFactoryCustomizer {
private final int timeout;
private final String methodName;
TimeoutConfiguringRequestFactoryCustomizer(int timeout, String methodName) {
this.timeout = timeout;
this.methodName = methodName;
}
@Override
public void customize(ClientHttpRequestFactory factory) {
ReflectionUtils.invokeMethod(findMethod(factory), factory, this.timeout);
}
private Method findMethod(ClientHttpRequestFactory factory) {
Method method = ReflectionUtils.findMethod(factory.getClass(),
this.methodName, int.class);
if (method != null) {
return method;
}
throw new IllegalStateException("Request factory " + factory.getClass()
+ " does not have a " + this.methodName + "(int) method");
}
}
private static class ReadTimeoutRequestFactoryCustomizer
extends TimeoutConfiguringRequestFactoryCustomizer {
ReadTimeoutRequestFactoryCustomizer(int readTimeout) {
super(readTimeout, "setReadTimeout");
}
}
private static class ConnectTimeoutRequestFactoryCustomizer
extends TimeoutConfiguringRequestFactoryCustomizer {
ConnectTimeoutRequestFactoryCustomizer(int connectTimeout) {
super(connectTimeout, "setConnectTimeout");
}
}
} }

View File

@ -19,6 +19,8 @@ package org.springframework.boot.web.client;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import com.squareup.okhttp.OkHttpClient;
import org.apache.http.client.config.RequestConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -26,14 +28,19 @@ import org.junit.rules.ExpectedException;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.http.client.OkHttpClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.client.support.BasicAuthorizationInterceptor; import org.springframework.http.client.support.BasicAuthorizationInterceptor;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -53,6 +60,7 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
*/ */
public class RestTemplateBuilderTests { public class RestTemplateBuilderTests {
@ -356,6 +364,116 @@ public class RestTemplateBuilderTests {
.isInstanceOf(HttpComponentsClientHttpRequestFactory.class); .isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
} }
@Test
public void connectTimeoutCanBeConfiguredOnHttpComponentsRequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(HttpComponentsClientHttpRequestFactory.class)
.setConnectTimeout(1234).build().getRequestFactory();
assertThat(((RequestConfig) ReflectionTestUtils.getField(requestFactory,
"requestConfig")).getConnectTimeout()).isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnHttpComponentsRequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(HttpComponentsClientHttpRequestFactory.class)
.setReadTimeout(1234).build().getRequestFactory();
assertThat(((RequestConfig) ReflectionTestUtils.getField(requestFactory,
"requestConfig")).getSocketTimeout()).isEqualTo(1234);
}
@Test
public void connectTimeoutCanBeConfiguredOnSimpleRequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(SimpleClientHttpRequestFactory.class)
.setConnectTimeout(1234).build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(requestFactory, "connectTimeout"))
.isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnSimpleRequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(SimpleClientHttpRequestFactory.class).setReadTimeout(1234)
.build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(requestFactory, "readTimeout"))
.isEqualTo(1234);
}
@Test
public void connectTimeoutCanBeConfiguredOnNetty4RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(Netty4ClientHttpRequestFactory.class)
.setConnectTimeout(1234).build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(requestFactory, "connectTimeout"))
.isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnNetty4RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(Netty4ClientHttpRequestFactory.class).setReadTimeout(1234)
.build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(requestFactory, "readTimeout"))
.isEqualTo(1234);
}
@Test
public void connectTimeoutCanBeConfiguredOnOkHttp2RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(OkHttpClientHttpRequestFactory.class)
.setConnectTimeout(1234).build().getRequestFactory();
assertThat(((OkHttpClient) ReflectionTestUtils.getField(requestFactory, "client"))
.getConnectTimeout()).isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnOkHttp2RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(OkHttpClientHttpRequestFactory.class).setReadTimeout(1234)
.build().getRequestFactory();
assertThat(((OkHttpClient) ReflectionTestUtils.getField(requestFactory, "client"))
.getReadTimeout()).isEqualTo(1234);
}
@Test
public void connectTimeoutCanBeConfiguredOnOkHttp3RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(OkHttp3ClientHttpRequestFactory.class)
.setConnectTimeout(1234).build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(
ReflectionTestUtils.getField(requestFactory, "client"), "connectTimeout"))
.isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnOkHttp3RequestFactory() {
ClientHttpRequestFactory requestFactory = this.builder
.requestFactory(OkHttp3ClientHttpRequestFactory.class)
.setReadTimeout(1234).build().getRequestFactory();
assertThat(ReflectionTestUtils.getField(
ReflectionTestUtils.getField(requestFactory, "client"), "readTimeout"))
.isEqualTo(1234);
}
@Test
public void connectTimeoutCanBeConfiguredOnAWrappedRequestFactory() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
this.builder.requestFactory(new BufferingClientHttpRequestFactory(requestFactory))
.setConnectTimeout(1234).build();
assertThat(ReflectionTestUtils.getField(requestFactory, "connectTimeout"))
.isEqualTo(1234);
}
@Test
public void readTimeoutCanBeConfiguredOnAWrappedRequestFactory() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
this.builder.requestFactory(new BufferingClientHttpRequestFactory(requestFactory))
.setReadTimeout(1234).build();
assertThat(ReflectionTestUtils.getField(requestFactory, "readTimeout"))
.isEqualTo(1234);
}
public static class RestTemplateSubclass extends RestTemplate { public static class RestTemplateSubclass extends RestTemplate {
} }