Align defaults in ServerProperties with defaults at runtime

Closes gh-13821
This commit is contained in:
Andy Wilkinson 2018-07-20 15:46:33 +01:00
parent 7d54eda6f1
commit db903c2176
3 changed files with 218 additions and 43 deletions

View File

@ -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;

View File

@ -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));

View File

@ -156,9 +156,9 @@ content into your application; rather pick only the properties that you need.
server.error.include-stacktrace=never # When to include a "stacktrace" attribute.
server.error.path=/error # Path of the error controller.
server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error.
server.jetty.acceptors= # Number of acceptor threads to use.
server.jetty.max-http-post-size=0 # Maximum size in bytes of the HTTP post or put content.
server.jetty.selectors= # Number of selector threads to use.
server.jetty.acceptors=-1 # Number of acceptor threads to use. When the value is -1, the default, the number of acceptors is derived from the operating environment.
server.jetty.max-http-post-size=200000 # Maximum size in bytes of the HTTP post or put content.
server.jetty.selectors=-1 # Number of selector threads to use. When the value is -1, the default, the number of selectors is derived from the operating environment.
server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet # The class name of the JSP servlet.
server.jsp-servlet.init-parameters.*= # Init parameters used to configure the JSP servlet
server.jsp-servlet.registered=true # Whether or not the JSP servlet is registered
@ -192,7 +192,7 @@ content into your application; rather pick only the properties that you need.
server.ssl.trust-store-password= # Password used to access the trust store.
server.ssl.trust-store-provider= # Provider for the trust store.
server.ssl.trust-store-type= # Type of the trust store.
server.tomcat.accept-count= # Maximum queue length for incoming connection requests when all possible request processing threads are in use.
server.tomcat.accept-count=100 # Maximum queue length for incoming connection requests when all possible request processing threads are in use.
server.tomcat.accesslog.buffered=true # Buffer output such that it is only flushed periodically.
server.tomcat.accesslog.directory=logs # Directory in which log files are created. Can be relative to the tomcat base dir or absolute.
server.tomcat.accesslog.enabled=false # Enable access log.
@ -204,7 +204,7 @@ content into your application; rather pick only the properties that you need.
server.tomcat.accesslog.rotate=true # Enable access log rotation.
server.tomcat.accesslog.suffix=.log # Log file name suffix.
server.tomcat.additional-tld-skip-patterns= # Comma-separated list of additional patterns that match jars to ignore for TLD scanning.
server.tomcat.background-processor-delay=30 # Delay in seconds between the invocation of backgroundProcess methods.
server.tomcat.background-processor-delay=10 # Delay in seconds between the invocation of backgroundProcess methods.
server.tomcat.basedir= # Tomcat base directory. If not specified a temporary directory will be used.
server.tomcat.internal-proxies=10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\
192\\.168\\.\\d{1,3}\\.\\d{1,3}|\\
@ -213,14 +213,15 @@ content into your application; rather pick only the properties that you need.
172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\
172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\
172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3} # regular expression matching trusted IP addresses.
server.tomcat.max-connections= # Maximum number of connections that the server will accept and process at any given time.
server.tomcat.max-http-post-size=0 # Maximum size in bytes of the HTTP post content.
server.tomcat.max-threads=0 # Maximum amount of worker threads.
server.tomcat.min-spare-threads=0 # Minimum amount of worker threads.
server.tomcat.max-connections=10000 # Maximum number of connections that the server will accept and process 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=2097152 # Maximum size in bytes of the HTTP post content.
server.tomcat.max-threads=200 # Maximum amount of worker threads.
server.tomcat.min-spare-threads=10 # Minimum amount of worker threads.
server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value.
server.tomcat.protocol-header= # Header that holds the incoming protocol, usually named "X-Forwarded-Proto".
server.tomcat.protocol-header-https-value=https # Value of the protocol header that indicates that the incoming request uses SSL.
server.tomcat.redirect-context-root= # Whether requests to the context root should be redirected by appending a / to the path.
server.tomcat.redirect-context-root=true # Whether requests to the context root should be redirected by appending a / to the path.
server.tomcat.remote-ip-header= # Name of the http header from which the remote ip is extracted. For instance `X-FORWARDED-FOR`
server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI.
server.undertow.accesslog.dir= # Undertow access log directory.
@ -230,10 +231,10 @@ content into your application; rather pick only the properties that you need.
server.undertow.accesslog.rotate=true # Enable access log rotation.
server.undertow.accesslog.suffix=log # Log file name suffix.
server.undertow.buffer-size= # Size of each buffer in bytes.
server.undertow.direct-buffers= # Allocate buffers outside the Java heap.
server.undertow.io-threads= # Number of I/O threads to create for the worker.
server.undertow.max-http-post-size=0 # Maximum size in bytes of the HTTP post content.
server.undertow.worker-threads= # Number of worker threads.
server.undertow.direct-buffers= # Allocate buffers outside the Java heap. The default is derived from the maximum amount of memory that is available to the JVM.
server.undertow.io-threads= # Number of I/O threads to create for the worker. The default is derived from the number of available processors.
server.undertow.max-http-post-size=-1 # Maximum size in bytes of the HTTP post content. When the value is -1, the default, the size is unlimited.
server.undertow.worker-threads= # Number of worker threads. The default is 8 times the number of I/O threads.
# FREEMARKER ({sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration])
spring.freemarker.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name.