Skip to content

Commit

Permalink
Allow users to provide a customizer to customize the HttpClient behav…
Browse files Browse the repository at this point in the history
…ior. (spring-cloud#2413)

Fixes spring-cloud#2410

Co-authored-by: Ryan Baxter <[email protected]>
  • Loading branch information
2 people authored and app committed May 20, 2024
1 parent 67916fc commit 82885f1
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
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;
Expand Down Expand Up @@ -184,11 +185,12 @@ public MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory(
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@

package org.springframework.cloud.config.server.environment;

import java.util.Collections;
import java.util.List;

import org.eclipse.jgit.transport.http.HttpConnectionFactory;

/**
* @author Dylan Roberts
*/
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;

}
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -81,9 +81,10 @@ public HttpConnection create(URL url, Proxy proxy) throws IOException {
}
}

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));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -61,19 +65,29 @@ public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environm
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
public MultipleJGitEnvironmentRepository build(MultipleJGitEnvironmentProperties environmentProperties)
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

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;
Expand All @@ -34,6 +36,7 @@
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;

Expand All @@ -48,6 +51,11 @@ private 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();

Expand Down Expand Up @@ -78,8 +86,10 @@ public static HttpClientBuilder builder(HttpEnvironmentRepositoryProperties envi
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
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 {

Expand Down Expand Up @@ -69,6 +73,23 @@ public void matchingUrl() throws Exception {
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();
Expand Down

0 comments on commit 82885f1

Please sign in to comment.