Rework server.servlet.encoding properties to clarify when they apply
Closes gh-45394
This commit is contained in:
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.http;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@@ -27,19 +25,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
|
||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.HttpMessageConvertersAutoConfigurationRuntimeHints;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.web.servlet.server.Encoding;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
|
||||
@@ -63,7 +56,6 @@ import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
@Conditional(NotReactiveWebApplicationCondition.class)
|
||||
@Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class,
|
||||
JsonbHttpMessageConvertersConfiguration.class })
|
||||
@ImportRuntimeHints(HttpMessageConvertersAutoConfigurationRuntimeHints.class)
|
||||
public class HttpMessageConvertersAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -74,13 +66,14 @@ public class HttpMessageConvertersAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(StringHttpMessageConverter.class)
|
||||
@EnableConfigurationProperties(HttpMessageConvertersProperties.class)
|
||||
protected static class StringHttpMessageConverterConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public StringHttpMessageConverter stringHttpMessageConverter(Environment environment) {
|
||||
Encoding encoding = Binder.get(environment).bindOrCreate("server.servlet.encoding", Encoding.class);
|
||||
StringHttpMessageConverter converter = new StringHttpMessageConverter(encoding.getCharset());
|
||||
public StringHttpMessageConverter stringHttpMessageConverter(HttpMessageConvertersProperties properties) {
|
||||
StringHttpMessageConverter converter = new StringHttpMessageConverter(
|
||||
properties.getStringEncodingCharset());
|
||||
converter.setWriteAcceptCharset(false);
|
||||
return converter;
|
||||
}
|
||||
@@ -100,13 +93,4 @@ public class HttpMessageConvertersAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class HttpMessageConvertersAutoConfigurationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
BindableRuntimeHintsRegistrar.forTypes(Encoding.class).registerHints(hints, classLoader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link ConfigurationProperties @ConfigurationProperties} for HTTP message conversion.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.http.converters")
|
||||
public class HttpMessageConvertersProperties {
|
||||
|
||||
/**
|
||||
* The charset to use for String conversion.
|
||||
*/
|
||||
private Charset stringEncodingCharset = StandardCharsets.UTF_8;
|
||||
|
||||
public Charset getStringEncodingCharset() {
|
||||
return this.stringEncodingCharset;
|
||||
}
|
||||
|
||||
public void setStringEncodingCharset(Charset stringEncodingCharset) {
|
||||
this.stringEncodingCharset = stringEncodingCharset;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import io.undertow.UndertowOptions;
|
||||
@@ -40,7 +41,6 @@ import org.springframework.boot.web.server.Http2;
|
||||
import org.springframework.boot.web.server.MimeMappings;
|
||||
import org.springframework.boot.web.server.Shutdown;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
import org.springframework.boot.web.servlet.server.Encoding;
|
||||
import org.springframework.boot.web.servlet.server.Jsp;
|
||||
import org.springframework.boot.web.servlet.server.Session;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -266,7 +266,6 @@ public class ServerProperties {
|
||||
*/
|
||||
private boolean registerDefaultServlet = false;
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final Encoding encoding = new Encoding();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
@@ -1970,4 +1969,21 @@ public class ServerProperties {
|
||||
|
||||
}
|
||||
|
||||
public static class Encoding {
|
||||
|
||||
/**
|
||||
* Mapping of locale to charset for response encoding.
|
||||
*/
|
||||
private Map<Locale, Charset> mapping;
|
||||
|
||||
public Map<Locale, Charset> getMapping() {
|
||||
return this.mapping;
|
||||
}
|
||||
|
||||
public void setMapping(Map<Locale, Charset> mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,73 +22,34 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProp
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.server.Encoding;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for configuring the encoding to use
|
||||
* in web applications.
|
||||
* in Servlet web applications.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(ServerProperties.class)
|
||||
@EnableConfigurationProperties(ServletEncodingProperties.class)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnClass(CharacterEncodingFilter.class)
|
||||
@ConditionalOnBooleanProperty(name = "server.servlet.encoding.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBooleanProperty(name = "spring.servlet.encoding.enabled", matchIfMissing = true)
|
||||
public class HttpEncodingAutoConfiguration {
|
||||
|
||||
private final Encoding properties;
|
||||
|
||||
public HttpEncodingAutoConfiguration(ServerProperties properties) {
|
||||
this.properties = properties.getServlet().getEncoding();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CharacterEncodingFilter characterEncodingFilter() {
|
||||
public CharacterEncodingFilter characterEncodingFilter(ServletEncodingProperties properties) {
|
||||
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
|
||||
filter.setEncoding(this.properties.getCharset().name());
|
||||
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
|
||||
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
|
||||
filter.setEncoding(properties.getCharset().name());
|
||||
filter.setForceRequestEncoding(properties.shouldForce(ServletEncodingProperties.HttpMessageType.REQUEST));
|
||||
filter.setForceResponseEncoding(properties.shouldForce(ServletEncodingProperties.HttpMessageType.RESPONSE));
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
|
||||
return new LocaleCharsetMappingsCustomizer(this.properties);
|
||||
}
|
||||
|
||||
static class LocaleCharsetMappingsCustomizer
|
||||
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
|
||||
|
||||
private final Encoding properties;
|
||||
|
||||
LocaleCharsetMappingsCustomizer(Encoding properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableServletWebServerFactory factory) {
|
||||
if (this.properties.getMapping() != null) {
|
||||
factory.setLocaleCharsetMappings(this.properties.getMapping());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,25 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.web.servlet.server;
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesSource;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration properties for server HTTP encoding.
|
||||
* {@link ConfigurationProperties @ConfigurationProperties} for Servlet encoding.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
* @since 2.3.0
|
||||
* @author Andy Wilkinson
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationPropertiesSource
|
||||
public class Encoding {
|
||||
@ConfigurationProperties("spring.servlet.encoding")
|
||||
public class ServletEncodingProperties {
|
||||
|
||||
/**
|
||||
* Default HTTP encoding for Servlet applications.
|
||||
@@ -62,11 +58,6 @@ public class Encoding {
|
||||
*/
|
||||
private Boolean forceResponse;
|
||||
|
||||
/**
|
||||
* Mapping of locale to charset for response encoding.
|
||||
*/
|
||||
private Map<Locale, Charset> mapping;
|
||||
|
||||
public Charset getCharset() {
|
||||
return this.charset;
|
||||
}
|
||||
@@ -99,21 +90,13 @@ public class Encoding {
|
||||
this.forceResponse = forceResponse;
|
||||
}
|
||||
|
||||
public Map<Locale, Charset> getMapping() {
|
||||
return this.mapping;
|
||||
}
|
||||
|
||||
public void setMapping(Map<Locale, Charset> mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public boolean shouldForce(Type type) {
|
||||
Boolean force = (type != Type.REQUEST) ? this.forceResponse : this.forceRequest;
|
||||
public boolean shouldForce(HttpMessageType type) {
|
||||
Boolean force = (type != HttpMessageType.REQUEST) ? this.forceResponse : this.forceRequest;
|
||||
if (force == null) {
|
||||
force = this.force;
|
||||
}
|
||||
if (force == null) {
|
||||
force = (type == Type.REQUEST);
|
||||
force = (type == HttpMessageType.REQUEST);
|
||||
}
|
||||
return force;
|
||||
}
|
||||
@@ -121,7 +104,7 @@ public class Encoding {
|
||||
/**
|
||||
* Type of HTTP message to consider for encoding configuration.
|
||||
*/
|
||||
public enum Type {
|
||||
public enum HttpMessageType {
|
||||
|
||||
/**
|
||||
* HTTP request message.
|
||||
@@ -96,6 +96,7 @@ public class ServletWebServerFactoryCustomizer
|
||||
.whenNot(CollectionUtils::isEmpty)
|
||||
.to(factory::setCookieSameSiteSuppliers);
|
||||
map.from(this.serverProperties::getMimeMappings).to(factory::addMimeMappings);
|
||||
map.from(this.serverProperties.getServlet().getEncoding()::getMapping).to(factory::setLocaleCharsetMappings);
|
||||
this.webListenerRegistrars.forEach((registrar) -> registrar.register(factory));
|
||||
}
|
||||
|
||||
|
||||
@@ -126,11 +126,54 @@
|
||||
"name": "server.reactive.session.cookie.secure",
|
||||
"description": "Whether to always mark the cookie as secure."
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.encoding.charset",
|
||||
"type": "java.nio.charset.Charset",
|
||||
"description": "Charset of HTTP requests and responses. Added to the Content-Type header if not set explicitly.",
|
||||
"deprecation": {
|
||||
"replacement": "spring.servlet.encoding.charset",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.encoding.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable http encoding support.",
|
||||
"defaultValue": true
|
||||
"defaultValue": true,
|
||||
"deprecation": {
|
||||
"replacement": "spring.servlet.encoding.enabled",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.encoding.force",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to force the encoding to the configured charset on HTTP requests and responses.",
|
||||
"defaultValue": false,
|
||||
"deprecation": {
|
||||
"replacement": "spring.servlet.encoding.force",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.encoding.force-request",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to force the encoding to the configured charset on HTTP requests. Defaults to true when force has not been specified.",
|
||||
"defaultValue": true,
|
||||
"deprecation": {
|
||||
"replacement": "spring.servlet.encoding.force-request",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.encoding.force-response",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to force the encoding to the configured charset on HTTP responses.",
|
||||
"defaultValue": false,
|
||||
"deprecation": {
|
||||
"replacement": "spring.servlet.encoding.force-response",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "server.servlet.jsp.class-name",
|
||||
@@ -2525,6 +2568,12 @@
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.servlet.encoding.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable Servlet HTTP encoding support.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.session.redis.cleanup-cron",
|
||||
"defaultValue": "0 * * * * *"
|
||||
|
||||
@@ -23,12 +23,9 @@ import com.google.gson.Gson;
|
||||
import jakarta.json.bind.Jsonb;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.HttpMessageConvertersAutoConfigurationRuntimeHints;
|
||||
import org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration;
|
||||
@@ -39,7 +36,6 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.server.Encoding;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
@@ -313,7 +309,7 @@ class HttpMessageConvertersAutoConfigurationTests {
|
||||
void whenEncodingCharsetIsConfiguredThenStringMessageConverterUsesSpecificCharset() {
|
||||
new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
||||
.withPropertyValues("server.servlet.encoding.charset=UTF-16")
|
||||
.withPropertyValues("spring.http.converters.string-encoding-charset=UTF-16")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(StringHttpMessageConverter.class);
|
||||
assertThat(context.getBean(StringHttpMessageConverter.class).getDefaultCharset())
|
||||
@@ -331,19 +327,6 @@ class HttpMessageConvertersAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRegisterHints() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new HttpMessageConvertersAutoConfigurationRuntimeHints().registerHints(hints, getClass().getClassLoader());
|
||||
assertThat(RuntimeHintsPredicates.reflection().onType(Encoding.class)).accepts(hints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Encoding.class, "getCharset")).accepts(hints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Encoding.class, "setCharset")).accepts(hints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Encoding.class, "isForce")).accepts(hints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Encoding.class, "setForce")).accepts(hints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Encoding.class, "shouldForce"))
|
||||
.rejects(hints);
|
||||
}
|
||||
|
||||
private ApplicationContextRunner allOptionsRunner() {
|
||||
return this.contextRunner.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, JsonbAutoConfiguration.class));
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -28,7 +25,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
|
||||
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
|
||||
@@ -69,53 +65,53 @@ class HttpEncodingAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void disableConfiguration() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.enabled:false");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.enabled:false");
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||
.isThrownBy(() -> this.context.getBean(CharacterEncodingFilter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customConfiguration() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.charset:ISO-8859-15",
|
||||
"server.servlet.encoding.force:false");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.charset:ISO-8859-15",
|
||||
"spring.servlet.encoding.force:false");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "ISO-8859-15", false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customFilterConfiguration() {
|
||||
load(FilterConfiguration.class, "server.servlet.encoding.charset:ISO-8859-15",
|
||||
"server.servlet.encoding.force:false");
|
||||
load(FilterConfiguration.class, "spring.servlet.encoding.charset:ISO-8859-15",
|
||||
"spring.servlet.encoding.force:false");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "US-ASCII", false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void forceRequest() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.force-request:false");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.force-request:false");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "UTF-8", false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void forceResponse() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.force-response:true");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.force-response:true");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "UTF-8", true, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void forceRequestOverridesForce() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.force:true",
|
||||
"server.servlet.encoding.force-request:false");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.force:true",
|
||||
"spring.servlet.encoding.force-request:false");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "UTF-8", false, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void forceResponseOverridesForce() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.force:true",
|
||||
"server.servlet.encoding.force-response:false");
|
||||
load(EmptyConfiguration.class, "spring.servlet.encoding.force:true",
|
||||
"spring.servlet.encoding.force-response:false");
|
||||
CharacterEncodingFilter filter = this.context.getBean(CharacterEncodingFilter.class);
|
||||
assertCharacterEncodingFilter(filter, "UTF-8", true, false);
|
||||
}
|
||||
@@ -129,30 +125,6 @@ class HttpEncodingAutoConfigurationTests {
|
||||
assertThat(beans.get(1)).isInstanceOf(HiddenHttpMethodFilter.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noLocaleCharsetMapping() {
|
||||
load(EmptyConfiguration.class);
|
||||
Map<String, WebServerFactoryCustomizer<?>> beans = getWebServerFactoryCustomizerBeans();
|
||||
assertThat(beans).hasSize(1);
|
||||
assertThat(this.context.getBean(MockServletWebServerFactory.class).getLocaleCharsetMappings()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void customLocaleCharsetMappings() {
|
||||
load(EmptyConfiguration.class, "server.servlet.encoding.mapping.en:UTF-8",
|
||||
"server.servlet.encoding.mapping.fr_FR:UTF-8");
|
||||
Map<String, WebServerFactoryCustomizer<?>> beans = getWebServerFactoryCustomizerBeans();
|
||||
assertThat(beans).hasSize(1);
|
||||
assertThat(this.context.getBean(MockServletWebServerFactory.class).getLocaleCharsetMappings()).hasSize(2)
|
||||
.containsEntry(Locale.ENGLISH, StandardCharsets.UTF_8)
|
||||
.containsEntry(Locale.FRANCE, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Map<String, WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
|
||||
return (Map) this.context.getBeansOfType(WebServerFactoryCustomizer.class);
|
||||
}
|
||||
|
||||
private void assertCharacterEncodingFilter(CharacterEncodingFilter actual, String encoding,
|
||||
boolean forceRequestEncoding, boolean forceResponseEncoding) {
|
||||
assertThat(actual.getEncoding()).isEqualTo(encoding);
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -38,9 +40,11 @@ import org.springframework.boot.web.servlet.server.Jsp;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.assertArg;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServletWebServerFactoryCustomizer}.
|
||||
@@ -193,6 +197,26 @@ class ServletWebServerFactoryCustomizerTests {
|
||||
then(factory).should().setShutdown(assertArg((shutdown) -> assertThat(shutdown).isEqualTo(Shutdown.IMMEDIATE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noLocaleCharsetMapping() {
|
||||
ConfigurableServletWebServerFactory factory = mock(ConfigurableServletWebServerFactory.class);
|
||||
this.customizer.customize(factory);
|
||||
then(factory).should(never()).setLocaleCharsetMappings(anyMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
void customLocaleCharsetMappings() {
|
||||
Map<String, String> map = Map.of("server.servlet.encoding.mapping.en", "UTF-8",
|
||||
"server.servlet.encoding.mapping.fr_FR", "UTF-8");
|
||||
bindProperties(map);
|
||||
ConfigurableServletWebServerFactory factory = mock(ConfigurableServletWebServerFactory.class);
|
||||
this.customizer.customize(factory);
|
||||
then(factory).should()
|
||||
.setLocaleCharsetMappings((assertArg((mappings) -> assertThat(mappings).hasSize(2)
|
||||
.containsEntry(Locale.ENGLISH, StandardCharsets.UTF_8)
|
||||
.containsEntry(Locale.FRANCE, StandardCharsets.UTF_8))));
|
||||
}
|
||||
|
||||
private void bindProperties(Map<String, String> map) {
|
||||
ConfigurationPropertySource source = new MapConfigurationPropertySource(map);
|
||||
new Binder(source).bind("server", Bindable.ofInstance(this.properties));
|
||||
|
||||
Reference in New Issue
Block a user