Skip to content

Commit 9496e87

Browse files
committed
Merge pull request #14234 from qct:max-header
* pr/14234: Polish "Align max HTTP header size configuration" Align max HTTP header size configuration
2 parents 7de9653 + 8771b34 commit 9496e87

File tree

9 files changed

+92
-20
lines changed

9 files changed

+92
-20
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.TimeZone;
3030

3131
import org.springframework.boot.context.properties.ConfigurationProperties;
32+
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
3233
import org.springframework.boot.context.properties.NestedConfigurationProperty;
3334
import org.springframework.boot.convert.DurationUnit;
3435
import org.springframework.boot.web.server.Compression;
@@ -53,6 +54,7 @@
5354
* @author Aurélien Leboulanger
5455
* @author Brian Clozel
5556
* @author Olivier Lamy
57+
* @author Chentao Qu
5658
*/
5759
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
5860
public class ServerProperties {
@@ -81,9 +83,9 @@ public class ServerProperties {
8183
private String serverHeader;
8284

8385
/**
84-
* Maximum size, in bytes, of the HTTP message header.
86+
* Maximum size of the HTTP message header.
8587
*/
86-
private int maxHttpHeaderSize = 0; // bytes
88+
private DataSize maxHttpHeaderSize = DataSize.ofKiloBytes(8);
8789

8890
/**
8991
* Time that connectors wait for another HTTP request before closing the connection.
@@ -141,11 +143,11 @@ public void setServerHeader(String serverHeader) {
141143
this.serverHeader = serverHeader;
142144
}
143145

144-
public int getMaxHttpHeaderSize() {
146+
public DataSize getMaxHttpHeaderSize() {
145147
return this.maxHttpHeaderSize;
146148
}
147149

148-
public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {
150+
public void setMaxHttpHeaderSize(DataSize maxHttpHeaderSize) {
149151
this.maxHttpHeaderSize = maxHttpHeaderSize;
150152
}
151153

@@ -493,10 +495,17 @@ public void setMaxConnections(int maxConnections) {
493495
this.maxConnections = maxConnections;
494496
}
495497

498+
@Deprecated
499+
@DeprecatedConfigurationProperty(replacement = "server.max-http-header-size")
496500
public int getMaxHttpHeaderSize() {
497501
return this.maxHttpHeaderSize;
498502
}
499503

504+
@Deprecated
505+
public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {
506+
this.maxHttpHeaderSize = maxHttpHeaderSize;
507+
}
508+
500509
public DataSize getMaxSwallowSize() {
501510
return this.maxSwallowSize;
502511
}
@@ -505,10 +514,6 @@ public void setMaxSwallowSize(DataSize maxSwallowSize) {
505514
this.maxSwallowSize = maxSwallowSize;
506515
}
507516

508-
public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {
509-
this.maxHttpHeaderSize = maxHttpHeaderSize;
510-
}
511-
512517
public int getAcceptCount() {
513518
return this.acceptCount;
514519
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
3737
import org.springframework.core.Ordered;
3838
import org.springframework.core.env.Environment;
39+
import org.springframework.util.unit.DataSize;
3940

4041
/**
4142
* Customization for Jetty-specific features common for both Servlet and Reactive servers.
@@ -73,7 +74,8 @@ public void customize(ConfigurableJettyWebServerFactory factory) {
7374
.to(factory::setAcceptors);
7475
propertyMapper.from(jettyProperties::getSelectors).whenNonNull()
7576
.to(factory::setSelectors);
76-
propertyMapper.from(properties::getMaxHttpHeaderSize).when(this::isPositive)
77+
propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull()
78+
.asInt(DataSize::toBytes)
7779
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
7880
maxHttpHeaderSize));
7981
propertyMapper.from(jettyProperties::getMaxHttpPostSize).when(this::isPositive)
@@ -133,7 +135,6 @@ public void customize(Server server) {
133135
private void customize(HttpConfiguration.ConnectionFactory factory) {
134136
HttpConfiguration configuration = factory.getHttpConfiguration();
135137
configuration.setRequestHeaderSize(maxHttpHeaderSize);
136-
configuration.setResponseHeaderSize(maxHttpHeaderSize);
137138
}
138139

139140
});

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818

1919
import org.springframework.boot.autoconfigure.web.ServerProperties;
2020
import org.springframework.boot.cloud.CloudPlatform;
21+
import org.springframework.boot.context.properties.PropertyMapper;
2122
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
23+
import org.springframework.boot.web.embedded.netty.NettyServerCustomizer;
2224
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
2325
import org.springframework.core.Ordered;
2426
import org.springframework.core.env.Environment;
27+
import org.springframework.util.unit.DataSize;
2528

2629
/**
2730
* Customization for Netty-specific features.
2831
*
2932
* @author Brian Clozel
33+
* @author Chentao Qu
3034
* @since 2.1.0
3135
*/
3236
public class NettyWebServerFactoryCustomizer
@@ -51,6 +55,11 @@ public int getOrder() {
5155
public void customize(NettyReactiveWebServerFactory factory) {
5256
factory.setUseForwardHeaders(
5357
getOrDeduceUseForwardHeaders(this.serverProperties, this.environment));
58+
PropertyMapper propertyMapper = PropertyMapper.get();
59+
propertyMapper.from(this.serverProperties::getMaxHttpHeaderSize).whenNonNull()
60+
.asInt(DataSize::toBytes)
61+
.to((maxHttpRequestHeaderSize) -> customizeMaxHttpHeaderSize(factory,
62+
maxHttpRequestHeaderSize));
5463
}
5564

5665
private boolean getOrDeduceUseForwardHeaders(ServerProperties serverProperties,
@@ -62,4 +71,11 @@ private boolean getOrDeduceUseForwardHeaders(ServerProperties serverProperties,
6271
return platform != null && platform.isUsingForwardHeaders();
6372
}
6473

74+
private void customizeMaxHttpHeaderSize(NettyReactiveWebServerFactory factory,
75+
Integer maxHttpHeaderSize) {
76+
factory.addServerCustomizers((NettyServerCustomizer) (httpServer) -> httpServer
77+
.httpRequestDecoder((httpRequestDecoderSpec) -> httpRequestDecoderSpec
78+
.maxHeaderSize(maxHttpHeaderSize)));
79+
}
80+
6581
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* @author Stephane Nicoll
4949
* @author Phillip Webb
5050
* @author Artsiom Yudovin
51+
* @author Chentao Qu
5152
* @since 2.0.0
5253
*/
5354
public class TomcatWebServerFactoryCustomizer implements
@@ -84,7 +85,8 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
8485
tomcatProperties.getMaxThreads()));
8586
propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
8687
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
87-
propertyMapper.from(this::determineMaxHttpHeaderSize).when(this::isPositive)
88+
propertyMapper.from(this::determineMaxHttpHeaderSize).whenNonNull()
89+
.asInt(DataSize::toBytes)
8890
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
8991
maxHttpHeaderSize));
9092
propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull()
@@ -114,10 +116,12 @@ private boolean isPositive(int value) {
114116
return value > 0;
115117
}
116118

117-
private int determineMaxHttpHeaderSize() {
118-
return (this.serverProperties.getMaxHttpHeaderSize() > 0)
119-
? this.serverProperties.getMaxHttpHeaderSize()
120-
: this.serverProperties.getTomcat().getMaxHttpHeaderSize();
119+
@SuppressWarnings("deprecation")
120+
private DataSize determineMaxHttpHeaderSize() {
121+
return isPositive(this.serverProperties.getTomcat().getMaxHttpHeaderSize())
122+
? DataSize
123+
.ofBytes(this.serverProperties.getTomcat().getMaxHttpHeaderSize())
124+
: this.serverProperties.getMaxHttpHeaderSize();
121125
}
122126

123127
private void customizeAcceptCount(ConfigurableTomcatWebServerFactory factory,

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
2828
import org.springframework.core.Ordered;
2929
import org.springframework.core.env.Environment;
30+
import org.springframework.util.unit.DataSize;
3031

3132
/**
3233
* Customization for Undertow-specific features common for both Servlet and Reactive
@@ -83,7 +84,8 @@ public void customize(ConfigurableUndertowWebServerFactory factory) {
8384
.to(factory::setAccessLogRotate);
8485
propertyMapper.from(this::getOrDeduceUseForwardHeaders)
8586
.to(factory::setUseForwardHeaders);
86-
propertyMapper.from(properties::getMaxHttpHeaderSize).when(this::isPositive)
87+
propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull()
88+
.asInt(DataSize::toBytes)
8789
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
8890
maxHttpHeaderSize));
8991
propertyMapper.from(undertowProperties::getMaxHttpPostSize).when(this::isPositive)

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.boot.context.properties.bind.Binder;
3030
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
3131
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
32+
import org.springframework.util.unit.DataSize;
3233

3334
import static org.assertj.core.api.Assertions.assertThat;
3435

@@ -135,8 +136,16 @@ public void testCustomizeUriEncoding() {
135136

136137
@Test
137138
public void testCustomizeHeaderSize() {
138-
bind("server.max-http-header-size", "9999");
139-
assertThat(this.properties.getMaxHttpHeaderSize()).isEqualTo(9999);
139+
bind("server.max-http-header-size", "1MB");
140+
assertThat(this.properties.getMaxHttpHeaderSize())
141+
.isEqualTo(DataSize.ofMegaBytes(1));
142+
}
143+
144+
@Test
145+
public void testCustomizeHeaderSizeUseBytesByDefault() {
146+
bind("server.max-http-header-size", "1024");
147+
assertThat(this.properties.getMaxHttpHeaderSize())
148+
.isEqualTo(DataSize.ofKiloBytes(1));
140149
}
141150

142151
@Test

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import java.util.Locale;
2222
import java.util.TimeZone;
2323

24+
import org.eclipse.jetty.server.Connector;
25+
import org.eclipse.jetty.server.HttpConfiguration;
26+
import org.eclipse.jetty.server.HttpConfiguration.ConnectionFactory;
2427
import org.eclipse.jetty.server.NCSARequestLog;
2528
import org.eclipse.jetty.server.RequestLog;
2629
import org.junit.Before;
@@ -140,6 +143,21 @@ public void setUseForwardHeaders() {
140143
verify(factory).setUseForwardHeaders(true);
141144
}
142145

146+
@Test
147+
public void customizeMaxHttpHeaderSize() {
148+
bind("server.max-http-header-size=2048");
149+
JettyWebServer server = customizeAndGetServer();
150+
for (Connector connector : server.getServer().getConnectors()) {
151+
connector.getConnectionFactories().stream()
152+
.filter((factory) -> factory instanceof ConnectionFactory)
153+
.forEach((cf) -> {
154+
ConnectionFactory factory = (ConnectionFactory) cf;
155+
HttpConfiguration configuration = factory.getHttpConfiguration();
156+
assertThat(configuration.getRequestHeaderSize()).isEqualTo(2048);
157+
});
158+
}
159+
}
160+
143161
private void bind(String... inlinedProperties) {
144162
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
145163
inlinedProperties);

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ public void customMaxHttpPostSize() {
121121
.isEqualTo(10000));
122122
}
123123

124+
@Test
125+
public void customMaxHttpHeaderSize() {
126+
bind("server.max-http-header-size=1KB");
127+
customizeAndRunServer((server) -> assertThat(((AbstractHttp11Protocol<?>) server
128+
.getTomcat().getConnector().getProtocolHandler()).getMaxHttpHeaderSize())
129+
.isEqualTo(DataSize.ofKiloBytes(1).toBytes()));
130+
}
131+
132+
@Test
133+
@Deprecated
134+
public void customMaxHttpHeaderSizeWithDeprecatedProperty() {
135+
bind("server.max-http-header-size=4KB",
136+
"server.tomcat.max-http-header-size=1024");
137+
customizeAndRunServer((server) -> assertThat(((AbstractHttp11Protocol<?>) server
138+
.getTomcat().getConnector().getProtocolHandler()).getMaxHttpHeaderSize())
139+
.isEqualTo(DataSize.ofKiloBytes(1).toBytes()));
140+
}
141+
124142
@Test
125143
public void customMaxSwallowSize() {
126144
bind("server.tomcat.max-swallow-size=10MB");

spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ content into your application. Rather, pick only the properties that you need.
207207
server.jetty.accesslog.time-zone=GMT # Timezone of the request log.
208208
server.jetty.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post or put content.
209209
server.jetty.selectors= # Number of selector threads to use.
210-
server.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header.
210+
server.max-http-header-size=8KB # Maximum size of the HTTP message header.
211211
server.port=8080 # Server HTTP port.
212212
server.server-header= # Value to use for the Server response header (if empty, no header is sent).
213213
server.use-forward-headers= # Whether X-Forwarded-* headers should be applied to the HttpRequest.
@@ -265,7 +265,6 @@ content into your application. Rather, pick only the properties that you need.
265265
172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\
266266
172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3} # Regular expression matching trusted IP addresses.
267267
server.tomcat.max-connections=0 # Maximum number of connections that the server accepts and processes at any given time.
268-
server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header.
269268
server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content.
270269
server.tomcat.max-swallow-size=2MB # Maximum amount of request body to swallow.
271270
server.tomcat.max-threads=0 # Maximum number of worker threads.

0 commit comments

Comments
 (0)