Polish "Restore max-http-header-size default value support"

Fix Jetty and Undertow customizers to restore Spring Boot 2.0
behavior where a negative or zero `max-http-header-size` indicates
that the server default should be used.

Closes gh-14986
pull/14934/merge
Phillip Webb 6 years ago
parent 8b40ce14cb
commit 1451c0c069

@ -75,7 +75,7 @@ public class JettyWebServerFactoryCustomizer implements
propertyMapper.from(jettyProperties::getSelectors).whenNonNull()
.to(factory::setSelectors);
propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull()
.asInt(DataSize::toBytes)
.asInt(DataSize::toBytes).when(this::isPositive)
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
maxHttpHeaderSize));
propertyMapper.from(jettyProperties::getMaxHttpPostSize).asInt(DataSize::toBytes)

@ -86,7 +86,7 @@ public class UndertowWebServerFactoryCustomizer implements
propertyMapper.from(this::getOrDeduceUseForwardHeaders)
.to(factory::setUseForwardHeaders);
propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull()
.asInt(DataSize::toBytes)
.asInt(DataSize::toBytes).when(this::isPositive)
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
maxHttpHeaderSize));
propertyMapper.from(undertowProperties::getMaxHttpPostSize)

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.web.embedded;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
@ -38,6 +40,7 @@ import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@ -147,15 +150,40 @@ public class JettyWebServerFactoryCustomizerTests {
public void customizeMaxHttpHeaderSize() {
bind("server.max-http-header-size=2048");
JettyWebServer server = customizeAndGetServer();
for (Connector connector : server.getServer().getConnectors()) {
List<Integer> requestHeaderSizes = getRequestHeaderSizes(server);
assertThat(requestHeaderSizes).containsOnly(2048);
}
@Test
public void customMaxHttpHeaderSizeIgnoredIfNegative() {
bind("server.max-http-header-size=-1");
JettyWebServer server = customizeAndGetServer();
List<Integer> requestHeaderSizes = getRequestHeaderSizes(server);
assertThat(requestHeaderSizes).containsOnly(8192);
}
@Test
public void customMaxHttpHeaderSizeIgnoredIfZero() {
bind("server.max-http-header-size=0");
JettyWebServer server = customizeAndGetServer();
List<Integer> requestHeaderSizes = getRequestHeaderSizes(server);
assertThat(requestHeaderSizes).containsOnly(8192);
}
private List<Integer> getRequestHeaderSizes(JettyWebServer server) {
List<Integer> requestHeaderSizes = new ArrayList<>();
Connector[] connectors = (Connector[]) ReflectionTestUtils.getField(server,
"connectors");
for (Connector connector : connectors) {
connector.getConnectionFactories().stream()
.filter((factory) -> factory instanceof ConnectionFactory)
.forEach((cf) -> {
ConnectionFactory factory = (ConnectionFactory) cf;
HttpConfiguration configuration = factory.getHttpConfiguration();
assertThat(configuration.getRequestHeaderSize()).isEqualTo(2048);
requestHeaderSizes.add(configuration.getRequestHeaderSize());
});
}
return requestHeaderSizes;
}
private void bind(String... inlinedProperties) {

@ -17,18 +17,28 @@
package org.springframework.boot.autoconfigure.web.embedded;
import java.io.File;
import java.util.Arrays;
import io.undertow.Undertow;
import io.undertow.Undertow.Builder;
import io.undertow.UndertowOptions;
import org.junit.Before;
import org.junit.Test;
import org.xnio.OptionMap;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.web.embedded.undertow.ConfigurableUndertowWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@ -100,6 +110,54 @@ public class UndertowWebServerFactoryCustomizerTests {
verify(factory).setUseForwardHeaders(true);
}
@Test
public void customizeMaxHttpHeaderSize() {
bind("server.max-http-header-size=2048");
Builder builder = Undertow.builder();
ConfigurableUndertowWebServerFactory factory = mockFactory(builder);
this.customizer.customize(factory);
OptionMap map = ((OptionMap.Builder) ReflectionTestUtils.getField(builder,
"serverOptions")).getMap();
assertThat(map.get(UndertowOptions.MAX_HEADER_SIZE).intValue()).isEqualTo(2048);
}
@Test
public void customMaxHttpHeaderSizeIgnoredIfNegative() {
bind("server.max-http-header-size=-1");
Builder builder = Undertow.builder();
ConfigurableUndertowWebServerFactory factory = mockFactory(builder);
this.customizer.customize(factory);
OptionMap map = ((OptionMap.Builder) ReflectionTestUtils.getField(builder,
"serverOptions")).getMap();
assertThat(map.contains(UndertowOptions.MAX_HEADER_SIZE)).isFalse();
}
@Test
public void customMaxHttpHeaderSizeIgnoredIfZero() {
bind("server.max-http-header-size=0");
Builder builder = Undertow.builder();
ConfigurableUndertowWebServerFactory factory = mockFactory(builder);
this.customizer.customize(factory);
OptionMap map = ((OptionMap.Builder) ReflectionTestUtils.getField(builder,
"serverOptions")).getMap();
assertThat(map.contains(UndertowOptions.MAX_HEADER_SIZE)).isFalse();
}
private ConfigurableUndertowWebServerFactory mockFactory(Builder builder) {
ConfigurableUndertowWebServerFactory factory = mock(
ConfigurableUndertowWebServerFactory.class);
willAnswer((invocation) -> {
Object argument = invocation.getArgument(0);
Arrays.stream((argument instanceof UndertowBuilderCustomizer)
? new UndertowBuilderCustomizer[] {
(UndertowBuilderCustomizer) argument }
: (UndertowBuilderCustomizer[]) argument)
.forEach((customizer) -> customizer.customize(builder));
return null;
}).given(factory).addBuilderCustomizers(any());
return factory;
}
private void bind(String... inlinedProperties) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
inlinedProperties);

Loading…
Cancel
Save