Skip to content

Add support for configuring Tomcat connector maxPartCount and maxPartHeaderSize #45890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
* @author Florian Storz
* @author Michael Weidmann
* @author Lasse Wulff
* @author Daeho Kwon
* @since 1.0.0
*/
@ConfigurationProperties("server")
Expand Down Expand Up @@ -519,6 +520,21 @@ public static class Tomcat {
*/
private int maxParameterCount = 10000;

/**
* The maximum total number of parts permitted in a request where the content type
* is multipart/form-data. This limit is in addition to maxParameterCount.
* Requests that exceed this limit will be rejected. A value of less than 0 means
* no limit.
*/
private int maxPartCount = 10;

/**
* The maximum number of header bytes permitted per part in a request where the
* content type is multipart/form-data. Requests that exceed this limit will be
* rejected. A value of less than 0 means no limit.
*/
private DataSize maxPartHeaderSize = DataSize.ofBytes(512);

/**
* Whether to use APR.
*/
Expand Down Expand Up @@ -688,6 +704,22 @@ public void setMaxParameterCount(int maxParameterCount) {
this.maxParameterCount = maxParameterCount;
}

public int getMaxPartCount() {
return this.maxPartCount;
}

public void setMaxPartCount(int maxPartCount) {
this.maxPartCount = maxPartCount;
}

public DataSize getMaxPartHeaderSize() {
return this.maxPartHeaderSize;
}

public void setMaxPartHeaderSize(DataSize maxPartHeaderSize) {
this.maxPartHeaderSize = maxPartHeaderSize;
}

public UseApr getUseApr() {
return this.useApr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
* @author Parviz Rozikov
* @author Florian Storz
* @author Michael Weidmann
* @author Daeho Kwon
* @since 2.0.0
*/
public class TomcatWebServerFactoryCustomizer
Expand Down Expand Up @@ -121,6 +122,10 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
map.from(properties::getMaxParameterCount)
.to((maxParameterCount) -> customizeMaxParameterCount(factory, maxParameterCount));
map.from(properties::getMaxPartCount).to((maxPartCount) -> customizeMaxPartCount(factory, maxPartCount));
map.from(properties::getMaxPartHeaderSize)
.asInt(DataSize::toBytes)
.to((maxPartHeaderSize) -> customizeMaxPartHeaderSize(factory, maxPartHeaderSize));
map.from(properties::getAccesslog)
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
.to((enabled) -> customizeAccessLog(factory));
Expand Down Expand Up @@ -298,6 +303,14 @@ private void customizeMaxParameterCount(ConfigurableTomcatWebServerFactory facto
factory.addConnectorCustomizers((connector) -> connector.setMaxParameterCount(maxParameterCount));
}

private void customizeMaxPartCount(ConfigurableTomcatWebServerFactory factory, int maxPartCount) {
factory.addConnectorCustomizers((connector) -> connector.setMaxPartCount(maxPartCount));
}

private void customizeMaxPartHeaderSize(ConfigurableTomcatWebServerFactory factory, int maxPartHeaderSize) {
factory.addConnectorCustomizers((connector) -> connector.setMaxPartHeaderSize(maxPartHeaderSize));
}

private void customizeAccessLog(ConfigurableTomcatWebServerFactory factory) {
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
AccessLogValve valve = new AccessLogValve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
* @author Parviz Rozikov
* @author Lasse Wulff
* @author Moritz Halbritter
* @author Daeho Kwon
*/
@DirtiesUrlFactories
class ServerPropertiesTests {
Expand Down Expand Up @@ -254,6 +255,18 @@ void testCustomizeTomcatMaxParameterCount() {
assertThat(this.properties.getTomcat().getMaxParameterCount()).isEqualTo(100);
}

@Test
void testCustomizeTomcatMaxPartCount() {
bind("server.tomcat.max-part-count", "20");
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(20);
}

@Test
void testCustomizeTomcatMaxPartHeaderSize() {
bind("server.tomcat.max-part-header-size", "1024");
assertThat(this.properties.getTomcat().getMaxPartHeaderSize()).isEqualTo(DataSize.ofKilobytes(1));
}

@Test
void testCustomizeTomcatMinSpareThreads() {
bind("server.tomcat.threads.min-spare", "10");
Expand Down Expand Up @@ -393,6 +406,17 @@ void tomcatMaxParameterCountMatchesConnectorDefault() {
.isEqualTo(getDefaultConnector().getMaxParameterCount());
}

@Test
void tomcatMaxPartCountMatchesConnectorDefault() {
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(getDefaultConnector().getMaxPartCount());
}

@Test
void tomcatMaxPartHeaderSizeMatchesConnectorDefault() {
assertThat(this.properties.getTomcat().getMaxPartHeaderSize().toBytes())
.isEqualTo(getDefaultConnector().getMaxPartHeaderSize());
}

@Test
void tomcatBackgroundProcessorDelayMatchesEngineDefault() {
assertThat(this.properties.getTomcat().getBackgroundProcessorDelay())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
* @author Victor Mandujano
* @author Parviz Rozikov
* @author Moritz Halbritter
* @author Daeho Kwon
*/
class TomcatWebServerFactoryCustomizerTests {

Expand Down Expand Up @@ -201,6 +202,20 @@ void customMaxParameterCount() {
(server) -> assertThat(server.getTomcat().getConnector().getMaxParameterCount()).isEqualTo(100));
}

@Test
void customMaxPartCount() {
bind("server.tomcat.max-part-count=20");
customizeAndRunServer(
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartCount()).isEqualTo(20));
}

@Test
void customMaxPartHeaderSize() {
bind("server.tomcat.max-part-header-size=1024");
customizeAndRunServer(
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartHeaderSize()).isEqualTo(1024));
}

@Test
void customMaxRequestHttpHeaderSizeIgnoredIfNegative() {
bind("server.max-http-request-header-size=-1");
Expand Down
Loading