Fix null customizer checks in HTTP client builders

AbstractClientHttpRequestFactoryBuilder.mergedCustomizers and its
reactive counterpart asserted on the customizers field rather than
the customizer parameter. The field is never null since the
constructor defaults it to an empty list, so the assertion always
passed and a null customizer was not rejected.

See gh-51509

Signed-off-by: kdomo <dongho5088@naver.com>
This commit is contained in:
kdomo
2026-08-30 20:16:15 +02:00
committed by Stéphane Nicoll
parent fea4844b1a
commit 93a24eabb1
7 changed files with 31 additions and 4 deletions
@@ -48,7 +48,7 @@ abstract class AbstractClientHttpRequestFactoryBuilder<T extends ClientHttpReque
}
protected final List<Consumer<T>> mergedCustomizers(Consumer<T> customizer) {
Assert.notNull(this.customizers, "'customizer' must not be null");
Assert.notNull(customizer, "'customizer' must not be null");
return merge(this.customizers, List.of(customizer));
}
@@ -49,7 +49,7 @@ abstract class AbstractClientHttpConnectorBuilder<T extends ClientHttpConnector>
}
protected final List<Consumer<T>> mergedCustomizers(Consumer<T> customizer) {
Assert.notNull(this.customizers, "'customizer' must not be null");
Assert.notNull(customizer, "'customizer' must not be null");
return merge(this.customizers, List.of(customizer));
}
@@ -139,7 +139,7 @@ public interface ClientHttpConnectorBuilder<T extends ClientHttpConnector> {
*/
@SuppressWarnings("unchecked")
static <T extends ClientHttpConnector> ClientHttpConnectorBuilder<T> of(Class<T> clientHttpConnectorType) {
Assert.notNull(clientHttpConnectorType, "'requestFactoryType' must not be null");
Assert.notNull(clientHttpConnectorType, "'clientHttpConnectorType' must not be null");
Assert.isTrue(clientHttpConnectorType != ClientHttpConnector.class,
"'clientHttpConnectorType' must be an implementation of ClientHttpConnector");
if (clientHttpConnectorType == ReactorClientHttpConnector.class) {
@@ -66,7 +66,7 @@ public final class HttpComponentsClientHttpConnectorBuilder
*/
public HttpComponentsClientHttpConnectorBuilder withHttpClientCustomizer(
Consumer<HttpAsyncClientBuilder> httpClientCustomizer) {
Assert.notNull(httpClientCustomizer, "'customizer' must not be null");
Assert.notNull(httpClientCustomizer, "'httpClientCustomizer' must not be null");
return new HttpComponentsClientHttpConnectorBuilder(getCustomizers(),
this.httpClientBuilder.withCustomizer(httpClientCustomizer));
}
@@ -16,6 +16,7 @@
package org.springframework.boot.http.client;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -25,6 +26,7 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
@@ -81,6 +83,14 @@ class SimpleClientHttpRequestFactoryBuilderTests
super.redirectDontFollow(httpMethod);
}
@Test
@SuppressWarnings("NullAway") // Test null check
void withCustomizerWhenCustomizerIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> ClientHttpRequestFactoryBuilder.simple().withCustomizer(null))
.withMessage("'customizer' must not be null");
}
@Override
protected HttpStatus getExpectedRedirect(HttpMethod httpMethod) {
return (httpMethod != HttpMethod.GET) ? HttpStatus.FOUND : HttpStatus.OK;
@@ -39,6 +39,7 @@ import org.springframework.http.client.reactive.HttpComponentsClientHttpConnecto
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link HttpComponentsClientHttpConnectorBuilder} and
@@ -80,6 +81,14 @@ class HttpComponentsClientHttpConnectorBuilderTests
defaultRequestConfigCustomizer1.assertCalled();
}
@Test
@SuppressWarnings("NullAway") // Test null check
void withHttpClientCustomizerWhenCustomizerIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> ClientHttpConnectorBuilder.httpComponents().withHttpClientCustomizer(null))
.withMessage("'httpClientCustomizer' must not be null");
}
@Test
@WithPackageResources("test.jks")
void withTlsSocketStrategyFactory() {
@@ -28,6 +28,7 @@ import org.springframework.http.client.reactive.JdkClientHttpConnector;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link JdkClientHttpConnectorBuilder} and {@link JdkHttpClientBuilder}.
@@ -52,6 +53,13 @@ class JdkClientHttpConnectorBuilderTests extends AbstractClientHttpConnectorBuil
httpClientCustomizer2.assertCalled();
}
@Test
@SuppressWarnings("NullAway") // Test null check
void withCustomizerWhenCustomizerIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> ClientHttpConnectorBuilder.jdk().withCustomizer(null))
.withMessage("'customizer' must not be null");
}
@Test
void withExecutor() {
Executor executor = new SimpleAsyncTaskExecutor();