Allow users to provide a customizer to customize the HttpClient behavior. (#2413)
Fixes #2410 Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
This commit is contained in:
@@ -62,6 +62,7 @@ import org.springframework.cloud.config.server.environment.EnvironmentWatch;
|
||||
import org.springframework.cloud.config.server.environment.GoogleSecretManagerEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.GoogleSecretManagerEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.GoogleSecretManagerEnvironmentRepositoryFactory;
|
||||
import org.springframework.cloud.config.server.environment.HttpClient4BuilderCustomizer;
|
||||
import org.springframework.cloud.config.server.environment.HttpClientConfigurableHttpConnectionFactory;
|
||||
import org.springframework.cloud.config.server.environment.HttpClientVaultRestTemplateFactory;
|
||||
import org.springframework.cloud.config.server.environment.HttpRequestConfigTokenProvider;
|
||||
@@ -184,11 +185,12 @@ public class EnvironmentRepositoryConfiguration {
|
||||
Optional<ConfigurableHttpConnectionFactory> jgitHttpConnectionFactory,
|
||||
Optional<TransportConfigCallback> customTransportConfigCallback,
|
||||
Optional<GoogleCloudSourceSupport> googleCloudSourceSupport,
|
||||
GitCredentialsProviderFactory gitCredentialsProviderFactory) {
|
||||
GitCredentialsProviderFactory gitCredentialsProviderFactory,
|
||||
List<HttpClient4BuilderCustomizer> customizers) {
|
||||
final TransportConfigCallbackFactory transportConfigCallbackFactory = new TransportConfigCallbackFactory(
|
||||
customTransportConfigCallback.orElse(null), googleCloudSourceSupport.orElse(null));
|
||||
return new MultipleJGitEnvironmentRepositoryFactory(environment, server, jgitHttpConnectionFactory,
|
||||
transportConfigCallbackFactory, gitCredentialsProviderFactory);
|
||||
transportConfigCallbackFactory, gitCredentialsProviderFactory, customizers);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
|
||||
|
||||
/**
|
||||
@@ -23,6 +26,11 @@ import org.eclipse.jgit.transport.http.HttpConnectionFactory;
|
||||
*/
|
||||
public interface ConfigurableHttpConnectionFactory extends HttpConnectionFactory {
|
||||
|
||||
void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties) throws Exception;
|
||||
default void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
|
||||
addConfiguration(environmentProperties, Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties,
|
||||
List<HttpClient4BuilderCustomizer> customizers) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.server.environment;
|
||||
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface HttpClient4BuilderCustomizer {
|
||||
|
||||
/**
|
||||
* Allows for customization of the HttpClientBuilder before it is created.
|
||||
* @param httpClientBuilder the HttpClientBuilder to customize
|
||||
*/
|
||||
void customize(HttpClientBuilder httpClientBuilder);
|
||||
|
||||
}
|
||||
@@ -54,11 +54,11 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
|
||||
Map<String, HttpClientBuilder> httpClientBuildersByUri = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties)
|
||||
throws GeneralSecurityException {
|
||||
addHttpClient(environmentProperties);
|
||||
public void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties,
|
||||
List<HttpClient4BuilderCustomizer> customizers) throws GeneralSecurityException {
|
||||
addHttpClient(environmentProperties, customizers);
|
||||
for (JGitEnvironmentProperties repo : environmentProperties.getRepos().values()) {
|
||||
addHttpClient(repo);
|
||||
addHttpClient(repo, customizers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,10 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
|
||||
}
|
||||
}
|
||||
|
||||
private void addHttpClient(JGitEnvironmentProperties properties) throws GeneralSecurityException {
|
||||
private void addHttpClient(JGitEnvironmentProperties properties, List<HttpClient4BuilderCustomizer> customizers)
|
||||
throws GeneralSecurityException {
|
||||
if (properties.getUri() != null && properties.getUri().startsWith("http")) {
|
||||
this.httpClientBuildersByUri.put(properties.getUri(), HttpClient4Support.builder(properties));
|
||||
this.httpClientBuildersByUri.put(properties.getUri(), HttpClient4Support.builder(properties, customizers));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
@@ -42,6 +44,8 @@ public class MultipleJGitEnvironmentRepositoryFactory
|
||||
|
||||
private final GitCredentialsProviderFactory gitCredentialsProviderFactory;
|
||||
|
||||
private final List<HttpClient4BuilderCustomizer> customizers;
|
||||
|
||||
@Deprecated
|
||||
public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environment, ConfigServerProperties server,
|
||||
TransportConfigCallbackFactory transportConfigCallbackFactory) {
|
||||
@@ -61,11 +65,21 @@ public class MultipleJGitEnvironmentRepositoryFactory
|
||||
Optional<ConfigurableHttpConnectionFactory> connectionFactory,
|
||||
TransportConfigCallbackFactory transportConfigCallbackFactory,
|
||||
GitCredentialsProviderFactory gitCredentialsProviderFactory) {
|
||||
this(environment, server, connectionFactory, transportConfigCallbackFactory, gitCredentialsProviderFactory,
|
||||
Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environment, ConfigServerProperties server,
|
||||
Optional<ConfigurableHttpConnectionFactory> connectionFactory,
|
||||
TransportConfigCallbackFactory transportConfigCallbackFactory,
|
||||
GitCredentialsProviderFactory gitCredentialsProviderFactory,
|
||||
List<HttpClient4BuilderCustomizer> customizers) {
|
||||
this.environment = environment;
|
||||
this.server = server;
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.transportConfigCallbackFactory = transportConfigCallbackFactory;
|
||||
this.gitCredentialsProviderFactory = gitCredentialsProviderFactory;
|
||||
this.customizers = customizers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,7 +87,7 @@ public class MultipleJGitEnvironmentRepositoryFactory
|
||||
throws Exception {
|
||||
if (this.connectionFactory.isPresent()) {
|
||||
HttpTransport.setConnectionFactory(this.connectionFactory.get());
|
||||
this.connectionFactory.get().addConfiguration(environmentProperties);
|
||||
this.connectionFactory.get().addConfiguration(environmentProperties, this.customizers);
|
||||
}
|
||||
|
||||
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment,
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.cloud.config.server.support;
|
||||
|
||||
import java.net.ProxySelector;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
@@ -34,6 +36,7 @@ import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.HttpClient4BuilderCustomizer;
|
||||
import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -48,6 +51,11 @@ public final class HttpClient4Support {
|
||||
|
||||
public static HttpClientBuilder builder(HttpEnvironmentRepositoryProperties environmentProperties)
|
||||
throws GeneralSecurityException {
|
||||
return builder(environmentProperties, Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
public static HttpClientBuilder builder(HttpEnvironmentRepositoryProperties environmentProperties,
|
||||
List<HttpClient4BuilderCustomizer> customizers) throws GeneralSecurityException {
|
||||
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
@@ -78,8 +86,10 @@ public final class HttpClient4Support {
|
||||
httpClientBuilder.disableRedirectHandling();
|
||||
|
||||
int timeout = environmentProperties.getTimeout() * 1000;
|
||||
return httpClientBuilder.setSSLContext(sslContextBuilder.build()).setDefaultRequestConfig(
|
||||
httpClientBuilder.setSSLContext(sslContextBuilder.build()).setDefaultRequestConfig(
|
||||
RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build());
|
||||
customizers.forEach(customizer -> customizer.customize(httpClientBuilder));
|
||||
return httpClientBuilder;
|
||||
}
|
||||
|
||||
static class SchemeBasedRoutePlanner4 extends DefaultRoutePlanner {
|
||||
|
||||
@@ -31,6 +31,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class HttpClientConfigurableHttpConnectionFactoryTest {
|
||||
|
||||
@@ -69,6 +73,23 @@ public class HttpClientConfigurableHttpConnectionFactoryTest {
|
||||
assertThat(actualHttpClientBuilder).isSameAs(expectedHttpClientBuilder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeHttpClient() throws Exception {
|
||||
String url = "http://localhost/test.git";
|
||||
MultipleJGitEnvironmentProperties properties = new MultipleJGitEnvironmentProperties();
|
||||
properties.setUri(url);
|
||||
HttpClient4BuilderCustomizer customizer = mock(HttpClient4BuilderCustomizer.class);
|
||||
this.connectionFactory.addConfiguration(properties, List.of(customizer));
|
||||
|
||||
HttpConnection actualConnection = this.connectionFactory.create(new URL(url));
|
||||
|
||||
HttpClientBuilder expectedHttpClientBuilder = this.connectionFactory.httpClientBuildersByUri.values().stream()
|
||||
.findFirst().get();
|
||||
HttpClientBuilder actualHttpClientBuilder = getActualHttpClientBuilder(actualConnection);
|
||||
assertThat(actualHttpClientBuilder).isSameAs(expectedHttpClientBuilder);
|
||||
verify(customizer, times(1)).customize(any(HttpClientBuilder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void longerUrl() throws Exception {
|
||||
MultipleJGitEnvironmentProperties properties = new MultipleJGitEnvironmentProperties();
|
||||
|
||||
Reference in New Issue
Block a user