commit
fa81ecddc1
|
@ -412,6 +412,20 @@ public class ServerProperties {
|
||||||
*/
|
*/
|
||||||
private DataSize maxHttpFormPostSize = DataSize.ofMegabytes(2);
|
private DataSize maxHttpFormPostSize = DataSize.ofMegabytes(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum per-part header size permitted in a multipart/form-data request.
|
||||||
|
* Requests that exceed this limit will be rejected. A value of less than 0 means
|
||||||
|
* no limit.
|
||||||
|
*/
|
||||||
|
private DataSize maxPartHeaderSize = DataSize.ofBytes(512);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum total number of parts permitted in a multipart/form-data request.
|
||||||
|
* Requests that exceed this limit will be rejected. A value of less than 0 means
|
||||||
|
* no limit.
|
||||||
|
*/
|
||||||
|
private int maxPartCount = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum amount of request body to swallow.
|
* Maximum amount of request body to swallow.
|
||||||
*/
|
*/
|
||||||
|
@ -524,6 +538,22 @@ public class ServerProperties {
|
||||||
*/
|
*/
|
||||||
private UseApr useApr = UseApr.NEVER;
|
private UseApr useApr = UseApr.NEVER;
|
||||||
|
|
||||||
|
public DataSize getMaxPartHeaderSize() {
|
||||||
|
return this.maxPartHeaderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxPartHeaderSize(DataSize maxPartHeaderSize) {
|
||||||
|
this.maxPartHeaderSize = maxPartHeaderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPartCount() {
|
||||||
|
return this.maxPartCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxPartCount(int maxPartCount) {
|
||||||
|
this.maxPartCount = maxPartCount;
|
||||||
|
}
|
||||||
|
|
||||||
public Accesslog getAccesslog() {
|
public Accesslog getAccesslog() {
|
||||||
return this.accesslog;
|
return this.accesslog;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,10 @@ public class TomcatWebServerFactoryCustomizer
|
||||||
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
|
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
|
||||||
map.from(properties::getMaxParameterCount)
|
map.from(properties::getMaxParameterCount)
|
||||||
.to((maxParameterCount) -> customizeMaxParameterCount(factory, maxParameterCount));
|
.to((maxParameterCount) -> customizeMaxParameterCount(factory, maxParameterCount));
|
||||||
|
map.from(properties::getMaxPartHeaderSize)
|
||||||
|
.asInt(DataSize::toBytes)
|
||||||
|
.to((maxPartHeaderSize) -> customizeMaxPartHeaderSize(factory, maxPartHeaderSize));
|
||||||
|
map.from(properties::getMaxPartCount).to((maxPartCount) -> customizeMaxPartCount(factory, maxPartCount));
|
||||||
map.from(properties::getAccesslog)
|
map.from(properties::getAccesslog)
|
||||||
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
|
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
|
||||||
.to((enabled) -> customizeAccessLog(factory));
|
.to((enabled) -> customizeAccessLog(factory));
|
||||||
|
@ -298,6 +302,28 @@ public class TomcatWebServerFactoryCustomizer
|
||||||
factory.addConnectorCustomizers((connector) -> connector.setMaxParameterCount(maxParameterCount));
|
factory.addConnectorCustomizers((connector) -> connector.setMaxParameterCount(maxParameterCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void customizeMaxPartCount(ConfigurableTomcatWebServerFactory factory, int maxPartCount) {
|
||||||
|
factory.addConnectorCustomizers((connector) -> {
|
||||||
|
try {
|
||||||
|
connector.setMaxPartCount(maxPartCount);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodError ex) {
|
||||||
|
// Tomcat < 10.1.42
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void customizeMaxPartHeaderSize(ConfigurableTomcatWebServerFactory factory, int maxPartHeaderSize) {
|
||||||
|
factory.addConnectorCustomizers((connector) -> {
|
||||||
|
try {
|
||||||
|
connector.setMaxPartHeaderSize(maxPartHeaderSize);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodError ex) {
|
||||||
|
// Tomcat < 10.1.42
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void customizeAccessLog(ConfigurableTomcatWebServerFactory factory) {
|
private void customizeAccessLog(ConfigurableTomcatWebServerFactory factory) {
|
||||||
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
|
ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
|
||||||
AccessLogValve valve = new AccessLogValve();
|
AccessLogValve valve = new AccessLogValve();
|
||||||
|
|
|
@ -260,6 +260,18 @@ class ServerPropertiesTests {
|
||||||
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
|
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void customizeTomcatMaxPartCount() {
|
||||||
|
bind("server.tomcat.max-part-count", "5");
|
||||||
|
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void customizeTomcatMaxPartHeaderSize() {
|
||||||
|
bind("server.tomcat.max-part-header-size", "128");
|
||||||
|
assertThat(this.properties.getTomcat().getMaxPartHeaderSize()).isEqualTo(DataSize.ofBytes(128));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCustomizeJettyAcceptors() {
|
void testCustomizeJettyAcceptors() {
|
||||||
bind("server.jetty.threads.acceptors", "10");
|
bind("server.jetty.threads.acceptors", "10");
|
||||||
|
@ -405,6 +417,17 @@ class ServerPropertiesTests {
|
||||||
.isEqualTo(getDefaultConnector().getMaxPostSize());
|
.isEqualTo(getDefaultConnector().getMaxPostSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void tomcatMaxPartCountMatchesConnectorDefault() {
|
||||||
|
assertThat(this.properties.getTomcat().getMaxPartCount()).isEqualTo(getDefaultConnector().getMaxPartCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void tomcatMaxPartHeaderSizeMatchesConnectorDefault() {
|
||||||
|
assertThat(this.properties.getTomcat().getMaxPartHeaderSize().toBytes())
|
||||||
|
.isEqualTo(getDefaultConnector().getMaxPartHeaderSize());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void tomcatUriEncodingMatchesConnectorDefault() {
|
void tomcatUriEncodingMatchesConnectorDefault() {
|
||||||
assertThat(this.properties.getTomcat().getUriEncoding().name())
|
assertThat(this.properties.getTomcat().getUriEncoding().name())
|
||||||
|
|
|
@ -37,6 +37,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeader
|
||||||
import org.springframework.boot.context.properties.bind.Bindable;
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||||
|
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
|
||||||
|
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
||||||
import org.springframework.boot.web.server.WebServer;
|
import org.springframework.boot.web.server.WebServer;
|
||||||
|
@ -45,6 +47,7 @@ import org.springframework.test.context.support.TestPropertySourceUtils;
|
||||||
import org.springframework.util.unit.DataSize;
|
import org.springframework.util.unit.DataSize;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link TomcatWebServerFactoryCustomizer}
|
* Tests for {@link TomcatWebServerFactoryCustomizer}
|
||||||
|
@ -60,6 +63,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* @author Parviz Rozikov
|
* @author Parviz Rozikov
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
*/
|
*/
|
||||||
|
@DirtiesUrlFactories
|
||||||
class TomcatWebServerFactoryCustomizerTests {
|
class TomcatWebServerFactoryCustomizerTests {
|
||||||
|
|
||||||
private MockEnvironment environment;
|
private MockEnvironment environment;
|
||||||
|
@ -177,6 +181,37 @@ class TomcatWebServerFactoryCustomizerTests {
|
||||||
(server) -> assertThat(server.getTomcat().getConnector().getMaxPostSize()).isEqualTo(10000));
|
(server) -> assertThat(server.getTomcat().getConnector().getMaxPostSize()).isEqualTo(10000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultMaxPartCount() {
|
||||||
|
customizeAndRunServer(
|
||||||
|
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartCount()).isEqualTo(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void customMaxPartCount() {
|
||||||
|
bind("server.tomcat.max-part-count=5");
|
||||||
|
customizeAndRunServer((server) -> assertThat(server.getTomcat().getConnector().getMaxPartCount()).isEqualTo(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultMaxPartHeaderSize() {
|
||||||
|
customizeAndRunServer(
|
||||||
|
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartHeaderSize()).isEqualTo(512));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void customMaxPartHeaderSize() {
|
||||||
|
bind("server.tomcat.max-part-header-size=4KB");
|
||||||
|
customizeAndRunServer(
|
||||||
|
(server) -> assertThat(server.getTomcat().getConnector().getMaxPartHeaderSize()).isEqualTo(4096));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@ClassPathOverrides("org.apache.tomcat.embed:tomcat-embed-core:10.1.41")
|
||||||
|
void customizerIsCompatibleWithTomcatVersionsWithoutMaxPartCountAndMaxPartHeaderSize() {
|
||||||
|
assertThatNoException().isThrownBy(this::customizeAndRunServer);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void defaultMaxHttpRequestHeaderSize() {
|
void defaultMaxHttpRequestHeaderSize() {
|
||||||
customizeAndRunServer((server) -> assertThat(
|
customizeAndRunServer((server) -> assertThat(
|
||||||
|
@ -593,11 +628,17 @@ class TomcatWebServerFactoryCustomizerTests {
|
||||||
Bindable.ofInstance(this.serverProperties));
|
Bindable.ofInstance(this.serverProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void customizeAndRunServer() {
|
||||||
|
customizeAndRunServer(null);
|
||||||
|
}
|
||||||
|
|
||||||
private void customizeAndRunServer(Consumer<TomcatWebServer> consumer) {
|
private void customizeAndRunServer(Consumer<TomcatWebServer> consumer) {
|
||||||
TomcatWebServer server = customizeAndGetServer();
|
TomcatWebServer server = customizeAndGetServer();
|
||||||
server.start();
|
server.start();
|
||||||
try {
|
try {
|
||||||
consumer.accept(server);
|
if (consumer != null) {
|
||||||
|
consumer.accept(server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
server.stop();
|
server.stop();
|
||||||
|
|
Loading…
Reference in New Issue