mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Apply cookie handling to reactive HttpComponents connector
The spring.http.clients.cookie-handling property and HttpClientSettings.cookieHandling() were honored by every imperative ClientHttpRequestFactoryBuilder and by the Jetty, JDK and Reactor ClientHttpConnectorBuilders, but HttpComponentsHttpAsyncClientBuilder ignored the setting. As a result, a WebClient backed by Apache HttpComponents kept storing cookies even when cookie handling was disabled. Map the setting to the default request config's cookie spec, as HttpComponentsHttpClientBuilder already does, and document the property alongside the other global HTTP client settings. See gh-51724 Signed-off-by: Hyun Lee <dlwhdugs4147@gmail.com>
This commit is contained in:
+8
@@ -364,6 +364,7 @@ You can use properties to configure aspects such as:
|
||||
* Any default headers that should be sent.
|
||||
* API versioning configuration.
|
||||
* Redirect settings.
|
||||
* Cookie handling settings.
|
||||
* Connection and read timeouts.
|
||||
* SSL bundles to use.
|
||||
|
||||
@@ -428,6 +429,7 @@ These include:
|
||||
* Connection Timeouts.
|
||||
* Read Timeouts.
|
||||
* How HTTP redirects should be handled.
|
||||
* How HTTP cookies should be handled.
|
||||
* Which SSL bundle should be used when connecting.
|
||||
|
||||
These common settings are represented by the javadoc:org.springframework.boot.http.client.HttpClientSettings[] class which can be passed into the `build(...)` methods of javadoc:org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder[] and javadoc:org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder[].
|
||||
@@ -442,8 +444,14 @@ spring:
|
||||
connect-timeout: 2s
|
||||
read-timeout: 1s
|
||||
redirects: dont-follow
|
||||
cookie-handling: disable
|
||||
----
|
||||
|
||||
When `spring.http.clients.cookie-handling` is not set, the default cookie handling of the underlying HTTP client library is used.
|
||||
These defaults vary: for example, the Apache HttpComponents and Jetty clients store cookies and send them with subsequent requests whereas the JDK client ignores them.
|
||||
When cookie handling is enabled, each underlying HTTP client instance uses its own cookie store.
|
||||
Reactor Netty and the `simple` request factory do not support cookie handling so `enable` will fail with those clients and `enable-when-possible` will leave them unchanged.
|
||||
|
||||
|
||||
|
||||
[[io.rest-client.global-configuration.inetaddress-filtering]]
|
||||
|
||||
+10
-2
@@ -26,6 +26,7 @@ import org.apache.hc.client5.http.SystemDefaultDnsResolver;
|
||||
import org.apache.hc.client5.http.async.HttpAsyncClient;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.cookie.StandardCookieSpec;
|
||||
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
|
||||
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
|
||||
@@ -178,7 +179,7 @@ public final class HttpComponentsHttpAsyncClientBuilder {
|
||||
.useSystemProperties()
|
||||
.setRedirectStrategy(HttpComponentsRedirectStrategy.get(settings.redirects()))
|
||||
.setConnectionManager(createConnectionManager(settings))
|
||||
.setDefaultRequestConfig(createDefaultRequestConfig());
|
||||
.setDefaultRequestConfig(createDefaultRequestConfig(settings));
|
||||
this.customizer.accept(builder);
|
||||
return builder.build();
|
||||
}
|
||||
@@ -211,8 +212,15 @@ public final class HttpComponentsHttpAsyncClientBuilder {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private RequestConfig createDefaultRequestConfig() {
|
||||
private RequestConfig createDefaultRequestConfig(HttpClientSettings settings) {
|
||||
RequestConfig.Builder builder = RequestConfig.custom();
|
||||
if (settings.cookieHandling() != null) {
|
||||
String cookieSpec = switch (settings.cookieHandling()) {
|
||||
case ENABLE_WHEN_POSSIBLE, ENABLE -> StandardCookieSpec.STRICT;
|
||||
case DISABLE -> StandardCookieSpec.IGNORE;
|
||||
};
|
||||
builder.setCookieSpec(cookieSpec);
|
||||
}
|
||||
this.defaultRequestConfigCustomizer.accept(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
+5
-3
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.HttpCookieHandling;
|
||||
import org.springframework.boot.http.client.HttpRedirects;
|
||||
import org.springframework.boot.http.client.InetAddressFilter;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@@ -52,9 +53,10 @@ class HttpClientAutoConfigurationTests {
|
||||
void createsHttpClientSettingsFromProperties() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.http.clients.redirects=dont-follow", "spring.http.clients.connect-timeout=1s",
|
||||
"spring.http.clients.read-timeout=2s")
|
||||
.run((context) -> assertThat(context.getBean(HttpClientSettings.class)).isEqualTo(new HttpClientSettings(
|
||||
null, HttpRedirects.DONT_FOLLOW, Duration.ofSeconds(1), Duration.ofSeconds(2), null)));
|
||||
"spring.http.clients.read-timeout=2s", "spring.http.clients.cookie-handling=disable")
|
||||
.run((context) -> assertThat(context.getBean(HttpClientSettings.class))
|
||||
.isEqualTo(new HttpClientSettings(HttpCookieHandling.DISABLE, HttpRedirects.DONT_FOLLOW,
|
||||
Duration.ofSeconds(1), Duration.ofSeconds(2), null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+26
@@ -25,15 +25,19 @@ import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.async.HttpAsyncClient;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.cookie.StandardCookieSpec;
|
||||
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
||||
import org.apache.hc.core5.function.Resolver;
|
||||
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import org.springframework.boot.http.client.HttpClientSettings;
|
||||
import org.springframework.boot.http.client.HttpComponentsHttpAsyncClientBuilder;
|
||||
import org.springframework.boot.http.client.HttpCookieHandling;
|
||||
import org.springframework.boot.http.client.InetAddressFilter;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
@@ -129,6 +133,28 @@ class HttpComponentsClientHttpConnectorBuilderTests
|
||||
.isSameAs(dnsResolver);
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultCookieHandling() {
|
||||
HttpComponentsClientHttpConnector connector = ClientHttpConnectorBuilder.httpComponents()
|
||||
.build(HttpClientSettings.defaults());
|
||||
assertThat(connector).extracting("client.defaultConfig.cookieSpec").isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void cookieHandlingDisabled() {
|
||||
HttpComponentsClientHttpConnector connector = ClientHttpConnectorBuilder.httpComponents()
|
||||
.build(HttpClientSettings.defaults().withCookieHandling(HttpCookieHandling.DISABLE));
|
||||
assertThat(connector).extracting("client.defaultConfig.cookieSpec").isEqualTo(StandardCookieSpec.IGNORE);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(names = { "ENABLE", "ENABLE_WHEN_POSSIBLE" })
|
||||
void cookieHandlingEnabled(HttpCookieHandling cookieHandling) {
|
||||
HttpComponentsClientHttpConnector connector = ClientHttpConnectorBuilder.httpComponents()
|
||||
.build(HttpClientSettings.defaults().withCookieHandling(cookieHandling));
|
||||
assertThat(connector).extracting("client.defaultConfig.cookieSpec").isEqualTo(StandardCookieSpec.STRICT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long connectTimeout(HttpComponentsClientHttpConnector connector) {
|
||||
return getConnectorConfig(connector).getConnectTimeout().toMilliseconds();
|
||||
|
||||
Reference in New Issue
Block a user