diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.java index eade4b54df..95930db476 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.java @@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.web.HttpEncodingProperties.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter; import org.springframework.context.annotation.Bean; @@ -39,18 +40,19 @@ import org.springframework.web.filter.CharacterEncodingFilter; @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { - private final HttpEncodingProperties httpEncodingProperties; + private final HttpEncodingProperties properties; - public HttpEncodingAutoConfiguration(HttpEncodingProperties httpEncodingProperties) { - this.httpEncodingProperties = httpEncodingProperties; + public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) { + this.properties = properties; } @Bean @ConditionalOnMissingBean(CharacterEncodingFilter.class) public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); - filter.setEncoding(this.httpEncodingProperties.getCharset().name()); - filter.setForceRequestEncoding(this.httpEncodingProperties.isForce()); + filter.setEncoding(this.properties.getCharset().name()); + filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); + filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingProperties.java index 0fb2fed72c..13892b3811 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpEncodingProperties.java @@ -40,7 +40,17 @@ public class HttpEncodingProperties { /** * Force the encoding to the configured charset on HTTP requests and responses. */ - private boolean force = true; + private Boolean force; + + /** + * Force the encoding to the configured charset on HTTP requests. + */ + private Boolean forceRequest; + + /** + * Force the encoding to the configured charset on HTTP responses. + */ + private Boolean forceResponse; public Charset getCharset() { return this.charset; @@ -51,11 +61,42 @@ public class HttpEncodingProperties { } public boolean isForce() { - return this.force; + return Boolean.TRUE.equals(this.force); } public void setForce(boolean force) { this.force = force; } + public boolean isForceRequest() { + return Boolean.TRUE.equals(this.forceRequest); + } + + public void setForceRequest(boolean forceRequest) { + this.forceRequest = forceRequest; + } + + public boolean isForceResponse() { + return Boolean.TRUE.equals(this.forceResponse); + } + + public void setForceResponse(boolean forceResponse) { + this.forceResponse = forceResponse; + } + + boolean shouldForce(Type type) { + Boolean force = (type == Type.REQUEST ? this.forceRequest : this.forceResponse); + if (force == null) { + force = this.force; + } + if (force == null) { + force = (type == Type.REQUEST ? true : false); + } + return force; + } + + enum Type { + REQUEST, RESPONSE + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfigurationTests.java index 12cbda1d69..45bc254aef 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfigurationTests.java @@ -63,7 +63,7 @@ public class HttpEncodingAutoConfigurationTests { load(EmptyConfiguration.class); CharacterEncodingFilter filter = this.context .getBean(CharacterEncodingFilter.class); - assertCharacterEncodingFilter(filter, "UTF-8", true); + assertCharacterEncodingFilter(filter, "UTF-8", true, false); } @Test @@ -79,7 +79,7 @@ public class HttpEncodingAutoConfigurationTests { "spring.http.encoding.force:false"); CharacterEncodingFilter filter = this.context .getBean(CharacterEncodingFilter.class); - assertCharacterEncodingFilter(filter, "ISO-8859-15", false); + assertCharacterEncodingFilter(filter, "ISO-8859-15", false, false); } @Test @@ -88,7 +88,41 @@ public class HttpEncodingAutoConfigurationTests { "spring.http.encoding.force:false"); CharacterEncodingFilter filter = this.context .getBean(CharacterEncodingFilter.class); - assertCharacterEncodingFilter(filter, "US-ASCII", false); + assertCharacterEncodingFilter(filter, "US-ASCII", false, false); + } + + @Test + public void forceRequest() throws Exception { + load(EmptyConfiguration.class, "spring.http.encoding.force-request:false"); + CharacterEncodingFilter filter = this.context + .getBean(CharacterEncodingFilter.class); + assertCharacterEncodingFilter(filter, "UTF-8", false, false); + } + + @Test + public void forceResponse() throws Exception { + load(EmptyConfiguration.class, "spring.http.encoding.force-response:true"); + CharacterEncodingFilter filter = this.context + .getBean(CharacterEncodingFilter.class); + assertCharacterEncodingFilter(filter, "UTF-8", true, true); + } + + @Test + public void forceRequestOverridesForce() throws Exception { + load(EmptyConfiguration.class, "spring.http.encoding.force:true", + "spring.http.encoding.force-request:false"); + CharacterEncodingFilter filter = this.context + .getBean(CharacterEncodingFilter.class); + assertCharacterEncodingFilter(filter, "UTF-8", false, true); + } + + @Test + public void forceResponseOverridesForce() throws Exception { + load(EmptyConfiguration.class, "spring.http.encoding.force:true", + "spring.http.encoding.force-response:false"); + CharacterEncodingFilter filter = this.context + .getBean(CharacterEncodingFilter.class); + assertCharacterEncodingFilter(filter, "UTF-8", true, false); } @Test @@ -102,10 +136,11 @@ public class HttpEncodingAutoConfigurationTests { } private void assertCharacterEncodingFilter(CharacterEncodingFilter actual, - String encoding, boolean forceRequestEncoding) { + String encoding, boolean forceRequestEncoding, + boolean forceResponseEncoding) { assertThat(actual.getEncoding()).isEqualTo(encoding); assertThat(actual.isForceRequestEncoding()).isEqualTo(forceRequestEncoding); - assertThat(actual.isForceResponseEncoding()).isFalse(); + assertThat(actual.isForceResponseEncoding()).isEqualTo(forceResponseEncoding); } private void load(Class config, String... environment) { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 5ced0c3459..0b7906842b 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -268,7 +268,9 @@ content into your application; rather pick only the properties that you need. # HTTP encoding ({sc-spring-boot-autoconfigure}/web/HttpEncodingProperties.{sc-ext}[HttpEncodingProperties]) spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly. spring.http.encoding.enabled=true # Enable http encoding support. - spring.http.encoding.force=true # Force the encoding to the configured charset on HTTP requests and responses. + spring.http.encoding.force= # Force the encoding to the configured charset on HTTP requests and responses. + spring.http.encoding.force-request= # Force the encoding to the configured charset on HTTP requests (defaults to true when ".force" has not been specified). + spring.http.encoding.force-response= # Force the encoding to the configured charset on HTTP responses. # MULTIPART ({sc-spring-boot-autoconfigure}/web/MultipartProperties.{sc-ext}[MultipartProperties]) spring.http.multipart.enabled=true # Enable support of multi-part uploads.