From 0d40c5aeccacb3123d3d5b4eb4391031cddb4adf Mon Sep 17 00:00:00 2001 From: artsiom Date: Tue, 31 Jul 2018 23:53:30 +0300 Subject: [PATCH 1/2] Make "MaxSwallowSize" more easily configurable See gh-13966 --- .../boot/autoconfigure/web/ServerProperties.java | 14 ++++++++++++++ .../TomcatWebServerFactoryCustomizer.java | 16 ++++++++++++++++ .../autoconfigure/web/ServerPropertiesTests.java | 3 +++ .../TomcatWebServerFactoryCustomizerTests.java | 10 ++++++++++ .../appendix-application-properties.adoc | 1 + 5 files changed, 44 insertions(+) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index b943184bda4..d793754dfcb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -52,6 +52,7 @@ import org.springframework.util.StringUtils; * @author Aurélien Leboulanger * @author Brian Clozel * @author Olivier Lamy + * @author Artsiom Yudovin */ @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { @@ -359,6 +360,11 @@ public class ServerProperties { */ private int acceptCount = 0; + /** + * Maximum amount of request body to swallow. + */ + private int maxSwallowSize = 0; + /** * Comma-separated list of additional patterns that match jars to ignore for TLD * scanning. The special '?' and '*' characters can be used in the pattern to @@ -503,6 +509,14 @@ public class ServerProperties { this.acceptCount = acceptCount; } + public int getMaxSwallowSize() { + return this.maxSwallowSize; + } + + public void setMaxSwallowSize(int maxSwallowSize) { + this.maxSwallowSize = maxSwallowSize; + } + public List getAdditionalTldSkipPatterns() { return this.additionalTldSkipPatterns; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java index a39f6df1a34..be0bcc0d863 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java @@ -46,6 +46,7 @@ import org.springframework.util.StringUtils; * @author Yulin Qin * @author Stephane Nicoll * @author Phillip Webb + * @author Artsiom Yudovin * @since 2.0.0 */ public class TomcatWebServerFactoryCustomizer implements @@ -101,6 +102,9 @@ public class TomcatWebServerFactoryCustomizer implements .to((maxConnections) -> customizeMaxConnections(factory, maxConnections)); propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive) .to((acceptCount) -> customizeAcceptCount(factory, acceptCount)); + propertyMapper.from(tomcatProperties::getMaxSwallowSize) + .when((maxSwallowSize) -> maxSwallowSize != 0) + .to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize)); customizeStaticResources(factory); customizeErrorReportValve(properties.getError(), factory); } @@ -266,4 +270,16 @@ public class TomcatWebServerFactoryCustomizer implements } } + @SuppressWarnings("rawtypes") + private void customizeMaxSwallowSize(ConfigurableTomcatWebServerFactory factory, + int maxSwallowSize) { + factory.addConnectorCustomizers((connector) -> { + ProtocolHandler handler = connector.getProtocolHandler(); + if (handler instanceof AbstractHttp11Protocol) { + AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler; + protocol.setMaxSwallowSize(maxSwallowSize); + } + }); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 771c3b646ca..c7763e61bbb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Eddú Meléndez * @author Quinten De Swaef * @author Venil Noronha + * @author Artsiom Yudovin */ public class ServerPropertiesTests { @@ -91,6 +92,7 @@ public class ServerPropertiesTests { map.put("server.tomcat.remote-ip-header", "Remote-Ip"); map.put("server.tomcat.internal-proxies", "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); map.put("server.tomcat.background-processor-delay", "10"); + map.put("server.tomcat.max-swallow-size", "2"); bind(map); ServerProperties.Tomcat tomcat = this.properties.getTomcat(); assertThat(tomcat.getAccesslog().getPattern()).isEqualTo("%h %t '%r' %s %b"); @@ -105,6 +107,7 @@ public class ServerPropertiesTests { .isEqualTo("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); assertThat(tomcat.getBackgroundProcessorDelay()) .isEqualTo(Duration.ofSeconds(10)); + assertThat(tomcat.getMaxSwallowSize()).isEqualTo(2); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java index ce43fac13dc..ad02f429637 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java @@ -28,6 +28,7 @@ import org.apache.catalina.valves.ErrorReportValve; import org.apache.catalina.valves.RemoteIpValve; import org.apache.catalina.webresources.StandardRoot; import org.apache.coyote.AbstractProtocol; +import org.apache.coyote.http11.AbstractHttp11Protocol; import org.junit.Before; import org.junit.Test; @@ -49,6 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Brian Clozel * @author Phillip Webb * @author Rob Tompkins + * @author Artsiom Yudovin */ public class TomcatWebServerFactoryCustomizerTests { @@ -67,6 +69,14 @@ public class TomcatWebServerFactoryCustomizerTests { this.serverProperties); } + @Test + public void customMaxSwallowSize() { + bind("server.tomcat.max-swallow-size=10"); + customizeAndRunServer((server) -> assertThat(((AbstractHttp11Protocol) server + .getTomcat().getConnector().getProtocolHandler()).getMaxSwallowSize()) + .isEqualTo(10)); + } + @Test public void customAcceptCount() { bind("server.tomcat.accept-count=10"); diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index dbc2f8d9af1..bd12b0a38d4 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -263,6 +263,7 @@ content into your application. Rather, pick only the properties that you need. server.tomcat.resource.cache-ttl= # Time-to-live of the static resource cache. server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI. server.tomcat.use-relative-redirects= # Whether HTTP 1.1 and later location headers generated by a call to sendRedirect will use relative or absolute redirects. + server.tomcat.max-swallow-size= # Maximum amount of request body to swallow. server.undertow.accesslog.dir= # Undertow access log directory. server.undertow.accesslog.enabled=false # Whether to enable the access log. server.undertow.accesslog.pattern=common # Format pattern for access logs. From a8b9718073ec997e3cd4f0a696ed65a4af33364a Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 2 Aug 2018 16:06:12 +0200 Subject: [PATCH 2/2] Polish "Make "MaxSwallowSize" more easily configurable" Closes gh-13966 --- .../autoconfigure/web/ServerProperties.java | 27 +++++++++--------- .../TomcatWebServerFactoryCustomizer.java | 28 +++++++++---------- .../web/ServerPropertiesTests.java | 3 -- ...TomcatWebServerFactoryCustomizerTests.java | 20 +++++++++---- .../appendix-application-properties.adoc | 2 +- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index d793754dfcb..68bc334d47f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -52,7 +52,6 @@ import org.springframework.util.StringUtils; * @author Aurélien Leboulanger * @author Brian Clozel * @author Olivier Lamy - * @author Artsiom Yudovin */ @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { @@ -330,6 +329,11 @@ public class ServerProperties { */ private int maxHttpHeaderSize = 0; + /** + * Maximum amount of request body bytes to swallow. + */ + private int maxSwallowSize = 4096; + /** * Whether requests to the context root should be redirected by appending a / to * the path. @@ -360,11 +364,6 @@ public class ServerProperties { */ private int acceptCount = 0; - /** - * Maximum amount of request body to swallow. - */ - private int maxSwallowSize = 0; - /** * Comma-separated list of additional patterns that match jars to ignore for TLD * scanning. The special '?' and '*' characters can be used in the pattern to @@ -497,6 +496,14 @@ public class ServerProperties { return this.maxHttpHeaderSize; } + public int getMaxSwallowSize() { + return this.maxSwallowSize; + } + + public void setMaxSwallowSize(int maxSwallowSize) { + this.maxSwallowSize = maxSwallowSize; + } + public void setMaxHttpHeaderSize(int maxHttpHeaderSize) { this.maxHttpHeaderSize = maxHttpHeaderSize; } @@ -509,14 +516,6 @@ public class ServerProperties { this.acceptCount = acceptCount; } - public int getMaxSwallowSize() { - return this.maxSwallowSize; - } - - public void setMaxSwallowSize(int maxSwallowSize) { - this.maxSwallowSize = maxSwallowSize; - } - public List getAdditionalTldSkipPatterns() { return this.additionalTldSkipPatterns; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java index be0bcc0d863..b2f70db2f62 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java @@ -86,6 +86,8 @@ public class TomcatWebServerFactoryCustomizer implements propertyMapper.from(() -> determineMaxHttpHeaderSize()).when(this::isPositive) .to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize)); + propertyMapper.from(tomcatProperties::getMaxSwallowSize) + .to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize)); propertyMapper.from(tomcatProperties::getMaxHttpPostSize) .when((maxHttpPostSize) -> maxHttpPostSize != 0) .to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, @@ -102,9 +104,6 @@ public class TomcatWebServerFactoryCustomizer implements .to((maxConnections) -> customizeMaxConnections(factory, maxConnections)); propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive) .to((acceptCount) -> customizeAcceptCount(factory, acceptCount)); - propertyMapper.from(tomcatProperties::getMaxSwallowSize) - .when((maxSwallowSize) -> maxSwallowSize != 0) - .to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize)); customizeStaticResources(factory); customizeErrorReportValve(properties.getError(), factory); } @@ -220,6 +219,17 @@ public class TomcatWebServerFactoryCustomizer implements }); } + private void customizeMaxSwallowSize(ConfigurableTomcatWebServerFactory factory, + int maxSwallowSize) { + factory.addConnectorCustomizers((connector) -> { + ProtocolHandler handler = connector.getProtocolHandler(); + if (handler instanceof AbstractHttp11Protocol) { + AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler; + protocol.setMaxSwallowSize(maxSwallowSize); + } + }); + } + private void customizeMaxHttpPostSize(ConfigurableTomcatWebServerFactory factory, int maxHttpPostSize) { factory.addConnectorCustomizers( @@ -270,16 +280,4 @@ public class TomcatWebServerFactoryCustomizer implements } } - @SuppressWarnings("rawtypes") - private void customizeMaxSwallowSize(ConfigurableTomcatWebServerFactory factory, - int maxSwallowSize) { - factory.addConnectorCustomizers((connector) -> { - ProtocolHandler handler = connector.getProtocolHandler(); - if (handler instanceof AbstractHttp11Protocol) { - AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler; - protocol.setMaxSwallowSize(maxSwallowSize); - } - }); - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index c7763e61bbb..771c3b646ca 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -42,7 +42,6 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Eddú Meléndez * @author Quinten De Swaef * @author Venil Noronha - * @author Artsiom Yudovin */ public class ServerPropertiesTests { @@ -92,7 +91,6 @@ public class ServerPropertiesTests { map.put("server.tomcat.remote-ip-header", "Remote-Ip"); map.put("server.tomcat.internal-proxies", "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); map.put("server.tomcat.background-processor-delay", "10"); - map.put("server.tomcat.max-swallow-size", "2"); bind(map); ServerProperties.Tomcat tomcat = this.properties.getTomcat(); assertThat(tomcat.getAccesslog().getPattern()).isEqualTo("%h %t '%r' %s %b"); @@ -107,7 +105,6 @@ public class ServerPropertiesTests { .isEqualTo("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); assertThat(tomcat.getBackgroundProcessorDelay()) .isEqualTo(Duration.ofSeconds(10)); - assertThat(tomcat.getMaxSwallowSize()).isEqualTo(2); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java index ad02f429637..d5b58abaefc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java @@ -51,6 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Phillip Webb * @author Rob Tompkins * @author Artsiom Yudovin + * @author Stephane Nicoll */ public class TomcatWebServerFactoryCustomizerTests { @@ -70,11 +71,12 @@ public class TomcatWebServerFactoryCustomizerTests { } @Test - public void customMaxSwallowSize() { - bind("server.tomcat.max-swallow-size=10"); - customizeAndRunServer((server) -> assertThat(((AbstractHttp11Protocol) server - .getTomcat().getConnector().getProtocolHandler()).getMaxSwallowSize()) - .isEqualTo(10)); + public void defaultsAreConsistent() { + customizeAndRunServer((server) -> { + assertThat(((AbstractHttp11Protocol) server.getTomcat().getConnector() + .getProtocolHandler()).getMaxSwallowSize()).isEqualTo( + this.serverProperties.getTomcat().getMaxSwallowSize()); + }); } @Test @@ -117,6 +119,14 @@ public class TomcatWebServerFactoryCustomizerTests { .isEqualTo(10000)); } + @Test + public void customMaxSwallowSize() { + bind("server.tomcat.max-swallow-size=10"); + customizeAndRunServer((server) -> assertThat(((AbstractHttp11Protocol) server + .getTomcat().getConnector().getProtocolHandler()).getMaxSwallowSize()) + .isEqualTo(10)); + } + @Test public void customRemoteIpValve() { bind("server.tomcat.remote-ip-header=x-my-remote-ip-header", diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index bd12b0a38d4..50add4549be 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -252,6 +252,7 @@ content into your application. Rather, pick only the properties that you need. server.tomcat.max-connections=0 # Maximum number of connections that the server accepts and processes at any given time. server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header. server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content. + server.tomcat.max-swallow-size=4096 # Maximum amount of request body bytes to swallow. server.tomcat.max-threads=0 # Maximum number of worker threads. server.tomcat.min-spare-threads=0 # Minimum number of worker threads. server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value. @@ -263,7 +264,6 @@ content into your application. Rather, pick only the properties that you need. server.tomcat.resource.cache-ttl= # Time-to-live of the static resource cache. server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI. server.tomcat.use-relative-redirects= # Whether HTTP 1.1 and later location headers generated by a call to sendRedirect will use relative or absolute redirects. - server.tomcat.max-swallow-size= # Maximum amount of request body to swallow. server.undertow.accesslog.dir= # Undertow access log directory. server.undertow.accesslog.enabled=false # Whether to enable the access log. server.undertow.accesslog.pattern=common # Format pattern for access logs.