From 4010a7cf7cfaa3ecc3ef12d9f541cd69e2ddc320 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Fri, 12 Mar 2021 18:31:25 -0500 Subject: [PATCH] Adds support for Tls to config data. Moves common setup to new ConfigClientRequestTemplateFactory class that was replicated between two implementations. Fixes gh-1689 --- .../tls/ConfigClientConfigDataTlsTests.java | 35 ++++ .../client/tls/ConfigClientTlsTests.java | 16 +- .../client/tls/TlsConfigClientRunner.java | 6 +- .../ConfigClientRequestTemplateFactory.java | 151 ++++++++++++++++++ .../client/ConfigServerConfigDataLoader.java | 22 +-- ...onfigServerConfigDataLocationResolver.java | 38 ++--- .../ConfigServicePropertySourceLocator.java | 115 ++----------- ...nfigServicePropertySourceLocatorTests.java | 29 ++-- 8 files changed, 245 insertions(+), 167 deletions(-) create mode 100644 spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientConfigDataTlsTests.java create mode 100644 spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java diff --git a/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientConfigDataTlsTests.java b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientConfigDataTlsTests.java new file mode 100644 index 00000000..a23c4445 --- /dev/null +++ b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientConfigDataTlsTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2020 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 + * + * https://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.cloud.config.client.tls; + +public class ConfigClientConfigDataTlsTests extends ConfigClientTlsTests { + + @Override + protected TlsConfigClientRunner createConfigClient(boolean optional) { + String importValue = "configserver:"; + if (optional) { + importValue = "optional:" + importValue; + } + return new TlsConfigClientRunner(TestApp.class, server, "spring.config.import", importValue); + } + + @Override + protected TlsConfigClientRunner createConfigClient() { + return new TlsConfigClientRunner(TestApp.class, server, "spring.config.import", "optional:configserver:"); + } + +} diff --git a/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientTlsTests.java b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientTlsTests.java index f87cd9e0..3a84c8b3 100644 --- a/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientTlsTests.java +++ b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/ConfigClientTlsTests.java @@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class ConfigClientTlsTests extends AbstractTlsSetup { - private static TlsConfigServerRunner server; + protected static TlsConfigServerRunner server; @BeforeClass public static void setupAll() throws Exception { @@ -95,7 +95,7 @@ public class ConfigClientTlsTests extends AbstractTlsSetup { @Test(expected = IllegalStateException.class) public void wrongPasswordCauseFailure() { - TlsConfigClientRunner client = createConfigClient(); + TlsConfigClientRunner client = createConfigClient(false); enableTlsClient(client); client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD); client.start(); @@ -103,7 +103,7 @@ public class ConfigClientTlsTests extends AbstractTlsSetup { @Test(expected = IllegalStateException.class) public void nonExistKeyStoreCauseFailure() { - TlsConfigClientRunner client = createConfigClient(); + TlsConfigClientRunner client = createConfigClient(false); enableTlsClient(client); client.setKeyStore(new File("nonExistFile")); client.start(); @@ -119,7 +119,15 @@ public class ConfigClientTlsTests extends AbstractTlsSetup { } } - private TlsConfigClientRunner createConfigClient() { + protected TlsConfigClientRunner createConfigClient(boolean optional) { + TlsConfigClientRunner runner = createConfigClient(); + if (!optional) { + runner.property("spring.cloud.config.fail-fast", "true"); + } + return runner; + } + + protected TlsConfigClientRunner createConfigClient() { return new TlsConfigClientRunner(TestApp.class, server); } diff --git a/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/TlsConfigClientRunner.java b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/TlsConfigClientRunner.java index fba12d5d..6fcf223c 100644 --- a/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/TlsConfigClientRunner.java +++ b/spring-cloud-config-client-tls-tests/src/test/java/org/springframework/cloud/config/client/tls/TlsConfigClientRunner.java @@ -21,11 +21,15 @@ import java.io.File; public class TlsConfigClientRunner extends AppRunner { public TlsConfigClientRunner(Class appClass, AppRunner server) { + this(appClass, server, "spring.config.use-legacy-processing", "true"); + } + + public TlsConfigClientRunner(Class appClass, AppRunner server, String importKey, String importValue) { super(appClass); property("spring.cloud.config.uri", server.root()); property("spring.cloud.config.enabled", "true"); - property("spring.config.use-legacy-processing", "true"); + property(importKey, importValue); } public void enableTls() { diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java new file mode 100644 index 00000000..8692ac70 --- /dev/null +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java @@ -0,0 +1,151 @@ +/* + * Copyright 2013-2021 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 + * + * https://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.cloud.config.client; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.net.ssl.SSLContext; + +import org.apache.commons.logging.Log; +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClients; + +import org.springframework.cloud.configuration.SSLContextFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.util.Base64Utils; +import org.springframework.web.client.RestTemplate; + +import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION; + +public class ConfigClientRequestTemplateFactory { + + private final Log log; + + private final ConfigClientProperties properties; + + public ConfigClientRequestTemplateFactory(Log log, ConfigClientProperties properties) { + this.log = log; + this.properties = properties; + } + + public Log getLog() { + return this.log; + } + + public ConfigClientProperties getProperties() { + return this.properties; + } + + public RestTemplate create() { + if (properties.getRequestReadTimeout() < 0) { + throw new IllegalStateException("Invalid Value for Read Timeout set."); + } + if (properties.getRequestConnectTimeout() < 0) { + throw new IllegalStateException("Invalid Value for Connect Timeout set."); + } + + ClientHttpRequestFactory requestFactory = createHttpRequestFactory(properties); + RestTemplate template = new RestTemplate(requestFactory); + Map headers = new HashMap<>(properties.getHeaders()); + headers.remove(AUTHORIZATION); // To avoid redundant addition of header + if (!headers.isEmpty()) { + template.setInterceptors(Arrays.asList(new GenericRequestHeaderInterceptor(headers))); + } + + return template; + } + + private ClientHttpRequestFactory createHttpRequestFactory(ConfigClientProperties client) { + if (client.getTls().isEnabled()) { + try { + SSLContextFactory factory = new SSLContextFactory(client.getTls()); + SSLContext sslContext = factory.createSSLContext(); + HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build(); + HttpComponentsClientHttpRequestFactory result = new HttpComponentsClientHttpRequestFactory(httpClient); + + result.setReadTimeout(client.getRequestReadTimeout()); + result.setConnectTimeout(client.getRequestConnectTimeout()); + return result; + + } + catch (GeneralSecurityException | IOException ex) { + log.error(ex); + throw new IllegalStateException("Failed to create config client with TLS.", ex); + } + } + + SimpleClientHttpRequestFactory result = new SimpleClientHttpRequestFactory(); + result.setReadTimeout(client.getRequestReadTimeout()); + result.setConnectTimeout(client.getRequestConnectTimeout()); + return result; + } + + public void addAuthorizationToken(HttpHeaders httpHeaders, String username, String password) { + String authorization = properties.getHeaders().get(AUTHORIZATION); + + if (password != null && authorization != null) { + throw new IllegalStateException("You must set either 'password' or 'authorization'"); + } + + if (password != null) { + byte[] token = Base64Utils.encode((username + ":" + password).getBytes()); + httpHeaders.add("Authorization", "Basic " + new String(token)); + } + else if (authorization != null) { + httpHeaders.add("Authorization", authorization); + } + + } + + /** + * Adds the provided headers to the request. + */ + public static class GenericRequestHeaderInterceptor implements ClientHttpRequestInterceptor { + + private final Map headers; + + public GenericRequestHeaderInterceptor(Map headers) { + this.headers = headers; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + for (Map.Entry header : this.headers.entrySet()) { + request.getHeaders().add(header.getKey(), header.getValue()); + } + return execution.execute(request, body); + } + + protected Map getHeaders() { + return this.headers; + } + + } + +} diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java index de3d79af..86447492 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java @@ -46,14 +46,12 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.util.Base64Utils; import org.springframework.util.StringUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; -import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION; import static org.springframework.cloud.config.client.ConfigClientProperties.STATE_HEADER; import static org.springframework.cloud.config.client.ConfigClientProperties.TOKEN_HEADER; @@ -240,6 +238,9 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader response = null; List acceptHeader = Collections.singletonList(MediaType.parseMediaType(properties.getMediaType())); + ConfigClientRequestTemplateFactory requestTemplateFactory = context.getBootstrapContext() + .get(ConfigClientRequestTemplateFactory.class); + for (int i = 0; i < noOfUrls; i++) { ConfigClientProperties.Credentials credentials = properties.getCredentials(i); String uri = credentials.getUri(); @@ -251,7 +252,7 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader headers = new HashMap<>(properties.getHeaders()); - if (headers.containsKey(AUTHORIZATION)) { - headers.remove(AUTHORIZATION); // To avoid redundant addition of header - } - if (!headers.isEmpty()) { - template.setInterceptors(Collections - .singletonList(new ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor(headers))); - } - - return template; + return null; } protected Log getLog() { @@ -147,9 +125,17 @@ public class ConfigServerConfigDataLocationResolver bootstrapContext.addCloseListener(event -> event.getApplicationContext().getBeanFactory().registerSingleton( "configDataConfigClientProperties", event.getBootstrapContext().get(ConfigClientProperties.class))); + bootstrapContext.registerIfAbsent(ConfigClientRequestTemplateFactory.class, + context -> new ConfigClientRequestTemplateFactory(log, context.get(ConfigClientProperties.class))); + bootstrapContext.registerIfAbsent(RestTemplate.class, context -> { - ConfigClientProperties props = context.get(ConfigClientProperties.class); - return createRestTemplate(props); + ConfigClientRequestTemplateFactory factory = context.get(ConfigClientRequestTemplateFactory.class); + RestTemplate restTemplate = createRestTemplate(factory.getProperties()); + if (restTemplate != null) { + // shouldn't normally happen + return restTemplate; + } + return factory.create(); }); boolean discoveryEnabled = resolverContext.getBinder() diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java index ad5d7dfe..03b1c71f 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java @@ -16,8 +16,6 @@ package org.springframework.cloud.config.client; -import java.io.IOException; -import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -25,14 +23,9 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; - -import javax.net.ssl.SSLContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.HttpClient; -import org.apache.http.impl.client.HttpClients; import org.springframework.boot.env.OriginTrackedMapPropertySource; import org.springframework.boot.origin.Origin; @@ -42,33 +35,23 @@ import org.springframework.cloud.bootstrap.support.OriginTrackedCompositePropert import org.springframework.cloud.config.client.ConfigClientProperties.Credentials; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; -import org.springframework.cloud.configuration.SSLContextFactory; import org.springframework.core.annotation.Order; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.MapPropertySource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.retry.annotation.Retryable; import org.springframework.util.Assert; -import org.springframework.util.Base64Utils; import org.springframework.util.StringUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; -import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION; import static org.springframework.cloud.config.client.ConfigClientProperties.STATE_HEADER; import static org.springframework.cloud.config.client.ConfigClientProperties.TOKEN_HEADER; @@ -95,7 +78,9 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator public org.springframework.core.env.PropertySource locate(org.springframework.core.env.Environment environment) { ConfigClientProperties properties = this.defaultProperties.override(environment); CompositePropertySource composite = new OriginTrackedCompositePropertySource("configService"); - RestTemplate restTemplate = this.restTemplate == null ? getSecureRestTemplate(properties) : this.restTemplate; + ConfigClientRequestTemplateFactory requestTemplateFactory = new ConfigClientRequestTemplateFactory(logger, + properties); + Exception error = null; String errorBody = null; try { @@ -106,7 +91,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator String state = ConfigClientStateHolder.getState(); // Try all the labels until one works for (String label : labels) { - Environment result = getRemoteEnvironment(restTemplate, properties, label.trim(), state); + Environment result = getRemoteEnvironment(requestTemplateFactory, label.trim(), state); if (result != null) { log(result); @@ -209,8 +194,10 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator } } - private Environment getRemoteEnvironment(RestTemplate restTemplate, ConfigClientProperties properties, String label, + private Environment getRemoteEnvironment(ConfigClientRequestTemplateFactory requestTemplateFactory, String label, String state) { + RestTemplate restTemplate = this.restTemplate == null ? requestTemplateFactory.create() : this.restTemplate; + ConfigClientProperties properties = requestTemplateFactory.getProperties(); String path = "/{name}/{profile}"; String name = properties.getName(); String profile = properties.getProfile(); @@ -241,7 +228,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator try { HttpHeaders headers = new HttpHeaders(); headers.setAccept(acceptHeader); - addAuthorizationToken(properties, headers, username, password); + requestTemplateFactory.addAuthorizationToken(headers, username, password); if (StringUtils.hasText(token)) { headers.add(TOKEN_HEADER, token); } @@ -282,93 +269,15 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator this.restTemplate = restTemplate; } - private RestTemplate getSecureRestTemplate(ConfigClientProperties client) { - if (client.getRequestReadTimeout() < 0) { - throw new IllegalStateException("Invalid Value for Read Timeout set."); - } - if (client.getRequestConnectTimeout() < 0) { - throw new IllegalStateException("Invalid Value for Connect Timeout set."); - } - - ClientHttpRequestFactory requestFactory = createHttpRquestFactory(client); - RestTemplate template = new RestTemplate(requestFactory); - Map headers = new HashMap<>(client.getHeaders()); - if (headers.containsKey(AUTHORIZATION)) { - headers.remove(AUTHORIZATION); // To avoid redundant addition of header - } - if (!headers.isEmpty()) { - template.setInterceptors( - Arrays.asList(new GenericRequestHeaderInterceptor(headers))); - } - - return template; - } - - private ClientHttpRequestFactory createHttpRquestFactory(ConfigClientProperties client) { - if (client.getTls().isEnabled()) { - try { - SSLContextFactory factory = new SSLContextFactory(client.getTls()); - SSLContext sslContext = factory.createSSLContext(); - HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build(); - HttpComponentsClientHttpRequestFactory result = new HttpComponentsClientHttpRequestFactory(httpClient); - - result.setReadTimeout(client.getRequestReadTimeout()); - result.setConnectTimeout(client.getRequestConnectTimeout()); - return result; - - } - catch (GeneralSecurityException | IOException ex) { - logger.error(ex); - throw new IllegalStateException("Failed to create config client with TLS.", ex); - } - } - - SimpleClientHttpRequestFactory result = new SimpleClientHttpRequestFactory(); - result.setReadTimeout(client.getRequestReadTimeout()); - result.setConnectTimeout(client.getRequestConnectTimeout()); - return result; - } - - private void addAuthorizationToken(ConfigClientProperties configClientProperties, HttpHeaders httpHeaders, - String username, String password) { - String authorization = configClientProperties.getHeaders().get(AUTHORIZATION); - - if (password != null && authorization != null) { - throw new IllegalStateException("You must set either 'password' or 'authorization'"); - } - - if (password != null) { - byte[] token = Base64Utils.encode((username + ":" + password).getBytes()); - httpHeaders.add("Authorization", "Basic " + new String(token)); - } - else if (authorization != null) { - httpHeaders.add("Authorization", authorization); - } - - } - /** * Adds the provided headers to the request. */ - public static class GenericRequestHeaderInterceptor implements ClientHttpRequestInterceptor { - - private final Map headers; + @Deprecated + public static class GenericRequestHeaderInterceptor + extends ConfigClientRequestTemplateFactory.GenericRequestHeaderInterceptor { public GenericRequestHeaderInterceptor(Map headers) { - this.headers = headers; - } - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) - throws IOException { - for (Entry header : this.headers.entrySet()) { - request.getHeaders().add(header.getKey(), header.getValue()); - } - return execution.execute(request, body); - } - - protected Map getHeaders() { - return this.headers; + super(headers); } } diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java index 3c72156c..39d61edb 100644 --- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java @@ -25,6 +25,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.apache.commons.logging.LogFactory; import org.hamcrest.core.IsInstanceOf; import org.junit.Rule; import org.junit.Test; @@ -34,7 +35,7 @@ import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor; +import org.springframework.cloud.config.client.ConfigClientRequestTemplateFactory.GenericRequestHeaderInterceptor; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; import org.springframework.core.env.ConfigurableEnvironment; @@ -51,7 +52,6 @@ import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.mock.http.client.MockClientHttpRequest; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.Assertions.assertThat; @@ -227,8 +227,7 @@ public class ConfigServicePropertySourceLocatorTests { byte[] body = new byte[] {}; Map headers = new HashMap<>(); headers.put("X-Example-Version", "2.1"); - new ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor(headers).intercept(request, body, - execution); + new GenericRequestHeaderInterceptor(headers).intercept(request, body, execution); Mockito.verify(execution).execute(request, body); assertThat(request.getHeaders().getFirst("X-Example-Version")).isEqualTo("2.1"); } @@ -237,10 +236,9 @@ public class ConfigServicePropertySourceLocatorTests { public void shouldAddAuthorizationHeaderWhenPasswordSet() { HttpHeaders headers = new HttpHeaders(); ConfigClientProperties defaults = new ConfigClientProperties(this.environment); - this.locator = new ConfigServicePropertySourceLocator(defaults); String username = "user"; String password = "pass"; - ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password); + factory(defaults).addAuthorizationToken(headers, username, password); assertThat(headers).hasSize(1); } @@ -249,10 +247,9 @@ public class ConfigServicePropertySourceLocatorTests { HttpHeaders headers = new HttpHeaders(); ConfigClientProperties defaults = new ConfigClientProperties(this.environment); defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg=="); - this.locator = new ConfigServicePropertySourceLocator(defaults); String username = "user"; String password = null; - ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password); + factory(defaults).addAuthorizationToken(headers, username, password); assertThat(headers).hasSize(1); } @@ -261,32 +258,29 @@ public class ConfigServicePropertySourceLocatorTests { HttpHeaders headers = new HttpHeaders(); ConfigClientProperties defaults = new ConfigClientProperties(this.environment); defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg=="); - this.locator = new ConfigServicePropertySourceLocator(defaults); String username = "user"; String password = "pass"; this.expected.expect(IllegalStateException.class); this.expected.expectMessage("You must set either 'password' or 'authorization'"); - ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password); + factory(defaults).addAuthorizationToken(headers, username, password); } @Test public void shouldThrowExceptionWhenNegativeReadTimeoutSet() { ConfigClientProperties defaults = new ConfigClientProperties(this.environment); defaults.setRequestReadTimeout(-1); - this.locator = new ConfigServicePropertySourceLocator(defaults); this.expected.expect(IllegalStateException.class); this.expected.expectMessage("Invalid Value for Read Timeout set."); - ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults); + factory(defaults).create(); } @Test public void shouldThrowExceptionWhenNegativeConnectTimeoutSet() { ConfigClientProperties defaults = new ConfigClientProperties(this.environment); defaults.setRequestConnectTimeout(-1); - this.locator = new ConfigServicePropertySourceLocator(defaults); this.expected.expect(IllegalStateException.class); this.expected.expectMessage("Invalid Value for Connect Timeout set."); - ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults); + factory(defaults).create(); } @Test @@ -294,8 +288,7 @@ public class ConfigServicePropertySourceLocatorTests { ConfigClientProperties defaults = new ConfigClientProperties(this.environment); defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg=="); defaults.getHeaders().put("key", "value"); - this.locator = new ConfigServicePropertySourceLocator(defaults); - RestTemplate restTemplate = ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults); + RestTemplate restTemplate = factory(defaults).create(); Iterator iterator = restTemplate.getInterceptors().iterator(); while (iterator.hasNext()) { GenericRequestHeaderInterceptor genericRequestHeaderInterceptor = (GenericRequestHeaderInterceptor) iterator @@ -304,6 +297,10 @@ public class ConfigServicePropertySourceLocatorTests { } } + private ConfigClientRequestTemplateFactory factory(ConfigClientProperties properties) { + return new ConfigClientRequestTemplateFactory(LogFactory.getLog(getClass()), properties); + } + @SuppressWarnings({ "unchecked", "raw" }) @Test public void shouldPreserveOrder() {