Align defaults in ServerProperties with defaults at runtime
Closes gh-13821
This commit is contained in:
@@ -640,22 +640,22 @@ public class ServerProperties
|
||||
/**
|
||||
* Delay in seconds between the invocation of backgroundProcess methods.
|
||||
*/
|
||||
private int backgroundProcessorDelay = 30; // seconds
|
||||
private int backgroundProcessorDelay = 10; // seconds
|
||||
|
||||
/**
|
||||
* Maximum amount of worker threads.
|
||||
*/
|
||||
private int maxThreads = 0; // Number of threads in protocol handler
|
||||
private int maxThreads = 200; // Number of threads in protocol handler
|
||||
|
||||
/**
|
||||
* Minimum amount of worker threads.
|
||||
*/
|
||||
private int minSpareThreads = 0; // Minimum spare threads in protocol handler
|
||||
private int minSpareThreads = 10; // Minimum spare threads in protocol handler
|
||||
|
||||
/**
|
||||
* Maximum size in bytes of the HTTP post content.
|
||||
*/
|
||||
private int maxHttpPostSize = 0; // bytes
|
||||
private int maxHttpPostSize = 2097152; // bytes
|
||||
|
||||
/**
|
||||
* Maximum size in bytes of the HTTP message header.
|
||||
@@ -666,25 +666,25 @@ public class ServerProperties
|
||||
* Whether requests to the context root should be redirected by appending a / to
|
||||
* the path.
|
||||
*/
|
||||
private Boolean redirectContextRoot;
|
||||
private Boolean redirectContextRoot = true;
|
||||
|
||||
/**
|
||||
* Character encoding to use to decode the URI.
|
||||
*/
|
||||
private Charset uriEncoding;
|
||||
private Charset uriEncoding = Charset.forName("UTF-8");
|
||||
|
||||
/**
|
||||
* Maximum number of connections that the server will accept and process at any
|
||||
* given time. Once the limit has been reached, the operating system may still
|
||||
* accept connections based on the "acceptCount" property.
|
||||
*/
|
||||
private int maxConnections = 0;
|
||||
private int maxConnections = 10000;
|
||||
|
||||
/**
|
||||
* Maximum queue length for incoming connection requests when all possible request
|
||||
* processing threads are in use.
|
||||
*/
|
||||
private int acceptCount = 0;
|
||||
private int acceptCount = 100;
|
||||
|
||||
/**
|
||||
* Comma-separated list of additional patterns that match jars to ignore for TLD
|
||||
@@ -1091,7 +1091,7 @@ public class ServerProperties
|
||||
/**
|
||||
* Defer inclusion of the date stamp in the file name until rotate time.
|
||||
*/
|
||||
private boolean renameOnRotate;
|
||||
private boolean renameOnRotate = false;
|
||||
|
||||
/**
|
||||
* Date format to place in log file name.
|
||||
@@ -1102,7 +1102,7 @@ public class ServerProperties
|
||||
* Set request attributes for IP address, Hostname, protocol and port used for
|
||||
* the request.
|
||||
*/
|
||||
private boolean requestAttributesEnabled;
|
||||
private boolean requestAttributesEnabled = false;
|
||||
|
||||
/**
|
||||
* Buffer output such that it is only flushed periodically.
|
||||
@@ -1198,17 +1198,19 @@ public class ServerProperties
|
||||
/**
|
||||
* Maximum size in bytes of the HTTP post or put content.
|
||||
*/
|
||||
private int maxHttpPostSize = 0; // bytes
|
||||
private int maxHttpPostSize = 200000; // bytes
|
||||
|
||||
/**
|
||||
* Number of acceptor threads to use.
|
||||
* Number of acceptor threads to use. When the value is -1, the default, the
|
||||
* number of acceptors is derived from the operating environment.
|
||||
*/
|
||||
private Integer acceptors;
|
||||
private Integer acceptors = -1;
|
||||
|
||||
/**
|
||||
* Number of selector threads to use.
|
||||
* Number of selector threads to use. When the value is -1, the default, the
|
||||
* number of selectors is derived from the operating environment.
|
||||
*/
|
||||
private Integer selectors;
|
||||
private Integer selectors = -1;
|
||||
|
||||
public int getMaxHttpPostSize() {
|
||||
return this.maxHttpPostSize;
|
||||
@@ -1359,12 +1361,14 @@ public class ServerProperties
|
||||
public static class Undertow {
|
||||
|
||||
/**
|
||||
* Maximum size in bytes of the HTTP post content.
|
||||
* Maximum size in bytes of the HTTP post content. When the value is -1, the
|
||||
* default, the size is unlimited.
|
||||
*/
|
||||
private long maxHttpPostSize = 0; // bytes
|
||||
private long maxHttpPostSize = -1; // bytes
|
||||
|
||||
/**
|
||||
* Size of each buffer in bytes.
|
||||
* Size of each buffer in bytes. The default is derived from the maximum amount of
|
||||
* memory that is available to the JVM.
|
||||
*/
|
||||
private Integer bufferSize;
|
||||
|
||||
@@ -1375,17 +1379,19 @@ public class ServerProperties
|
||||
private Integer buffersPerRegion;
|
||||
|
||||
/**
|
||||
* Number of I/O threads to create for the worker.
|
||||
* Number of I/O threads to create for the worker. The default is derived from the
|
||||
* number of available processors.
|
||||
*/
|
||||
private Integer ioThreads;
|
||||
|
||||
/**
|
||||
* Number of worker threads.
|
||||
* Number of worker threads. The default is 8 times the number of I/O threads.
|
||||
*/
|
||||
private Integer workerThreads;
|
||||
|
||||
/**
|
||||
* Allocate buffers outside the Java heap.
|
||||
* Allocate buffers outside the Java heap. The default is derived from the maximum
|
||||
* amount of memory that is available to the JVM.
|
||||
*/
|
||||
private Boolean directBuffers;
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.springframework.boot.autoconfigure.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@@ -29,15 +31,23 @@ import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import io.undertow.UndertowOptions;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.core.StandardEngine;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.valves.AccessLogValve;
|
||||
import org.apache.catalina.valves.ErrorReportValve;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -49,12 +59,21 @@ import org.springframework.boot.bind.RelaxedDataBinder;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
@@ -256,13 +275,6 @@ public class ServerPropertiesTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectContextRootIsNotConfiguredByDefault() throws Exception {
|
||||
bindProperties(new HashMap<String, String>());
|
||||
ServerProperties.Tomcat tomcat = this.properties.getTomcat();
|
||||
assertThat(tomcat.getRedirectContextRoot()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectContextRootCanBeConfigured() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
@@ -274,6 +286,10 @@ public class ServerPropertiesTests {
|
||||
Context context = (Context) ((TomcatEmbeddedServletContainer) factory
|
||||
.getEmbeddedServletContainer()).getTomcat().getHost().findChildren()[0];
|
||||
assertThat(context.getMapperContextRootRedirectEnabled()).isTrue();
|
||||
this.properties.customize(factory);
|
||||
context = (Context) ((TomcatEmbeddedServletContainer) factory
|
||||
.getEmbeddedServletContainer()).getTomcat().getHost().findChildren()[0];
|
||||
assertThat(context.getMapperContextRootRedirectEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -517,7 +533,7 @@ public class ServerPropertiesTests {
|
||||
this.properties.customize(factory);
|
||||
EmbeddedServletContainer container = factory.getEmbeddedServletContainer();
|
||||
assertThat(((TomcatEmbeddedServletContainer) container).getTomcat().getEngine()
|
||||
.getBackgroundProcessorDelay()).isEqualTo(30);
|
||||
.getBackgroundProcessorDelay()).isEqualTo(10);
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@@ -819,6 +835,158 @@ public class ServerPropertiesTests {
|
||||
verify(container, never()).setAccessLogEnabled(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatAcceptCountMatchesProtocolDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getAcceptCount())
|
||||
.isEqualTo(getDefaultProtocol().getAcceptCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatMaxConnectionsMatchesProtocolDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getMaxConnections())
|
||||
.isEqualTo(getDefaultProtocol().getMaxConnections());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatMaxThreadsMatchesProtocolDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getMaxThreads())
|
||||
.isEqualTo(getDefaultProtocol().getMaxThreads());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatMinSpareThreadsMatchesProtocolDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getMinSpareThreads())
|
||||
.isEqualTo(getDefaultProtocol().getMinSpareThreads());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatMaxHttpPostSizeMatchesConnectorDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getMaxHttpPostSize())
|
||||
.isEqualTo(getDefaultConnector().getMaxPostSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatBackgroundProcessorDelayMatchesEngineDefault() {
|
||||
assertThat(this.properties.getTomcat().getBackgroundProcessorDelay())
|
||||
.isEqualTo(new StandardEngine().getBackgroundProcessorDelay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatUriEncodingMatchesConnectorDefault() throws Exception {
|
||||
assertThat(this.properties.getTomcat().getUriEncoding().name())
|
||||
.isEqualTo(getDefaultConnector().getURIEncoding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatRedirectContextRootMatchesDefault() {
|
||||
assertThat(this.properties.getTomcat().getRedirectContextRoot())
|
||||
.isEqualTo(new StandardContext().getMapperContextRootRedirectEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatAccessLogRenameOnRotateMatchesDefault() {
|
||||
assertThat(this.properties.getTomcat().getAccesslog().isRenameOnRotate())
|
||||
.isEqualTo(new AccessLogValve().isRenameOnRotate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatAccessLogRequestAttributesEnabledMatchesDefault() {
|
||||
assertThat(
|
||||
this.properties.getTomcat().getAccesslog().isRequestAttributesEnabled())
|
||||
.isEqualTo(new AccessLogValve().getRequestAttributesEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jettyMaxHttpPostSizeMatchesDefault() throws Exception {
|
||||
JettyEmbeddedServletContainerFactory jettyFactory = new JettyEmbeddedServletContainerFactory(
|
||||
0);
|
||||
JettyEmbeddedServletContainer jetty = (JettyEmbeddedServletContainer) jettyFactory
|
||||
.getEmbeddedServletContainer(new ServletContextInitializer() {
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext)
|
||||
throws ServletException {
|
||||
servletContext.addServlet("formPost", new HttpServlet() {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req,
|
||||
HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
req.getParameterMap();
|
||||
}
|
||||
|
||||
}).addMapping("/form");
|
||||
}
|
||||
|
||||
});
|
||||
jetty.start();
|
||||
org.eclipse.jetty.server.Connector connector = jetty.getServer()
|
||||
.getConnectors()[0];
|
||||
final AtomicReference<Throwable> failure = new AtomicReference<Throwable>();
|
||||
connector.addBean(new HttpChannel.Listener() {
|
||||
|
||||
@Override
|
||||
public void onDispatchFailure(Request request, Throwable ex) {
|
||||
failure.set(ex);
|
||||
}
|
||||
|
||||
});
|
||||
try {
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setErrorHandler(new ResponseErrorHandler() {
|
||||
|
||||
@Override
|
||||
public boolean hasError(ClientHttpResponse response) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<String, Object>();
|
||||
StringBuilder data = new StringBuilder();
|
||||
for (int i = 0; i < 250000; i++) {
|
||||
data.append("a");
|
||||
}
|
||||
body.add("data", data.toString());
|
||||
HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<MultiValueMap<String, Object>>(
|
||||
body, headers);
|
||||
template.postForEntity(
|
||||
URI.create("http://localhost:" + jetty.getPort() + "/form"), entity,
|
||||
Void.class);
|
||||
assertThat(failure.get()).isNotNull();
|
||||
String message = failure.get().getCause().getMessage();
|
||||
int defaultMaxPostSize = Integer
|
||||
.valueOf(message.substring(message.lastIndexOf(' ')).trim());
|
||||
assertThat(this.properties.getJetty().getMaxHttpPostSize())
|
||||
.isEqualTo(defaultMaxPostSize);
|
||||
}
|
||||
finally {
|
||||
jetty.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undertowMaxHttpPostSizeMatchesDefault() {
|
||||
assertThat(this.properties.getUndertow().getMaxHttpPostSize())
|
||||
.isEqualTo(UndertowOptions.DEFAULT_MAX_ENTITY_SIZE);
|
||||
}
|
||||
|
||||
private Connector getDefaultConnector() throws Exception {
|
||||
return new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
|
||||
}
|
||||
|
||||
private AbstractProtocol<?> getDefaultProtocol() throws Exception {
|
||||
return (AbstractProtocol<?>) Class
|
||||
.forName(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL)
|
||||
.newInstance();
|
||||
}
|
||||
|
||||
private void bindProperties(Map<String, String> map) {
|
||||
new RelaxedDataBinder(this.properties, "server")
|
||||
.bind(new MutablePropertyValues(map));
|
||||
|
||||
Reference in New Issue
Block a user