From b0433ba689c76256980428d8b442c7aa49ae3f31 Mon Sep 17 00:00:00 2001 From: Dylan Roberts Date: Wed, 6 Jun 2018 10:22:06 -0400 Subject: [PATCH] Add connect timeout support to HttpClientSupport (#1040) gh-1033 --- .../JGitEnvironmentProperties.java | 1 + .../VaultEnvironmentProperties.java | 14 ++++- .../server/support/HttpClientSupport.java | 9 ++- .../HttpEnvironmentRepositoryProperties.java | 2 + .../server/support/HttpClientSupportTest.java | 61 +++++++++++++++++++ 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java index 3598f62b..065933a7 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java @@ -116,6 +116,7 @@ public class JGitEnvironmentProperties extends AbstractScmAccessorProperties this.forcePull = forcePull; } + @Override public int getTimeout() { return timeout; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java index cacb87fc..36d9ea11 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java @@ -35,6 +35,8 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp private Integer port = 8200; /** Vault scheme. Defaults to http. */ private String scheme = "http"; + /** Timeout (in seconds) for obtaining HTTP connection, defaults to 5 seconds. */ + private int timeout = 5; /** Vault backend. Defaults to secret. */ private String backend = "secret"; /** The key in vault shared by all applications. Defaults to application. Set to empty to disable. */ @@ -46,7 +48,6 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp * over an HTTPS connection. */ private boolean skipSslValidation = false; - /** * HTTP proxy configuration. */ @@ -133,7 +134,16 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp this.order = order; } - public int getKvVersion() { + @Override + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public int getKvVersion() { return kvVersion; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java index 0974e86a..8c9f7784 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java @@ -17,6 +17,7 @@ package org.springframework.cloud.config.server.support; import java.security.GeneralSecurityException; +import org.apache.http.client.config.RequestConfig; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -50,6 +51,12 @@ public class HttpClientSupport { httpClientBuilder.setDefaultCredentialsProvider(new ProxyHostCredentialsProvider(httpProxy, httpsProxy)); } - return httpClientBuilder.setSSLContext(sslContextBuilder.build()); + int timeout = environmentProperties.getTimeout() * 1000; + return httpClientBuilder + .setSSLContext(sslContextBuilder.build()) + .setDefaultRequestConfig(RequestConfig.custom() + .setSocketTimeout(timeout) + .setConnectTimeout(timeout) + .build()); } } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java index bb5cc3e0..12dc2154 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java @@ -28,4 +28,6 @@ public interface HttpEnvironmentRepositoryProperties extends EnvironmentReposito Map getProxy(); boolean isSkipSslValidation(); + + int getTimeout(); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java new file mode 100644 index 00000000..b392e622 --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java @@ -0,0 +1,61 @@ +package org.springframework.cloud.config.server.support; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.security.GeneralSecurityException; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.isA; +import static org.junit.internal.matchers.ThrowableCauseMatcher.hasCause; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = HttpClientSupportTest.TestConfiguration.class, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class HttpClientSupportTest { + + @LocalServerPort + private String localServerPort; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void setsTimeout() throws GeneralSecurityException, IOException { + JGitEnvironmentProperties properties = new JGitEnvironmentProperties(); + properties.setTimeout(1); + CloseableHttpClient httpClient = HttpClientSupport.builder(properties).build(); + + expectedException.expect(anyOf(isA(SocketTimeoutException.class), hasCause(isA(SocketTimeoutException.class)))); + + httpClient.execute(new HttpGet(String.format("http://127.0.0.1:%s/test/endpoint", localServerPort))); + } + + @SpringBootConfiguration + @EnableWebMvc + @EnableAutoConfiguration + @RestController + static class TestConfiguration { + + @GetMapping("/test/endpoint") + public void testEndpoint() throws InterruptedException { + Thread.sleep(2000); + } + } +} \ No newline at end of file