Polish 'Update RestClientSsl to support ClientHttpRequestFactorySettings'

See gh-44979
This commit is contained in:
Phillip Webb
2025-04-14 19:27:56 -07:00
parent af5d72b94f
commit 567353a555
4 changed files with 42 additions and 45 deletions

View File

@@ -29,19 +29,20 @@ import org.springframework.web.client.RestClient;
* An auto-configured {@link RestClientSsl} implementation.
*
* @author Phillip Webb
* @author Dmytro Nosan
*/
class AutoConfiguredRestClientSsl implements RestClientSsl {
private final ClientHttpRequestFactoryBuilder<?> clientHttpRequestFactoryBuilder;
private final ClientHttpRequestFactoryBuilder<?> builder;
private final ClientHttpRequestFactorySettings clientHttpRequestFactorySettings;
private final ClientHttpRequestFactorySettings settings;
private final SslBundles sslBundles;
AutoConfiguredRestClientSsl(ClientHttpRequestFactoryBuilder<?> clientHttpRequestFactoryBuilder,
ClientHttpRequestFactorySettings clientHttpRequestFactorySettings, SslBundles sslBundles) {
this.clientHttpRequestFactoryBuilder = clientHttpRequestFactoryBuilder;
this.clientHttpRequestFactorySettings = clientHttpRequestFactorySettings;
this.builder = clientHttpRequestFactoryBuilder;
this.settings = clientHttpRequestFactorySettings;
this.sslBundles = sslBundles;
}
@@ -52,11 +53,11 @@ class AutoConfiguredRestClientSsl implements RestClientSsl {
@Override
public Consumer<RestClient.Builder> fromBundle(SslBundle bundle) {
return (builder) -> {
ClientHttpRequestFactorySettings settings = this.clientHttpRequestFactorySettings.withSslBundle(bundle);
ClientHttpRequestFactory requestFactory = this.clientHttpRequestFactoryBuilder.build(settings);
builder.requestFactory(requestFactory);
};
return (builder) -> builder.requestFactory(requestFactory(bundle));
}
private ClientHttpRequestFactory requestFactory(SslBundle bundle) {
return this.builder.build(this.settings.withSslBundle(bundle));
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web.client;
import java.util.function.Consumer;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.ssl.NoSuchSslBundleException;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.http.client.ClientHttpRequestFactory;
@@ -34,8 +35,11 @@ import org.springframework.web.client.RestClient;
* RestClient restClient = restClientBuilder.apply(ssl.fromBundle("mybundle")).build();
* return new MyBean(restClient);
* }
* </pre> NOTE: Apply SSL configuration will replace any previously
* </pre> NOTE: Applying SSL configuration will replace any previously
* {@link RestClient.Builder#requestFactory configured} {@link ClientHttpRequestFactory}.
* The replacement {@link ClientHttpRequestFactory} will apply only configured
* {@link ClientHttpRequestFactorySettings} and the appropriate {@link SslBundle}.
* <p>
* If you need to configure {@link ClientHttpRequestFactory} with more than just SSL
* consider using a {@link ClientHttpRequestFactoryBuilder}.
*

View File

@@ -18,12 +18,11 @@ package org.springframework.boot.autoconfigure.web.client;
import java.time.Duration;
import java.util.function.Consumer;
import java.util.function.Function;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
@@ -42,11 +41,11 @@ import static org.mockito.Mockito.mock;
* Tests for {@link AutoConfiguredRestClientSsl}.
*
* @author Dmytro Nosan
* @author Phillip Webb
*/
@ExtendWith(MockitoExtension.class)
class AutoConfiguredRestClientSslTests {
private final ClientHttpRequestFactorySettings clientHttpRequestFactorySettings = ClientHttpRequestFactorySettings
private final ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings
.ofSslBundle(mock(SslBundle.class, "Default SslBundle"))
.withRedirects(Redirects.DONT_FOLLOW)
.withReadTimeout(Duration.ofSeconds(10))
@@ -56,47 +55,41 @@ class AutoConfiguredRestClientSslTests {
private SslBundles sslBundles;
@Mock
private ClientHttpRequestFactoryBuilder<ClientHttpRequestFactory> clientHttpRequestFactoryBuilder;
private ClientHttpRequestFactoryBuilder<ClientHttpRequestFactory> factoryBuilder;
@Mock
private ClientHttpRequestFactory clientHttpRequestFactory;
private ClientHttpRequestFactory factory;
private AutoConfiguredRestClientSsl restClientSsl;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
this.restClientSsl = new AutoConfiguredRestClientSsl(this.factoryBuilder, this.settings, this.sslBundles);
}
@Test
void shouldConfigureRestClientUsingBundleName() {
String bundleName = "test";
SslBundle sslBundle = mock(SslBundle.class, "SslBundle named '%s'".formatted(bundleName));
given(this.sslBundles.getBundle(bundleName)).willReturn(sslBundle);
given(this.clientHttpRequestFactoryBuilder
.build(this.clientHttpRequestFactorySettings.withSslBundle(sslBundle)))
.willReturn(this.clientHttpRequestFactory);
assertThat(applySslBundle((restClientSsl) -> restClientSsl.fromBundle(bundleName)))
.hasFieldOrPropertyWithValue("clientRequestFactory", this.clientHttpRequestFactory);
given(this.factoryBuilder.build(this.settings.withSslBundle(sslBundle))).willReturn(this.factory);
RestClient restClient = build(this.restClientSsl.fromBundle(bundleName));
assertThat(restClient).hasFieldOrPropertyWithValue("clientRequestFactory", this.factory);
}
@Test
void shouldConfigureRestClientUsingBundle() {
SslBundle sslBundle = mock(SslBundle.class, "Custom SslBundle");
given(this.clientHttpRequestFactoryBuilder
.build(this.clientHttpRequestFactorySettings.withSslBundle(sslBundle)))
.willReturn(this.clientHttpRequestFactory);
assertThat(applySslBundle((restClientSsl) -> restClientSsl.fromBundle(sslBundle)))
.hasFieldOrPropertyWithValue("clientRequestFactory", this.clientHttpRequestFactory);
given(this.factoryBuilder.build(this.settings.withSslBundle(sslBundle))).willReturn(this.factory);
RestClient restClient = build(this.restClientSsl.fromBundle(sslBundle));
assertThat(restClient).hasFieldOrPropertyWithValue("clientRequestFactory", this.factory);
}
private RestClient applySslBundle(Function<RestClientSsl, Consumer<Builder>> applySslBundle) {
private RestClient build(Consumer<RestClient.Builder> customizer) {
Builder builder = RestClient.builder();
applySslBundle.apply(getRestClientSsl()).accept(builder);
customizer.accept(builder);
return builder.build();
}
private RestClientSsl getRestClientSsl() {
return new AutoConfiguredRestClientSsl(this.clientHttpRequestFactoryBuilder,
this.clientHttpRequestFactorySettings, this.sslBundles);
}
}

View File

@@ -52,6 +52,7 @@ import static org.mockito.Mockito.mock;
*
* @author Arjen Poutsma
* @author Moritz Halbritter
* @author Dmytro Nosan
*/
class RestClientAutoConfigurationTests {
@@ -84,10 +85,8 @@ class RestClientAutoConfigurationTests {
assertThat(context).hasSingleBean(RestClientSsl.class);
RestClientSsl restClientSsl = context.getBean(RestClientSsl.class);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("sslBundles", sslBundles);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("clientHttpRequestFactoryBuilder",
clientHttpRequestFactoryBuilder);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("clientHttpRequestFactorySettings",
clientHttpRequestFactorySettings);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("builder", clientHttpRequestFactoryBuilder);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("settings", clientHttpRequestFactorySettings);
});
}
@@ -100,9 +99,9 @@ class RestClientAutoConfigurationTests {
.hasSingleBean(ClientHttpRequestFactoryBuilder.class);
RestClientSsl restClientSsl = context.getBean(RestClientSsl.class);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("sslBundles", sslBundles);
assertThat(restClientSsl).hasFieldOrPropertyWithValue("clientHttpRequestFactoryBuilder",
assertThat(restClientSsl).hasFieldOrPropertyWithValue("builder",
context.getBean(ClientHttpRequestFactoryBuilder.class));
assertThat(restClientSsl).hasFieldOrPropertyWithValue("clientHttpRequestFactorySettings",
assertThat(restClientSsl).hasFieldOrPropertyWithValue("settings",
context.getBean(ClientHttpRequestFactorySettings.class));
});
}