Skip to content

Commit 6de3c1c

Browse files
committed
Merge branch 'main' into 4.0.x
2 parents 80b1f9c + fa81ecd commit 6de3c1c

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,20 @@ public static class Tomcat {
411411
*/
412412
private DataSize maxHttpFormPostSize = DataSize.ofMegabytes(2);
413413

414+
/**
415+
* Maximum per-part header size permitted in a multipart/form-data request.
416+
* Requests that exceed this limit will be rejected. A value of less than 0 means
417+
* no limit.
418+
*/
419+
private DataSize maxPartHeaderSize = DataSize.ofBytes(512);
420+
421+
/**
422+
* Maximum total number of parts permitted in a multipart/form-data request.
423+
* Requests that exceed this limit will be rejected. A value of less than 0 means
424+
* no limit.
425+
*/
426+
private int maxPartCount = 10;
427+
414428
/**
415429
* Maximum amount of request body to swallow.
416430
*/
@@ -523,6 +537,22 @@ public static class Tomcat {
523537
*/
524538
private UseApr useApr = UseApr.NEVER;
525539

540+
public DataSize getMaxPartHeaderSize() {
541+
return this.maxPartHeaderSize;
542+
}
543+
544+
public void setMaxPartHeaderSize(DataSize maxPartHeaderSize) {
545+
this.maxPartHeaderSize = maxPartHeaderSize;
546+
}
547+
548+
public int getMaxPartCount() {
549+
return this.maxPartCount;
550+
}
551+
552+
public void setMaxPartCount(int maxPartCount) {
553+
this.maxPartCount = maxPartCount;
554+
}
555+
526556
public Accesslog getAccesslog() {
527557
return this.accesslog;
528558
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
121121
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
122122
map.from(properties::getMaxParameterCount)
123123
.to((maxParameterCount) -> customizeMaxParameterCount(factory, maxParameterCount));
124+
map.from(properties::getMaxPartHeaderSize)
125+
.asInt(DataSize::toBytes)
126+
.to((maxPartHeaderSize) -> customizeMaxPartHeaderSize(factory, maxPartHeaderSize));
127+
map.from(properties::getMaxPartCount).to((maxPartCount) -> customizeMaxPartCount(factory, maxPartCount));
124128
map.from(properties::getAccesslog)
125129
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
126130
.to((enabled) -> customizeAccessLog(factory));
@@ -298,6 +302,28 @@ private void customizeMaxParameterCount(ConfigurableTomcatWebServerFactory facto
298302
factory.addConnectorCustomizers((connector) -> connector.setMaxParameterCount(maxParameterCount));
299303
}
300304

305+
private void customizeMaxPartCount(ConfigurableTomcatWebServerFactory factory, int maxPartCount) {
306+
factory.addConnectorCustomizers((connector) -> {
307+
try {
308+
connector.setMaxPartCount(maxPartCount);
309+
}
310+
catch (NoSuchMethodError ex) {
311+
// Tomcat < 10.1.42
312+
}
313+
});
314+
}
315+
316+
private void customizeMaxPartHeaderSize(ConfigurableTomcatWebServerFactory factory, int maxPartHeaderSize) {
317+
factory.addConnectorCustomizers((connector) -> {
318+
try {
319+
connector.setMaxPartHeaderSize(maxPartHeaderSize);
320+
}
321+
catch (NoSuchMethodError ex) {
322+
// Tomcat < 10.1.42
323+
}
324+
});
325+
}
326+
301327
private void customizeAccessLog(ConfigurableTomcatWebServerFactory factory) {
302328
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
303329
AccessLogValve valve = new AccessLogValve();

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,18 @@ void testCustomizeTomcatMinSpareThreads() {
260260
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
261261
}
262262

263+
@Test
264+
void customizeTomcatMaxPartCount() {
265+
bind("server.tomcat.max-part-count", "5");
266+
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(5);
267+
}
268+
269+
@Test
270+
void customizeTomcatMaxPartHeaderSize() {
271+
bind("server.tomcat.max-part-header-size", "128");
272+
assertThat(this.properties.getTomcat().getMaxPartHeaderSize()).isEqualTo(DataSize.ofBytes(128));
273+
}
274+
263275
@Test
264276
void testCustomizeJettyAcceptors() {
265277
bind("server.jetty.threads.acceptors", "10");
@@ -405,6 +417,17 @@ void tomcatMaxHttpFormPostSizeMatchesConnectorDefault() {
405417
.isEqualTo(getDefaultConnector().getMaxPostSize());
406418
}
407419

420+
@Test
421+
void tomcatMaxPartCountMatchesConnectorDefault() {
422+
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(getDefaultConnector().getMaxPartCount());
423+
}
424+
425+
@Test
426+
void tomcatMaxPartHeaderSizeMatchesConnectorDefault() {
427+
assertThat(this.properties.getTomcat().getMaxPartHeaderSize().toBytes())
428+
.isEqualTo(getDefaultConnector().getMaxPartHeaderSize());
429+
}
430+
408431
@Test
409432
void tomcatUriEncodingMatchesConnectorDefault() {
410433
assertThat(this.properties.getTomcat().getUriEncoding().name())

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.springframework.boot.context.properties.bind.Bindable;
3838
import org.springframework.boot.context.properties.bind.Binder;
3939
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
40+
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
41+
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
4042
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
4143
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
4244
import org.springframework.boot.web.server.WebServer;
@@ -45,6 +47,7 @@
4547
import org.springframework.util.unit.DataSize;
4648

4749
import static org.assertj.core.api.Assertions.assertThat;
50+
import static org.assertj.core.api.Assertions.assertThatNoException;
4851

4952
/**
5053
* Tests for {@link TomcatWebServerFactoryCustomizer}
@@ -60,6 +63,7 @@
6063
* @author Parviz Rozikov
6164
* @author Moritz Halbritter
6265
*/
66+
@DirtiesUrlFactories
6367
class TomcatWebServerFactoryCustomizerTests {
6468

6569
private MockEnvironment environment;
@@ -177,6 +181,37 @@ void customMaxHttpFormPostSize() {
177181
(server) -> assertThat(server.getTomcat().getConnector().getMaxPostSize()).isEqualTo(10000));
178182
}
179183

184+
@Test
185+
void defaultMaxPartCount() {
186+
customizeAndRunServer(
187+
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartCount()).isEqualTo(10));
188+
}
189+
190+
@Test
191+
void customMaxPartCount() {
192+
bind("server.tomcat.max-part-count=5");
193+
customizeAndRunServer((server) -> assertThat(server.getTomcat().getConnector().getMaxPartCount()).isEqualTo(5));
194+
}
195+
196+
@Test
197+
void defaultMaxPartHeaderSize() {
198+
customizeAndRunServer(
199+
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartHeaderSize()).isEqualTo(512));
200+
}
201+
202+
@Test
203+
void customMaxPartHeaderSize() {
204+
bind("server.tomcat.max-part-header-size=4KB");
205+
customizeAndRunServer(
206+
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartHeaderSize()).isEqualTo(4096));
207+
}
208+
209+
@Test
210+
@ClassPathOverrides("org.apache.tomcat.embed:tomcat-embed-core:10.1.41")
211+
void customizerIsCompatibleWithTomcatVersionsWithoutMaxPartCountAndMaxPartHeaderSize() {
212+
assertThatNoException().isThrownBy(this::customizeAndRunServer);
213+
}
214+
180215
@Test
181216
void defaultMaxHttpRequestHeaderSize() {
182217
customizeAndRunServer((server) -> assertThat(
@@ -593,11 +628,17 @@ private void bind(String... inlinedProperties) {
593628
Bindable.ofInstance(this.serverProperties));
594629
}
595630

631+
private void customizeAndRunServer() {
632+
customizeAndRunServer(null);
633+
}
634+
596635
private void customizeAndRunServer(Consumer<TomcatWebServer> consumer) {
597636
TomcatWebServer server = customizeAndGetServer();
598637
server.start();
599638
try {
600-
consumer.accept(server);
639+
if (consumer != null) {
640+
consumer.accept(server);
641+
}
601642
}
602643
finally {
603644
server.stop();

0 commit comments

Comments
 (0)