Rename 'spring.http.client' properties to 'spring.http.client.settings'
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Deprecate 'spring.http.client' properties in favor of 'spring.http.client.settings` to align with the new reactive client properties. Closes gh-44958
This commit is contained in:
parent
068f621967
commit
c69d3ef406
|
@ -18,12 +18,8 @@ package org.springframework.boot.autoconfigure.http.client;
|
|||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for properties that directly or indirectly make use of a blocking
|
||||
|
@ -38,7 +34,7 @@ public abstract class AbstractHttpClientProperties {
|
|||
/**
|
||||
* Handling for HTTP redirects.
|
||||
*/
|
||||
private HttpRedirects redirects = HttpRedirects.FOLLOW_WHEN_POSSIBLE;
|
||||
private HttpRedirects redirects;
|
||||
|
||||
/**
|
||||
* Default connect timeout for a client HTTP request.
|
||||
|
@ -83,20 +79,6 @@ public abstract class AbstractHttpClientProperties {
|
|||
return this.ssl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link HttpClientSettings} based on these properties.
|
||||
* @param sslBundles a {@link SslBundles} provider
|
||||
* @return the {@link HttpClientSettings}
|
||||
*/
|
||||
protected HttpClientSettings httpClientSettings(ObjectProvider<SslBundles> sslBundles) {
|
||||
return new HttpClientSettings(this.redirects, this.connectTimeout, this.readTimeout, sslBundle(sslBundles));
|
||||
}
|
||||
|
||||
private SslBundle sslBundle(ObjectProvider<SslBundles> sslBundles) {
|
||||
String name = getSsl().getBundle();
|
||||
return (StringUtils.hasLength(name)) ? sslBundles.getObject().getBundle(name) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* SSL configuration.
|
||||
*/
|
||||
|
|
|
@ -46,16 +46,6 @@ public abstract class AbstractHttpRequestFactoryProperties extends AbstractHttpC
|
|||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ClientHttpRequestFactoryBuilder} based on the properties.
|
||||
* @param classLoader the class loader to use for detection
|
||||
* @return a {@link ClientHttpRequestFactoryBuilder}
|
||||
*/
|
||||
protected final ClientHttpRequestFactoryBuilder<?> factoryBuilder(ClassLoader classLoader) {
|
||||
Factory factory = getFactory();
|
||||
return (factory != null) ? factory.builder() : ClientHttpRequestFactoryBuilder.detect(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported factory types.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.http.client;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.http.client.AbstractHttpClientProperties.Ssl;
|
||||
import org.springframework.boot.autoconfigure.http.client.AbstractHttpRequestFactoryProperties.Factory;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings.Redirects;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Helper class to create {@link ClientHttpRequestFactoryBuilder} and
|
||||
* {@link ClientHttpRequestFactorySettings}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ClientHttpRequestFactories {
|
||||
|
||||
private final ObjectProvider<SslBundles> sslBundles;
|
||||
|
||||
private final AbstractHttpRequestFactoryProperties[] orderedProperties;
|
||||
|
||||
ClientHttpRequestFactories(ObjectProvider<SslBundles> sslBundles,
|
||||
AbstractHttpRequestFactoryProperties... orderedProperties) {
|
||||
this.sslBundles = sslBundles;
|
||||
this.orderedProperties = orderedProperties;
|
||||
}
|
||||
|
||||
ClientHttpRequestFactoryBuilder<?> builder(ClassLoader classLoader) {
|
||||
Factory factory = getProperty(AbstractHttpRequestFactoryProperties::getFactory);
|
||||
return (factory != null) ? factory.builder() : ClientHttpRequestFactoryBuilder.detect(classLoader);
|
||||
}
|
||||
|
||||
ClientHttpRequestFactorySettings settings() {
|
||||
HttpRedirects redirects = getProperty(AbstractHttpRequestFactoryProperties::getRedirects);
|
||||
Duration connectTimeout = getProperty(AbstractHttpRequestFactoryProperties::getConnectTimeout);
|
||||
Duration readTimeout = getProperty(AbstractHttpRequestFactoryProperties::getReadTimeout);
|
||||
String sslBundleName = getProperty(AbstractHttpRequestFactoryProperties::getSsl, Ssl::getBundle,
|
||||
StringUtils::hasLength);
|
||||
SslBundle sslBundle = (StringUtils.hasLength(sslBundleName))
|
||||
? this.sslBundles.getObject().getBundle(sslBundleName) : null;
|
||||
return new ClientHttpRequestFactorySettings(Redirects.of(redirects), connectTimeout, readTimeout, sslBundle);
|
||||
}
|
||||
|
||||
private <T> T getProperty(Function<AbstractHttpRequestFactoryProperties, T> accessor) {
|
||||
return getProperty(accessor, Function.identity(), Objects::nonNull);
|
||||
}
|
||||
|
||||
private <P, T> T getProperty(Function<AbstractHttpRequestFactoryProperties, P> accessor, Function<P, T> extractor,
|
||||
Predicate<T> predicate) {
|
||||
for (AbstractHttpRequestFactoryProperties properties : this.orderedProperties) {
|
||||
P value = accessor.apply(properties);
|
||||
T extracted = (value != null) ? extractor.apply(value) : null;
|
||||
if (predicate.test(extracted)) {
|
||||
return extracted;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,9 +28,6 @@ import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
|||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings.Redirects;
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.boot.util.LambdaSafe;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -44,14 +41,22 @@ import org.springframework.http.client.ClientHttpRequestFactory;
|
|||
* @author Phillip Webb
|
||||
* @since 3.4.0
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@AutoConfiguration(after = SslAutoConfiguration.class)
|
||||
@ConditionalOnClass(ClientHttpRequestFactory.class)
|
||||
@Conditional(NotReactiveWebApplicationCondition.class)
|
||||
@EnableConfigurationProperties(HttpClientProperties.class)
|
||||
@EnableConfigurationProperties({ HttpClientSettingsProperties.class, HttpClientProperties.class })
|
||||
public class HttpClientAutoConfiguration implements BeanClassLoaderAware {
|
||||
|
||||
private final ClientHttpRequestFactories factories;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
HttpClientAutoConfiguration(ObjectProvider<SslBundles> sslBundles, HttpClientSettingsProperties properties,
|
||||
HttpClientProperties deprecatedProperties) {
|
||||
this.factories = new ClientHttpRequestFactories(sslBundles, properties, deprecatedProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
|
@ -59,9 +64,9 @@ public class HttpClientAutoConfiguration implements BeanClassLoaderAware {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ClientHttpRequestFactoryBuilder<?> clientHttpRequestFactoryBuilder(HttpClientProperties httpClientProperties,
|
||||
ClientHttpRequestFactoryBuilder<?> clientHttpRequestFactoryBuilder(
|
||||
ObjectProvider<ClientHttpRequestFactoryBuilderCustomizer<?>> clientHttpRequestFactoryBuilderCustomizers) {
|
||||
ClientHttpRequestFactoryBuilder<?> builder = httpClientProperties.factoryBuilder(this.beanClassLoader);
|
||||
ClientHttpRequestFactoryBuilder<?> builder = this.factories.builder(this.beanClassLoader);
|
||||
return customize(builder, clientHttpRequestFactoryBuilderCustomizers.orderedStream().toList());
|
||||
}
|
||||
|
||||
|
@ -76,19 +81,8 @@ public class HttpClientAutoConfiguration implements BeanClassLoaderAware {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ClientHttpRequestFactorySettings clientHttpRequestFactorySettings(HttpClientProperties httpClientProperties,
|
||||
ObjectProvider<SslBundles> sslBundles) {
|
||||
HttpClientSettings settings = httpClientProperties.httpClientSettings(sslBundles);
|
||||
return new ClientHttpRequestFactorySettings(asRequestFactoryRedirects(settings.redirects()),
|
||||
settings.connectTimeout(), settings.readTimeout(), settings.sslBundle());
|
||||
}
|
||||
|
||||
private Redirects asRequestFactoryRedirects(HttpRedirects redirects) {
|
||||
return switch (redirects) {
|
||||
case FOLLOW_WHEN_POSSIBLE -> Redirects.FOLLOW_WHEN_POSSIBLE;
|
||||
case FOLLOW -> Redirects.FOLLOW;
|
||||
case DONT_FOLLOW -> Redirects.DONT_FOLLOW;
|
||||
};
|
||||
ClientHttpRequestFactorySettings clientHttpRequestFactorySettings() {
|
||||
return this.factories.settings();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.http.client;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
|
||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
|
||||
/**
|
||||
* {@link ConfigurationProperties @ConfigurationProperties} for a Spring's blocking HTTP
|
||||
|
@ -26,8 +30,41 @@ import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
|||
* @author Phillip Webb
|
||||
* @since 3.4.0
|
||||
* @see ClientHttpRequestFactorySettings
|
||||
* @deprecated since 3.5.0 for removal in 4.0.0 in favor of
|
||||
* {@link HttpClientSettingsProperties}
|
||||
*/
|
||||
@ConfigurationProperties("spring.http.client")
|
||||
@Deprecated(since = "3.5.0", forRemoval = true)
|
||||
public class HttpClientProperties extends AbstractHttpRequestFactoryProperties {
|
||||
|
||||
@Override
|
||||
@DeprecatedConfigurationProperty(since = "3.5.0", replacement = "spring.http.client.settings.factory")
|
||||
public Factory getFactory() {
|
||||
return super.getFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DeprecatedConfigurationProperty(since = "3.5.0", replacement = "spring.http.client.settings.redirects")
|
||||
public HttpRedirects getRedirects() {
|
||||
return super.getRedirects();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DeprecatedConfigurationProperty(since = "3.5.0", replacement = "spring.http.client.settings.connect-timeout")
|
||||
public Duration getConnectTimeout() {
|
||||
return super.getConnectTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DeprecatedConfigurationProperty(since = "3.5.0", replacement = "spring.http.client.settings.read-timeout")
|
||||
public Duration getReadTimeout() {
|
||||
return super.getReadTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DeprecatedConfigurationProperty(since = "3.5.0", replacement = "spring.http.client.settings.ssl")
|
||||
public Ssl getSsl() {
|
||||
return super.getSsl();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.http.client;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorSettings;
|
||||
|
||||
/**
|
||||
* {@link ConfigurationProperties @ConfigurationProperties} to configure settings that
|
||||
* apply to Spring's reactive client HTTP connectors.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 3.5.0
|
||||
* @see ClientHttpConnectorSettings
|
||||
*/
|
||||
@ConfigurationProperties("spring.http.client.settings")
|
||||
public class HttpClientSettingsProperties extends AbstractHttpRequestFactoryProperties {
|
||||
|
||||
}
|
|
@ -18,13 +18,10 @@ package org.springframework.boot.autoconfigure.http.client.reactive;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.http.client.AbstractHttpClientProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorSettings;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
|
||||
/**
|
||||
|
@ -50,21 +47,6 @@ public abstract class AbstractClientHttpConnectorProperties extends AbstractHttp
|
|||
this.connector = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpClientSettings httpClientSettings(ObjectProvider<SslBundles> sslBundles) {
|
||||
return super.httpClientSettings(sslBundles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ClientHttpConnectorBuilder} based on the properties.
|
||||
* @param classLoader the class loader to use for detection
|
||||
* @return a {@link ClientHttpConnectorBuilder}
|
||||
*/
|
||||
protected final ClientHttpConnectorBuilder<?> connectorBuilder(ClassLoader classLoader) {
|
||||
Connector connector = getConnector();
|
||||
return (connector != null) ? connector.builder() : ClientHttpConnectorBuilder.detect(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported factory types.
|
||||
*/
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
|||
import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorSettings;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
|
@ -52,8 +51,15 @@ import org.springframework.http.client.reactive.ClientHttpConnector;
|
|||
@EnableConfigurationProperties(HttpReactiveClientSettingsProperties.class)
|
||||
public class ClientHttpConnectorAutoConfiguration implements BeanClassLoaderAware {
|
||||
|
||||
private final ClientHttpConnectors connectors;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
ClientHttpConnectorAutoConfiguration(ObjectProvider<SslBundles> sslBundles,
|
||||
HttpReactiveClientSettingsProperties properties) {
|
||||
this.connectors = new ClientHttpConnectors(sslBundles, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
|
@ -62,10 +68,8 @@ public class ClientHttpConnectorAutoConfiguration implements BeanClassLoaderAwar
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ClientHttpConnectorBuilder<?> clientHttpConnectorBuilder(
|
||||
HttpReactiveClientSettingsProperties httpReactiveClientSettingsProperties,
|
||||
ObjectProvider<ClientHttpConnectorBuilderCustomizer<?>> clientHttpConnectorBuilderCustomizers) {
|
||||
ClientHttpConnectorBuilder<?> builder = httpReactiveClientSettingsProperties
|
||||
.connectorBuilder(this.beanClassLoader);
|
||||
ClientHttpConnectorBuilder<?> builder = this.connectors.builder(this.beanClassLoader);
|
||||
return customize(builder, clientHttpConnectorBuilderCustomizers.orderedStream().toList());
|
||||
}
|
||||
|
||||
|
@ -80,12 +84,8 @@ public class ClientHttpConnectorAutoConfiguration implements BeanClassLoaderAwar
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ClientHttpConnectorSettings clientHttpConnectorSettings(
|
||||
HttpReactiveClientSettingsProperties httpReactiveClientSettingsProperties,
|
||||
ObjectProvider<SslBundles> sslBundles) {
|
||||
HttpClientSettings settings = httpReactiveClientSettingsProperties.httpClientSettings(sslBundles);
|
||||
return new ClientHttpConnectorSettings(settings.redirects(), settings.connectTimeout(), settings.readTimeout(),
|
||||
settings.sslBundle());
|
||||
ClientHttpConnectorSettings clientHttpConnectorSettings() {
|
||||
return this.connectors.settings();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.http.client.reactive;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.http.client.AbstractHttpClientProperties.Ssl;
|
||||
import org.springframework.boot.autoconfigure.http.client.reactive.AbstractClientHttpConnectorProperties.Connector;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder;
|
||||
import org.springframework.boot.http.client.reactive.ClientHttpConnectorSettings;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Helper class to create {@link ClientHttpConnectorBuilder} and
|
||||
* {@link ClientHttpConnectorSettings}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ClientHttpConnectors {
|
||||
|
||||
private final ObjectProvider<SslBundles> sslBundles;
|
||||
|
||||
private final AbstractClientHttpConnectorProperties[] orderedProperties;
|
||||
|
||||
ClientHttpConnectors(ObjectProvider<SslBundles> sslBundles,
|
||||
AbstractClientHttpConnectorProperties... orderedProperties) {
|
||||
this.sslBundles = sslBundles;
|
||||
this.orderedProperties = orderedProperties;
|
||||
}
|
||||
|
||||
ClientHttpConnectorBuilder<?> builder(ClassLoader classLoader) {
|
||||
Connector connector = getProperty(AbstractClientHttpConnectorProperties::getConnector);
|
||||
return (connector != null) ? connector.builder() : ClientHttpConnectorBuilder.detect(classLoader);
|
||||
}
|
||||
|
||||
ClientHttpConnectorSettings settings() {
|
||||
HttpRedirects redirects = getProperty(AbstractClientHttpConnectorProperties::getRedirects);
|
||||
Duration connectTimeout = getProperty(AbstractClientHttpConnectorProperties::getConnectTimeout);
|
||||
Duration readTimeout = getProperty(AbstractClientHttpConnectorProperties::getReadTimeout);
|
||||
String sslBundleName = getProperty(AbstractClientHttpConnectorProperties::getSsl, Ssl::getBundle,
|
||||
StringUtils::hasText);
|
||||
SslBundle sslBundle = (StringUtils.hasLength(sslBundleName))
|
||||
? this.sslBundles.getObject().getBundle(sslBundleName) : null;
|
||||
return new ClientHttpConnectorSettings(redirects, connectTimeout, readTimeout, sslBundle);
|
||||
}
|
||||
|
||||
private <T> T getProperty(Function<AbstractClientHttpConnectorProperties, T> accessor) {
|
||||
return getProperty(accessor, Function.identity(), Objects::nonNull);
|
||||
}
|
||||
|
||||
private <P, T> T getProperty(Function<AbstractClientHttpConnectorProperties, P> accessor, Function<P, T> extractor,
|
||||
Predicate<T> predicate) {
|
||||
for (AbstractClientHttpConnectorProperties properties : this.orderedProperties) {
|
||||
P value = accessor.apply(properties);
|
||||
T extracted = (value != null) ? extractor.apply(value) : null;
|
||||
if (predicate.test(extracted)) {
|
||||
return extracted;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -68,6 +68,21 @@ class HttpClientAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
void configuresClientHttpRequestFactorySettings() {
|
||||
this.contextRunner.withPropertyValues(sslPropertyValues().toArray(String[]::new))
|
||||
.withPropertyValues("spring.http.client.settings.redirects=dont-follow",
|
||||
"spring.http.client.settings.connect-timeout=10s", "spring.http.client.settings.read-timeout=20s",
|
||||
"spring.http.client.settings.ssl.bundle=test")
|
||||
.run((context) -> {
|
||||
ClientHttpRequestFactorySettings settings = context.getBean(ClientHttpRequestFactorySettings.class);
|
||||
assertThat(settings.redirects()).isEqualTo(Redirects.DONT_FOLLOW);
|
||||
assertThat(settings.connectTimeout()).isEqualTo(Duration.ofSeconds(10));
|
||||
assertThat(settings.readTimeout()).isEqualTo(Duration.ofSeconds(20));
|
||||
assertThat(settings.sslBundle().getKey().getAlias()).isEqualTo("alias1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configuresClientHttpRequestFactorySettingsUsingDeprecatedProperties() {
|
||||
this.contextRunner.withPropertyValues(sslPropertyValues().toArray(String[]::new))
|
||||
.withPropertyValues("spring.http.client.redirects=dont-follow", "spring.http.client.connect-timeout=10s",
|
||||
"spring.http.client.read-timeout=20s", "spring.http.client.ssl.bundle=test")
|
||||
|
|
|
@ -248,7 +248,7 @@ If multiple clients are available on the classpath, and not global configuration
|
|||
[[io.rest-client.clienthttprequestfactory.configuration]]
|
||||
=== Global HTTP Client Configuration
|
||||
|
||||
If the auto-detected HTTP client does not meet your needs, you can use the configprop:spring.http.client.factory[] property to pick a specific factory.
|
||||
If the auto-detected HTTP client does not meet your needs, you can use the configprop:spring.http.client.settings.factory[] property to pick a specific factory.
|
||||
For example, if you have Apache HttpClient on your classpath, but you prefer Jetty's javadoc:org.eclipse.jetty.client.HttpClient[] you can add the following:
|
||||
|
||||
[configprops,yaml]
|
||||
|
@ -256,7 +256,8 @@ For example, if you have Apache HttpClient on your classpath, but you prefer Jet
|
|||
spring:
|
||||
http:
|
||||
client:
|
||||
factory: jetty
|
||||
settings:
|
||||
factory: jetty
|
||||
----
|
||||
|
||||
You can also set properties to change defaults that will be applied to all clients.
|
||||
|
@ -267,9 +268,10 @@ For example, you may want to change timeouts and if redirects are followed:
|
|||
spring:
|
||||
http:
|
||||
client:
|
||||
connect-timeout: 2s
|
||||
read-timeout: 1s
|
||||
redirects: dont-follow
|
||||
settings:
|
||||
connect-timeout: 2s
|
||||
read-timeout: 1s
|
||||
redirects: dont-follow
|
||||
----
|
||||
|
||||
For more complex customizations, you can use javadoc:org.springframework.boot.autoconfigure.http.client.ClientHttpRequestFactoryBuilderCustomizer[] or declare your own javadoc:org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder[] bean which will cause auto-configuration to back off.
|
||||
|
|
|
@ -145,6 +145,20 @@ public record ClientHttpRequestFactorySettings(Redirects redirects, Duration con
|
|||
return this.httpClientRedirects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the related {@link Redirects} for the given {@link HttpRedirects}.
|
||||
* @param httpRedirects the HTTP redirects
|
||||
* @return the related redirects
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public static Redirects of(HttpRedirects httpRedirects) {
|
||||
return (httpRedirects != null) ? switch (httpRedirects) {
|
||||
case FOLLOW_WHEN_POSSIBLE -> FOLLOW_WHEN_POSSIBLE;
|
||||
case FOLLOW -> FOLLOW;
|
||||
case DONT_FOLLOW -> DONT_FOLLOW;
|
||||
} : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue