Add RestTemplateBuilder support
Add a RestTemplateBuilder that allows RestTemplates to be easily created and configured. See gh-5507
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.test.web.client;
|
||||
|
||||
import org.springframework.boot.web.client.RootUriTemplateHandler;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.DefaultUriTemplateHandler;
|
||||
@@ -28,17 +29,18 @@ import org.springframework.web.util.UriTemplateHandler;
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class LocalHostUriTemplateHandler extends DefaultUriTemplateHandler {
|
||||
public class LocalHostUriTemplateHandler extends RootUriTemplateHandler {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
public LocalHostUriTemplateHandler(Environment environment) {
|
||||
super(new DefaultUriTemplateHandler());
|
||||
Assert.notNull(environment, "Environment must not be null");
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
public String getRootUri() {
|
||||
String port = this.environment.getProperty("local.server.port", "8080");
|
||||
return "http://localhost:" + port;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.boot.test.web.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -37,20 +36,18 @@ import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
|
||||
import org.springframework.boot.web.client.BasicAuthorizationInterceptor;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.InterceptingClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RequestCallback;
|
||||
@@ -76,8 +73,6 @@ import org.springframework.web.util.UriTemplateHandler;
|
||||
*/
|
||||
public class TestRestTemplate {
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
@@ -912,29 +907,6 @@ public class TestRestTemplate {
|
||||
|
||||
}
|
||||
|
||||
private static class BasicAuthorizationInterceptor
|
||||
implements ClientHttpRequestInterceptor {
|
||||
|
||||
private final String username;
|
||||
|
||||
private final String password;
|
||||
|
||||
BasicAuthorizationInterceptor(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = (password == null ? "" : password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
String token = Base64Utils.encodeToString(
|
||||
(this.username + ":" + this.password).getBytes(UTF_8));
|
||||
request.getHeaders().add("Authorization", "Basic " + token);
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link HttpComponentsClientHttpRequestFactory} to apply customizations.
|
||||
*/
|
||||
|
||||
@@ -47,7 +47,7 @@ public class LocalHostUriTemplateHandlerTests {
|
||||
environment.setProperty("local.server.port", "1234");
|
||||
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(
|
||||
environment);
|
||||
assertThat(handler.getBaseUrl()).isEqualTo("http://localhost:1234");
|
||||
assertThat(handler.getRootUri()).isEqualTo("http://localhost:1234");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -55,7 +55,7 @@ public class LocalHostUriTemplateHandlerTests {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(
|
||||
environment);
|
||||
assertThat(handler.getBaseUrl()).isEqualTo("http://localhost:8080");
|
||||
assertThat(handler.getRootUri()).isEqualTo("http://localhost:8080");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestInterceptor} to apply a BASIC authorization header.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class BasicAuthorizationInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private final String username;
|
||||
|
||||
private final String password;
|
||||
|
||||
public BasicAuthorizationInterceptor(String username, String password) {
|
||||
Assert.hasLength(username, "Username must not be empty");
|
||||
this.username = username;
|
||||
this.password = (password == null ? "" : password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
String token = Base64Utils
|
||||
.encodeToString((this.username + ":" + this.password).getBytes(UTF_8));
|
||||
request.getHeaders().add("Authorization", "Basic " + token);
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriTemplateHandler;
|
||||
|
||||
/**
|
||||
* Builder that can be used to configure and create a {@link RestTemplate}. Provides
|
||||
* convenience methods to register {@link #messageConverters(HttpMessageConverter...)
|
||||
* converters}, {@link #errorHandler(ResponseErrorHandler) error handlers} and
|
||||
* {@link #uriTemplateHandler(UriTemplateHandler) UriTemplateHandlers}.
|
||||
* <p>
|
||||
* By default the built {@link RestTemplate} will attempt to use the most suitable
|
||||
* {@link ClientHttpRequestFactory}, call {@link #detectRequestFactory(boolean)
|
||||
* detectRequestFactory(false)} if you prefer to keep the default. In a typical
|
||||
* auto-configured Spring Boot application this builder is available as a bean and can be
|
||||
* injected whenever a {@link RestTemplate} is needed.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class RestTemplateBuilder {
|
||||
|
||||
private static final Map<String, String> REQUEST_FACTORY_CANDIDATES;
|
||||
|
||||
static {
|
||||
Map<String, String> candidates = new LinkedHashMap<String, String>();
|
||||
candidates.put("org.apache.http.client.HttpClient",
|
||||
"org.springframework.http.client.HttpComponentsClientHttpRequestFactory");
|
||||
candidates.put("okhttp3.OkHttpClient",
|
||||
"org.springframework.http.client.OkHttp3ClientHttpRequestFactory");
|
||||
candidates.put("com.squareup.okhttp.OkHttpClient",
|
||||
"org.springframework.http.client.OkHttpClientHttpRequestFactory");
|
||||
candidates.put("io.netty.channel.EventLoopGroup",
|
||||
"org.springframework.http.client.Netty4ClientHttpRequestFactory");
|
||||
REQUEST_FACTORY_CANDIDATES = Collections.unmodifiableMap(candidates);
|
||||
}
|
||||
|
||||
private final boolean detectRequestFactory;
|
||||
|
||||
private final String rootUri;
|
||||
|
||||
private final Set<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private final ClientHttpRequestFactory requestFactory;
|
||||
|
||||
private final UriTemplateHandler uriTemplateHandler;
|
||||
|
||||
private final ResponseErrorHandler errorHandler;
|
||||
|
||||
private final BasicAuthorizationInterceptor basicAuthorization;
|
||||
|
||||
private final Set<RestTemplateCustomizer> customizers;
|
||||
|
||||
/**
|
||||
* Create a new {@link RestTemplateBuilder} instance.
|
||||
* @param customizers any {@link RestTemplateCustomizer RestTemplateCustomizers} that
|
||||
* should be applied when the {@link RestTemplate} is built
|
||||
*/
|
||||
public RestTemplateBuilder(RestTemplateCustomizer... customizers) {
|
||||
Assert.notNull(customizers, "Customizers must not be null");
|
||||
this.detectRequestFactory = true;
|
||||
this.rootUri = null;
|
||||
this.messageConverters = null;
|
||||
this.requestFactory = null;
|
||||
this.uriTemplateHandler = null;
|
||||
this.errorHandler = null;
|
||||
this.basicAuthorization = null;
|
||||
this.customizers = Collections.unmodifiableSet(
|
||||
new LinkedHashSet<RestTemplateCustomizer>(Arrays.asList(customizers)));
|
||||
}
|
||||
|
||||
private RestTemplateBuilder(boolean detectRequestFactory, String rootUri,
|
||||
Set<HttpMessageConverter<?>> messageConverters,
|
||||
ClientHttpRequestFactory requestFactory,
|
||||
UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler,
|
||||
BasicAuthorizationInterceptor basicAuthorization,
|
||||
Set<RestTemplateCustomizer> customizers) {
|
||||
super();
|
||||
this.detectRequestFactory = detectRequestFactory;
|
||||
this.rootUri = rootUri;
|
||||
this.messageConverters = messageConverters;
|
||||
this.requestFactory = requestFactory;
|
||||
this.uriTemplateHandler = uriTemplateHandler;
|
||||
this.errorHandler = errorHandler;
|
||||
this.basicAuthorization = basicAuthorization;
|
||||
this.customizers = customizers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the {@link ClientHttpRequestFactory} should be detected based on the
|
||||
* classpath. Default if {@code true}.
|
||||
* @param detectRequestFactory if the {@link ClientHttpRequestFactory} should be
|
||||
* detected
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder detectRequestFactory(boolean detectRequestFactory) {
|
||||
return new RestTemplateBuilder(detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a root URL that should be applied to each request that starts with {@code '/'}.
|
||||
* See {@link RootUriTemplateHandler} for details.
|
||||
* @param rootUri the root URI or {@code null}
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder rootUri(String rootUri) {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HttpMessageConverter HttpMessageConverters} that should be used with
|
||||
* the {@link RestTemplate}. Setting this value will replace any previously calls.
|
||||
* @param messageConverters the converters to set
|
||||
* @return a new builder instance
|
||||
* @see #additionalMessageConverters(HttpMessageConverter...)
|
||||
*/
|
||||
public RestTemplateBuilder messageConverters(
|
||||
HttpMessageConverter<?>... messageConverters) {
|
||||
Assert.notNull(messageConverters, "MessageConverters must not be null");
|
||||
return messageConverters(Arrays.asList(messageConverters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HttpMessageConverter HttpMessageConverters} that should be used with
|
||||
* the {@link RestTemplate}. Setting this value will replace any previously calls.
|
||||
* @param messageConverters the converters to set
|
||||
* @return a new builder instance
|
||||
* @see #additionalMessageConverters(HttpMessageConverter...)
|
||||
*/
|
||||
public RestTemplateBuilder messageConverters(
|
||||
Collection<? extends HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notNull(messageConverters, "MessageConverters must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
Collections.unmodifiableSet(
|
||||
new LinkedHashSet<HttpMessageConverter<?>>(messageConverters)),
|
||||
this.requestFactory, this.uriTemplateHandler, this.errorHandler,
|
||||
this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional {@link HttpMessageConverter HttpMessageConverters} that should be
|
||||
* used with the {@link RestTemplate}.
|
||||
* @param messageConverters the converters to add
|
||||
* @return a new builder instance
|
||||
* @see #messageConverters(HttpMessageConverter...)
|
||||
*/
|
||||
public RestTemplateBuilder additionalMessageConverters(
|
||||
HttpMessageConverter<?>... messageConverters) {
|
||||
Assert.notNull(messageConverters, "MessageConverters must not be null");
|
||||
return additionalMessageConverters(Arrays.asList(messageConverters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional {@link HttpMessageConverter HttpMessageConverters} that should be
|
||||
* used with the {@link RestTemplate}.
|
||||
* @param messageConverters the converters to add
|
||||
* @return a new builder instance
|
||||
* @see #messageConverters(HttpMessageConverter...)
|
||||
*/
|
||||
public RestTemplateBuilder additionalMessageConverters(
|
||||
Collection<? extends HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notNull(messageConverters, "MessageConverters must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
append(this.messageConverters, messageConverters), this.requestFactory,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HttpMessageConverter HttpMessageConverters} that should be used with
|
||||
* the {@link RestTemplate} to the default set. Calling this method will replace any
|
||||
* previously defined converters.
|
||||
* @return a new builder instance
|
||||
* @see #messageConverters(HttpMessageConverter...)
|
||||
*/
|
||||
public RestTemplateBuilder defaultMessageConverters() {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
Collections.unmodifiableSet(new LinkedHashSet<HttpMessageConverter<?>>(
|
||||
new RestTemplate().getMessageConverters())),
|
||||
this.requestFactory, this.uriTemplateHandler, this.errorHandler,
|
||||
this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ClientHttpRequestFactory} class that should be used with the
|
||||
* {@link RestTemplate}.
|
||||
* @param requestFactory the request factory to use
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder requestFactory(
|
||||
Class<? extends ClientHttpRequestFactory> requestFactory) {
|
||||
Assert.notNull(requestFactory, "RequestFactory must not be null");
|
||||
return requestFactory(BeanUtils.instantiate(requestFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ClientHttpRequestFactory} that should be used with the
|
||||
* {@link RestTemplate}.
|
||||
* @param requestFactory the request factory to use
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder requestFactory(ClientHttpRequestFactory requestFactory) {
|
||||
Assert.notNull(requestFactory, "RequestFactory must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link UriTemplateHandler} that should be used with the
|
||||
* {@link RestTemplate}.
|
||||
* @param uriTemplateHandler the URI template handler to use
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder uriTemplateHandler(UriTemplateHandler uriTemplateHandler) {
|
||||
Assert.notNull(uriTemplateHandler, "UriTemplateHandler must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ResponseErrorHandler} that should be used with the
|
||||
* {@link RestTemplate}.
|
||||
* @param errorHandler the error hander to use
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder errorHandler(ResponseErrorHandler errorHandler) {
|
||||
Assert.notNull(errorHandler, "ErrorHandler must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
errorHandler, this.basicAuthorization, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add HTTP basic authentication to requests. See
|
||||
* {@link BasicAuthorizationInterceptor} for details.
|
||||
* @param username the user name
|
||||
* @param password the password
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public RestTemplateBuilder basicAuthorization(String username, String password) {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, new BasicAuthorizationInterceptor(username, password),
|
||||
this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HttpMessageConverter HttpMessageConverters} that should be applied
|
||||
* to the {@link RestTemplate}. Customizers are applied in the order that they were
|
||||
* added after builder configuration has been applied. Setting this value will replace
|
||||
* any previously configured customizers.
|
||||
* @param restTemplateCustomizers the customizers to set
|
||||
* @return a new builder instance
|
||||
* @see #additionalCustomizers(RestTemplateCustomizer...)
|
||||
*/
|
||||
public RestTemplateBuilder customizers(
|
||||
RestTemplateCustomizer... restTemplateCustomizers) {
|
||||
Assert.notNull(restTemplateCustomizers,
|
||||
"RestTemplateCustomizers must not be null");
|
||||
return customizers(Arrays.asList(restTemplateCustomizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HttpMessageConverter HttpMessageConverters} that should be applied
|
||||
* to the {@link RestTemplate}. Customizers are applied in the order that they were
|
||||
* added after builder configuration has been applied. Setting this value will replace
|
||||
* any previously configured customizers.
|
||||
* @param restTemplateCustomizers the customizers to set
|
||||
* @return a new builder instance
|
||||
* @see #additionalCustomizers(RestTemplateCustomizer...)
|
||||
*/
|
||||
public RestTemplateBuilder customizers(
|
||||
Collection<? extends RestTemplateCustomizer> restTemplateCustomizers) {
|
||||
Assert.notNull(restTemplateCustomizers,
|
||||
"RestTemplateCustomizers must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization,
|
||||
Collections.unmodifiableSet(new LinkedHashSet<RestTemplateCustomizer>(
|
||||
restTemplateCustomizers)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link HttpMessageConverter HttpMessageConverters} that should be applied to
|
||||
* the {@link RestTemplate}. Customizers are applied in the order that they were added
|
||||
* after builder configuration has been applied.
|
||||
* @param restTemplateCustomizers the customizers to add
|
||||
* @return a new builder instance
|
||||
* @see #customizers(RestTemplateCustomizer...)
|
||||
*/
|
||||
public RestTemplateBuilder additionalCustomizers(
|
||||
RestTemplateCustomizer... restTemplateCustomizers) {
|
||||
Assert.notNull(restTemplateCustomizers,
|
||||
"RestTemplateCustomizers must not be null");
|
||||
return additionalCustomizers(Arrays.asList(restTemplateCustomizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link HttpMessageConverter HttpMessageConverters} that should be applied to
|
||||
* the {@link RestTemplate}. Customizers are applied in the order that they were added
|
||||
* after builder configuration has been applied.
|
||||
* @param customizers the customizers to add
|
||||
* @return a new builder instance
|
||||
* @see #customizers(RestTemplateCustomizer...)
|
||||
*/
|
||||
public RestTemplateBuilder additionalCustomizers(
|
||||
Collection<? extends RestTemplateCustomizer> customizers) {
|
||||
Assert.notNull(customizers, "RestTemplateCustomizers must not be null");
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactory, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization,
|
||||
append(this.customizers, customizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link RestTemplate} instance and configure it using this builder.
|
||||
* @return a configured {@link RestTemplate} instance.
|
||||
* @see #build(Class)
|
||||
* @see #configure(RestTemplate)
|
||||
*/
|
||||
public RestTemplate build() {
|
||||
return build(RestTemplate.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link RestTemplate} instance of the specified type and configure it
|
||||
* using this builder.
|
||||
* @param <T> the type of rest template
|
||||
* @param restTemplateClass the template type to create
|
||||
* @return a configured {@link RestTemplate} instance.
|
||||
* @see RestTemplateBuilder#build()
|
||||
* @see #configure(RestTemplate)
|
||||
*/
|
||||
|
||||
public <T extends RestTemplate> T build(Class<T> restTemplateClass) {
|
||||
return configure(BeanUtils.instantiate(restTemplateClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the provided {@link RestTemplate} instance using this builder.
|
||||
* @param <T> the type of rest template
|
||||
* @param restTemplate the {@link RestTemplate} to configure
|
||||
* @return the rest template instance
|
||||
* @see RestTemplateBuilder#build()
|
||||
* @see RestTemplateBuilder#build(Class)
|
||||
*/
|
||||
public <T extends RestTemplate> T configure(T restTemplate) {
|
||||
if (this.requestFactory != null) {
|
||||
restTemplate.setRequestFactory(this.requestFactory);
|
||||
}
|
||||
else if (this.detectRequestFactory) {
|
||||
restTemplate.setRequestFactory(detectRequestFactory());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.messageConverters)) {
|
||||
restTemplate.setMessageConverters(
|
||||
new ArrayList<HttpMessageConverter<?>>(this.messageConverters));
|
||||
}
|
||||
if (this.uriTemplateHandler != null) {
|
||||
restTemplate.setUriTemplateHandler(this.uriTemplateHandler);
|
||||
}
|
||||
if (this.errorHandler != null) {
|
||||
restTemplate.setErrorHandler(this.errorHandler);
|
||||
}
|
||||
if (this.rootUri != null) {
|
||||
RootUriTemplateHandler.addTo(restTemplate, this.rootUri);
|
||||
}
|
||||
if (this.basicAuthorization != null) {
|
||||
restTemplate.getInterceptors().add(this.basicAuthorization);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.customizers)) {
|
||||
for (RestTemplateCustomizer customizer : this.customizers) {
|
||||
customizer.customize(restTemplate);
|
||||
}
|
||||
}
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
private ClientHttpRequestFactory detectRequestFactory() {
|
||||
for (Map.Entry<String, String> candidate : REQUEST_FACTORY_CANDIDATES
|
||||
.entrySet()) {
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
if (ClassUtils.isPresent(candidate.getKey(), classLoader)) {
|
||||
Class<?> factoryClass = ClassUtils.resolveClassName(candidate.getValue(),
|
||||
classLoader);
|
||||
return (ClientHttpRequestFactory) BeanUtils.instantiate(factoryClass);
|
||||
}
|
||||
}
|
||||
return new SimpleClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
private <T> Set<T> append(Set<T> set, Collection<? extends T> additions) {
|
||||
Set<T> result = new LinkedHashSet<T>(
|
||||
set == null ? Collections.<T>emptySet() : set);
|
||||
result.addAll(additions);
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Callback interface that can be used to customize a {@link RestTemplate}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
* @see RestTemplateBuilder
|
||||
*/
|
||||
public interface RestTemplateCustomizer {
|
||||
|
||||
/**
|
||||
* Callback to customize a {@link RestTemplate} instance.
|
||||
* @param restTemplate the template to customize
|
||||
*/
|
||||
void customize(RestTemplate restTemplate);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.DefaultUriTemplateHandler;
|
||||
import org.springframework.web.util.UriTemplateHandler;
|
||||
|
||||
/**
|
||||
* {@link UriTemplateHandler} to set the root for URI that start with {@code '/'}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class RootUriTemplateHandler implements UriTemplateHandler {
|
||||
|
||||
private final String rootUri;
|
||||
|
||||
private final UriTemplateHandler handler;
|
||||
|
||||
protected RootUriTemplateHandler(UriTemplateHandler handler) {
|
||||
this.rootUri = null;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RootUriTemplateHandler} instance.
|
||||
* @param rootUri the root URI to used to prefix relative URLs
|
||||
*/
|
||||
public RootUriTemplateHandler(String rootUri) {
|
||||
this(rootUri, new DefaultUriTemplateHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RootUriTemplateHandler} instance.
|
||||
* @param rootUri the root URI to used to prefix relative URLs
|
||||
* @param handler the delegate handler
|
||||
*/
|
||||
public RootUriTemplateHandler(String rootUri, UriTemplateHandler handler) {
|
||||
Assert.notNull(rootUri, "RootUri must not be null");
|
||||
Assert.notNull(handler, "Handler must not be null");
|
||||
this.rootUri = rootUri;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI expand(String uriTemplate, Map<String, ?> uriVariables) {
|
||||
return this.handler.expand(apply(uriTemplate), uriVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI expand(String uriTemplate, Object... uriVariables) {
|
||||
return this.handler.expand(apply(uriTemplate), uriVariables);
|
||||
}
|
||||
|
||||
private String apply(String uriTemplate) {
|
||||
if (StringUtils.startsWithIgnoreCase(uriTemplate, "/")) {
|
||||
return getRootUri() + uriTemplate;
|
||||
}
|
||||
return uriTemplate;
|
||||
}
|
||||
|
||||
public String getRootUri() {
|
||||
return this.rootUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link RootUriTemplateHandler} instance to the given {@link RestTemplate}.
|
||||
* @param restTemplate the {@link RestTemplate} to add the handler to
|
||||
* @param rootUri the root URI
|
||||
* @return the added {@link RootUriTemplateHandler}.
|
||||
*/
|
||||
public static RootUriTemplateHandler addTo(RestTemplate restTemplate,
|
||||
String rootUri) {
|
||||
Assert.notNull(restTemplate, "RestTemplate must not be null");
|
||||
RootUriTemplateHandler handler = new RootUriTemplateHandler(rootUri,
|
||||
restTemplate.getUriTemplateHandler());
|
||||
restTemplate.setUriTemplateHandler(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link BasicAuthorizationInterceptor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class BasicAuthorizationInterceptorTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createWhenUsernameIsNullShouldThrowException() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Username must not be empty");
|
||||
new BasicAuthorizationInterceptor(null, "password");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenUsernameIsEmptyShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Username must not be empty");
|
||||
new BasicAuthorizationInterceptor("", "password");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenPasswordIsNullShouldUseEmptyPassword() throws Exception {
|
||||
BasicAuthorizationInterceptor interceptor = new BasicAuthorizationInterceptor(
|
||||
"username", "");
|
||||
assertThat(interceptor).extracting("password").containsExactly("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interceptShouldAddHeader() throws Exception {
|
||||
MockClientHttpRequest request = new MockClientHttpRequest();
|
||||
ClientHttpRequestExecution execution = mock(ClientHttpRequestExecution.class);
|
||||
byte[] body = new byte[] {};
|
||||
new BasicAuthorizationInterceptor("spring", "boot").intercept(request, body,
|
||||
execution);
|
||||
verify(execution).execute(request, body);
|
||||
assertThat(request.getHeaders().getFirst("Authorization"))
|
||||
.isEqualTo("Basic c3ByaW5nOmJvb3Q=");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriTemplateHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestTemplateBuilder}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RestTemplateBuilderTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
|
||||
@Mock
|
||||
private HttpMessageConverter<Object> messageConverter;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenCustomizersAreNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Customizers must not be null");
|
||||
RestTemplateCustomizer[] customizers = null;
|
||||
new RestTemplateBuilder(customizers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithCustomizersShouldApplyCustomizers() throws Exception {
|
||||
RestTemplateCustomizer customizer = mock(RestTemplateCustomizer.class);
|
||||
RestTemplate template = new RestTemplateBuilder(customizer).build();
|
||||
verify(customizer).customize(template);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildShouldDetectRequestFactory() throws Exception {
|
||||
RestTemplate restTemplate = this.builder.build();
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectRequestFactoryWhenFalseShouldDisableDetection() throws Exception {
|
||||
RestTemplate restTemplate = this.builder.detectRequestFactory(false).build();
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SimpleClientHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rootUriShouldApply() throws Exception {
|
||||
RestTemplate restTemplate = this.builder.rootUri("http://example.com").build();
|
||||
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();
|
||||
server.expect(requestTo("http://example.com/hello")).andRespond(withSuccess());
|
||||
restTemplate.getForEntity("/hello", String.class);
|
||||
server.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rootUriShouldApplyAfterUriTemplateHandler() throws Exception {
|
||||
UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class);
|
||||
RestTemplate template = this.builder.uriTemplateHandler(uriTemplateHandler)
|
||||
.rootUri("http://example.com").build();
|
||||
UriTemplateHandler handler = template.getUriTemplateHandler();
|
||||
handler.expand("/hello");
|
||||
assertThat(handler).isInstanceOf(RootUriTemplateHandler.class);
|
||||
verify(uriTemplateHandler).expand("http://example.com/hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageConvertersWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("MessageConverters must not be null");
|
||||
this.builder.messageConverters((HttpMessageConverter<?>[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageConvertersCollectionWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("MessageConverters must not be null");
|
||||
this.builder.messageConverters((Set<HttpMessageConverter<?>>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageConvertersShouldApply() throws Exception {
|
||||
RestTemplate template = this.builder.messageConverters(this.messageConverter)
|
||||
.build();
|
||||
assertThat(template.getMessageConverters()).containsOnly(this.messageConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageConvertersShouldRepalceExisting() throws Exception {
|
||||
RestTemplate template = this.builder
|
||||
.messageConverters(new ResourceHttpMessageConverter())
|
||||
.messageConverters(Collections.singleton(this.messageConverter)).build();
|
||||
assertThat(template.getMessageConverters()).containsOnly(this.messageConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalMessageConvertersWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("MessageConverters must not be null");
|
||||
this.builder.additionalMessageConverters((HttpMessageConverter<?>[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalMessageConvertersCollectionWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("MessageConverters must not be null");
|
||||
this.builder.additionalMessageConverters((Set<HttpMessageConverter<?>>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalMessageConvertersShouldAddToExisting() throws Exception {
|
||||
HttpMessageConverter<?> resourceConverter = new ResourceHttpMessageConverter();
|
||||
RestTemplate template = this.builder.messageConverters(resourceConverter)
|
||||
.additionalMessageConverters(this.messageConverter).build();
|
||||
assertThat(template.getMessageConverters()).containsOnly(resourceConverter,
|
||||
this.messageConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageConvertersShouldSetDefaultList() throws Exception {
|
||||
RestTemplate template = new RestTemplate(
|
||||
Collections.<HttpMessageConverter<?>>singletonList(
|
||||
new StringHttpMessageConverter()));
|
||||
this.builder.defaultMessageConverters().configure(template);
|
||||
assertThat(template.getMessageConverters())
|
||||
.hasSameSizeAs(new RestTemplate().getMessageConverters());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageConvertersShouldClearExisting() throws Exception {
|
||||
RestTemplate template = new RestTemplate(
|
||||
Collections.<HttpMessageConverter<?>>singletonList(
|
||||
new StringHttpMessageConverter()));
|
||||
this.builder.additionalMessageConverters(this.messageConverter)
|
||||
.defaultMessageConverters().configure(template);
|
||||
assertThat(template.getMessageConverters())
|
||||
.hasSameSizeAs(new RestTemplate().getMessageConverters());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryClassWhenFactoryIsNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RequestFactory must not be null");
|
||||
this.builder.requestFactory((Class<ClientHttpRequestFactory>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryClassShouldApply() throws Exception {
|
||||
RestTemplate template = this.builder
|
||||
.requestFactory(SimpleClientHttpRequestFactory.class).build();
|
||||
assertThat(template.getRequestFactory())
|
||||
.isInstanceOf(SimpleClientHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryWhenFactoryIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RequestFactory must not be null");
|
||||
this.builder.requestFactory((ClientHttpRequestFactory) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryShouldApply() throws Exception {
|
||||
ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class);
|
||||
RestTemplate template = this.builder.requestFactory(requestFactory).build();
|
||||
assertThat(template.getRequestFactory()).isSameAs(requestFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uriTemplateHandlerWhenHandlerIsNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("UriTemplateHandler must not be null");
|
||||
this.builder.uriTemplateHandler(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uriTemplateHandlerShouldApply() throws Exception {
|
||||
UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class);
|
||||
RestTemplate template = this.builder.uriTemplateHandler(uriTemplateHandler)
|
||||
.build();
|
||||
assertThat(template.getUriTemplateHandler()).isSameAs(uriTemplateHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorHandlerWhenHandlerIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ErrorHandler must not be null");
|
||||
this.builder.errorHandler(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorHandlerShouldApply() throws Exception {
|
||||
ResponseErrorHandler errorHandler = mock(ResponseErrorHandler.class);
|
||||
RestTemplate template = this.builder.errorHandler(errorHandler).build();
|
||||
assertThat(template.getErrorHandler()).isSameAs(errorHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthorizationShouldApply() throws Exception {
|
||||
RestTemplate template = this.builder.basicAuthorization("spring", "boot").build();
|
||||
ClientHttpRequestInterceptor interceptor = template.getInterceptors().get(0);
|
||||
assertThat(interceptor).isInstanceOf(BasicAuthorizationInterceptor.class);
|
||||
assertThat(interceptor).extracting("username").containsExactly("spring");
|
||||
assertThat(interceptor).extracting("password").containsExactly("boot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersWhenNullArrayShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Customizers must not be null");
|
||||
RestTemplateCustomizer[] customizers = null;
|
||||
this.builder.customizers(customizers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersWhenConvertersAreNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RestTemplateCustomizers must not be null");
|
||||
this.builder.customizers((RestTemplateCustomizer[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersCollectionWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RestTemplateCustomizers must not be null");
|
||||
this.builder.customizers((Set<RestTemplateCustomizer>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersShouldApply() throws Exception {
|
||||
RestTemplateCustomizer customizer = mock(RestTemplateCustomizer.class);
|
||||
RestTemplate template = this.builder.customizers(customizer).build();
|
||||
verify(customizer).customize(template);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersShouldBeAppliedLast() throws Exception {
|
||||
RestTemplate template = spy(new RestTemplate());
|
||||
this.builder.additionalCustomizers(new RestTemplateCustomizer() {
|
||||
|
||||
@Override
|
||||
public void customize(RestTemplate restTemplate) {
|
||||
verify(restTemplate).setRequestFactory((ClientHttpRequestFactory) any());
|
||||
}
|
||||
|
||||
});
|
||||
this.builder.configure(template);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizersShouldRepalceExisting() throws Exception {
|
||||
RestTemplateCustomizer customizer1 = mock(RestTemplateCustomizer.class);
|
||||
RestTemplateCustomizer customizer2 = mock(RestTemplateCustomizer.class);
|
||||
RestTemplate template = this.builder.customizers(customizer1)
|
||||
.customizers(Collections.singleton(customizer2)).build();
|
||||
verifyZeroInteractions(customizer1);
|
||||
verify(customizer2).customize(template);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalCustomizersWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RestTemplateCustomizers must not be null");
|
||||
this.builder.additionalCustomizers((RestTemplateCustomizer[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalCustomizersCollectionWhenConvertersAreNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RestTemplateCustomizers must not be null");
|
||||
this.builder.additionalCustomizers((Set<RestTemplateCustomizer>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalCustomizersShouldAddToExisting() throws Exception {
|
||||
RestTemplateCustomizer customizer1 = mock(RestTemplateCustomizer.class);
|
||||
RestTemplateCustomizer customizer2 = mock(RestTemplateCustomizer.class);
|
||||
RestTemplate template = this.builder.customizers(customizer1)
|
||||
.additionalCustomizers(customizer2).build();
|
||||
verify(customizer1).customize(template);
|
||||
verify(customizer2).customize(template);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildShouldReturnRestTemplate() throws Exception {
|
||||
RestTemplate template = this.builder.build();
|
||||
assertThat(template.getClass()).isEqualTo(RestTemplate.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClassShouldReturnClassInstance() throws Exception {
|
||||
RestTemplateSubclass template = this.builder.build(RestTemplateSubclass.class);
|
||||
assertThat(template.getClass()).isEqualTo(RestTemplateSubclass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureShouldApply() throws Exception {
|
||||
RestTemplate template = new RestTemplate();
|
||||
this.builder.configure(template);
|
||||
assertThat(template.getRequestFactory())
|
||||
.isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
public static class RestTemplateSubclass extends RestTemplate {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriTemplateHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.anyVararg;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link RootUriTemplateHandler}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RootUriTemplateHandlerTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private URI uri;
|
||||
|
||||
@Mock
|
||||
public UriTemplateHandler delegate;
|
||||
|
||||
public UriTemplateHandler handler;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setup() throws URISyntaxException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.uri = new URI("http://example.com/hello");
|
||||
this.handler = new RootUriTemplateHandler("http://example.com", this.delegate);
|
||||
given(this.delegate.expand(anyString(), anyMap())).willReturn(this.uri);
|
||||
given(this.delegate.expand(anyString(), (Object[]) anyVararg()))
|
||||
.willReturn(this.uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithNullRootUriShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("RootUri must not be null");
|
||||
new RootUriTemplateHandler((String) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithNullHandlerShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Handler must not be null");
|
||||
new RootUriTemplateHandler("http://example.com", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expandMapVariablesShouldPrefixRoot() throws Exception {
|
||||
HashMap<String, Object> uriVariables = new HashMap<String, Object>();
|
||||
URI expanded = this.handler.expand("/hello", uriVariables);
|
||||
verify(this.delegate).expand("http://example.com/hello", uriVariables);
|
||||
assertThat(expanded).isEqualTo(this.uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expandMapVariablesWhenPathDoesNotStartWithSlashShouldNotPrefixRoot()
|
||||
throws Exception {
|
||||
HashMap<String, Object> uriVariables = new HashMap<String, Object>();
|
||||
URI expanded = this.handler.expand("http://spring.io/hello", uriVariables);
|
||||
verify(this.delegate).expand("http://spring.io/hello", uriVariables);
|
||||
assertThat(expanded).isEqualTo(this.uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expandArrayVariablesShouldPrefixRoot() throws Exception {
|
||||
Object[] uriVariables = new Object[0];
|
||||
URI expanded = this.handler.expand("/hello", uriVariables);
|
||||
verify(this.delegate).expand("http://example.com/hello", uriVariables);
|
||||
assertThat(expanded).isEqualTo(this.uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expandArrayVariablesWhenPathDoesNotStartWithSlashShouldNotPrefixRoot()
|
||||
throws Exception {
|
||||
Object[] uriVariables = new Object[0];
|
||||
URI expanded = this.handler.expand("http://spring.io/hello", uriVariables);
|
||||
verify(this.delegate).expand("http://spring.io/hello", uriVariables);
|
||||
assertThat(expanded).isEqualTo(this.uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyShouldWrapExistingTemplate() throws Exception {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setUriTemplateHandler(this.delegate);
|
||||
this.handler = RootUriTemplateHandler.addTo(restTemplate, "http://example.com");
|
||||
Object[] uriVariables = new Object[0];
|
||||
URI expanded = this.handler.expand("/hello", uriVariables);
|
||||
verify(this.delegate).expand("http://example.com/hello", uriVariables);
|
||||
assertThat(expanded).isEqualTo(this.uri);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user