Polish "Add configuration for HTML escaping configuration with WebFlux"

See gh-49791
This commit is contained in:
Stéphane Nicoll
2026-03-26 15:11:36 +01:00
parent 59f8dca1a4
commit c747c9c53d
4 changed files with 30 additions and 40 deletions
@@ -64,10 +64,13 @@ public final class HttpHandlerAutoConfiguration {
@Bean
HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider,
ObjectProvider<WebHttpHandlerBuilderCustomizer> handlerBuilderCustomizers) {
WebFluxProperties properties = propsProvider.getIfAvailable();
WebHttpHandlerBuilder handlerBuilder = WebHttpHandlerBuilder.applicationContext(this.applicationContext);
if (properties != null) {
handlerBuilder.defaultHtmlEscape(properties.getDefaultHtmlEscape());
}
handlerBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(handlerBuilder));
HttpHandler httpHandler = handlerBuilder.build();
WebFluxProperties properties = propsProvider.getIfAvailable();
if (properties != null && StringUtils.hasText(properties.getBasePath())) {
Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler);
return new ContextPathCompositeHandler(handlersMap);
@@ -304,11 +304,6 @@ public final class WebFluxAutoConfiguration {
.forEach((mediaType, parameterName) -> configurer.useMediaTypeParameter(mediaType, parameterName));
}
@Bean
WebHttpHandlerBuilderCustomizer defaultHtmlEscapeCustomizer() {
return (builder) -> builder.defaultHtmlEscape(this.webFluxProperties.getDefaultHtmlEscape());
}
}
/**
@@ -18,6 +18,8 @@ package org.springframework.boot.webflux.autoconfigure;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfigurations;
@@ -35,6 +37,7 @@ import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.WebHandler;
import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
@@ -100,6 +103,29 @@ class HttpHandlerAutoConfigurationTests {
});
}
@ParameterizedTest
@ValueSource(booleans = { true, false })
void shouldConfigureDefaultHtmlEscape(boolean enabled) {
this.contextRunner.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class))
.withPropertyValues("spring.webflux.default-html-escape=" + enabled)
.run((context) -> {
assertThat(context).hasSingleBean(HttpHandler.class);
assertThat(context.getBean(HttpHandler.class)).isInstanceOfSatisfying(HttpWebHandlerAdapter.class,
(adapter) -> assertThat(adapter.getDefaultHtmlEscape()).isEqualTo(enabled));
});
}
@Test
void shouldNotConfigureDefaultHtmlEscaperWithoutWebFluxAutoConfiguration() {
this.contextRunner.withUserConfiguration(CustomWebHandler.class)
.withPropertyValues("spring.webflux.default-html-escape=true")
.run((context) -> {
assertThat(context).hasSingleBean(HttpHandler.class);
assertThat(context.getBean(HttpHandler.class)).isInstanceOfSatisfying(HttpWebHandlerAdapter.class,
(adapter) -> assertThat(adapter.getDefaultHtmlEscape()).isNull());
});
}
@Configuration(proxyBeanMethods = false)
static class CustomHttpHandler {
@@ -120,7 +120,6 @@ import org.springframework.web.reactive.result.method.annotation.ResponseEntityE
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebHandler;
import org.springframework.web.server.WebSession;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
@@ -462,39 +461,6 @@ class WebFluxAutoConfigurationTests {
.run((context) -> assertThat(context).hasSingleBean(OrderedHiddenHttpMethodFilter.class));
}
@Test
void defaultHtmlEscapeIsNotConfiguredByDefault() {
this.contextRunner.run((context) -> {
WebHttpHandlerBuilderCustomizer customizer = context.getBean("defaultHtmlEscapeCustomizer",
WebHttpHandlerBuilderCustomizer.class);
WebHttpHandlerBuilder builder = WebHttpHandlerBuilder.webHandler(mock(WebHandler.class));
customizer.customize(builder);
assertThat(builder.getDefaultHtmlEscape()).isNull();
});
}
@Test
void defaultHtmlEscapeCanBeEnabled() {
this.contextRunner.withPropertyValues("spring.webflux.default-html-escape=true").run((context) -> {
WebHttpHandlerBuilderCustomizer customizer = context.getBean("defaultHtmlEscapeCustomizer",
WebHttpHandlerBuilderCustomizer.class);
WebHttpHandlerBuilder builder = WebHttpHandlerBuilder.webHandler(mock(WebHandler.class));
customizer.customize(builder);
assertThat(builder.getDefaultHtmlEscape()).isTrue();
});
}
@Test
void defaultHtmlEscapeCanBeDisabled() {
this.contextRunner.withPropertyValues("spring.webflux.default-html-escape=false").run((context) -> {
WebHttpHandlerBuilderCustomizer customizer = context.getBean("defaultHtmlEscapeCustomizer",
WebHttpHandlerBuilderCustomizer.class);
WebHttpHandlerBuilder builder = WebHttpHandlerBuilder.webHandler(mock(WebHandler.class));
customizer.customize(builder);
assertThat(builder.getDefaultHtmlEscape()).isFalse();
});
}
@Test
void customRequestMappingHandlerMapping() {
this.contextRunner.withUserConfiguration(CustomRequestMappingHandlerMapping.class).run((context) -> {