From e6568596b92de6b06b3d843ba06de9484513d33d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 4 Oct 2022 15:16:54 +0100 Subject: [PATCH] Make max header size config consistent across web servers Closes gh-29382 --- .../autoconfigure/web/ServerProperties.java | 19 +++++++++++++++---- .../JettyWebServerFactoryCustomizer.java | 16 ++++++++-------- .../NettyWebServerFactoryCustomizer.java | 2 +- .../TomcatWebServerFactoryCustomizer.java | 9 +++++---- .../UndertowWebServerFactoryCustomizer.java | 4 ++-- .../web/ServerPropertiesTests.java | 18 ++++++++++++++++++ ...TomcatWebServerFactoryCustomizerTests.java | 8 ++++---- 7 files changed, 53 insertions(+), 23 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index ca119825eff..4669f0f85f8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -98,9 +98,9 @@ public class ServerProperties { private String serverHeader; /** - * Maximum size of the HTTP message header. + * Maximum size of the HTTP request header. */ - private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8); + private DataSize maxHttpRequestHeaderSize = DataSize.ofKilobytes(8); /** * Type of shutdown that the server will support. @@ -152,12 +152,23 @@ public class ServerProperties { this.serverHeader = serverHeader; } + @Deprecated(since = "3.0.0", forRemoval = true) + @DeprecatedConfigurationProperty public DataSize getMaxHttpHeaderSize() { - return this.maxHttpHeaderSize; + return getMaxHttpRequestHeaderSize(); } + @Deprecated(since = "3.0.0", forRemoval = true) public void setMaxHttpHeaderSize(DataSize maxHttpHeaderSize) { - this.maxHttpHeaderSize = maxHttpHeaderSize; + setMaxHttpRequestHeaderSize(maxHttpHeaderSize); + } + + public DataSize getMaxHttpRequestHeaderSize() { + return this.maxHttpRequestHeaderSize; + } + + public void setMaxHttpRequestHeaderSize(DataSize maxHttpRequestHeaderSize) { + this.maxHttpRequestHeaderSize = maxHttpRequestHeaderSize; } public Shutdown getShutdown() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java index e6677bdcf01..709c908c105 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java @@ -82,9 +82,9 @@ public class JettyWebServerFactoryCustomizer PropertyMapper propertyMapper = PropertyMapper.get(); propertyMapper.from(threadProperties::getAcceptors).whenNonNull().to(factory::setAcceptors); propertyMapper.from(threadProperties::getSelectors).whenNonNull().to(factory::setSelectors); - propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull().asInt(DataSize::toBytes) - .when(this::isPositive).to((maxHttpHeaderSize) -> factory - .addServerCustomizers(new MaxHttpHeaderSizeCustomizer(maxHttpHeaderSize))); + propertyMapper.from(properties::getMaxHttpRequestHeaderSize).whenNonNull().asInt(DataSize::toBytes) + .when(this::isPositive).to((maxHttpRequestHeaderSize) -> factory + .addServerCustomizers(new MaxHttpRequestHeaderSizeCustomizer(maxHttpRequestHeaderSize))); propertyMapper.from(jettyProperties::getMaxHttpFormPostSize).asInt(DataSize::toBytes).when(this::isPositive) .to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize)); propertyMapper.from(jettyProperties::getConnectionIdleTimeout).whenNonNull() @@ -192,12 +192,12 @@ public class JettyWebServerFactoryCustomizer return CustomRequestLog.NCSA_FORMAT; } - private static class MaxHttpHeaderSizeCustomizer implements JettyServerCustomizer { + private static class MaxHttpRequestHeaderSizeCustomizer implements JettyServerCustomizer { - private final int maxHttpHeaderSize; + private final int maxRequestHeaderSize; - MaxHttpHeaderSizeCustomizer(int maxHttpHeaderSize) { - this.maxHttpHeaderSize = maxHttpHeaderSize; + MaxHttpRequestHeaderSizeCustomizer(int maxRequestHeaderSize) { + this.maxRequestHeaderSize = maxRequestHeaderSize; } @Override @@ -212,7 +212,7 @@ public class JettyWebServerFactoryCustomizer private void customize(ConnectionFactory factory) { if (factory instanceof HttpConfiguration.ConnectionFactory) { ((HttpConfiguration.ConnectionFactory) factory).getHttpConfiguration() - .setRequestHeaderSize(this.maxHttpHeaderSize); + .setRequestHeaderSize(this.maxRequestHeaderSize); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java index c943eb28110..53ed62ad97a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java @@ -83,7 +83,7 @@ public class NettyWebServerFactoryCustomizer private void customizeRequestDecoder(NettyReactiveWebServerFactory factory, PropertyMapper propertyMapper) { factory.addServerCustomizers((httpServer) -> httpServer.httpRequestDecoder((httpRequestDecoderSpec) -> { - propertyMapper.from(this.serverProperties.getMaxHttpHeaderSize()).whenNonNull() + propertyMapper.from(this.serverProperties.getMaxHttpRequestHeaderSize()).whenNonNull() .to((maxHttpRequestHeader) -> httpRequestDecoderSpec .maxHeaderSize((int) maxHttpRequestHeader.toBytes())); ServerProperties.Netty nettyProperties = this.serverProperties.getNetty(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java index 3551ce3cbb9..42052483681 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java @@ -92,9 +92,9 @@ public class TomcatWebServerFactoryCustomizer .to((maxThreads) -> customizeMaxThreads(factory, threadProperties.getMax())); propertyMapper.from(threadProperties::getMinSpare).when(this::isPositive) .to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads)); - propertyMapper.from(this.serverProperties.getMaxHttpHeaderSize()).whenNonNull().asInt(DataSize::toBytes) + propertyMapper.from(this.serverProperties.getMaxHttpRequestHeaderSize()).whenNonNull().asInt(DataSize::toBytes) .when(this::isPositive) - .to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize)); + .to((maxHttpRequestHeaderSize) -> customizeMaxHttpRequestHeaderSize(factory, maxHttpRequestHeaderSize)); propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull().asInt(DataSize::toBytes) .to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize)); propertyMapper.from(tomcatProperties::getMaxHttpFormPostSize).asInt(DataSize::toBytes) @@ -275,12 +275,13 @@ public class TomcatWebServerFactoryCustomizer } @SuppressWarnings("rawtypes") - private void customizeMaxHttpHeaderSize(ConfigurableTomcatWebServerFactory factory, int maxHttpHeaderSize) { + private void customizeMaxHttpRequestHeaderSize(ConfigurableTomcatWebServerFactory factory, + int maxHttpRequestHeaderSize) { factory.addConnectorCustomizers((connector) -> { ProtocolHandler handler = connector.getProtocolHandler(); if (handler instanceof AbstractHttp11Protocol) { AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler; - protocol.setMaxHttpHeaderSize(maxHttpHeaderSize); + protocol.setMaxHttpRequestHeaderSize(maxHttpRequestHeaderSize); } }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java index 8f291b1a220..4a07c8e1cf9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,7 +78,7 @@ public class UndertowWebServerFactoryCustomizer PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); ServerOptions options = new ServerOptions(factory); ServerProperties properties = this.serverProperties; - map.from(properties::getMaxHttpHeaderSize).asInt(DataSize::toBytes).when(this::isPositive) + map.from(properties::getMaxHttpRequestHeaderSize).asInt(DataSize::toBytes).when(this::isPositive) .to(options.option(UndertowOptions.MAX_HEADER_SIZE)); mapUndertowProperties(factory, options); mapAccessLogProperties(factory); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 92c998acc23..a36d22dcdf7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -204,15 +204,33 @@ class ServerPropertiesTests { } @Test + @SuppressWarnings("removal") + @Deprecated(since = "3.0.0", forRemoval = true) void testCustomizeHeaderSize() { bind("server.max-http-header-size", "1MB"); assertThat(this.properties.getMaxHttpHeaderSize()).isEqualTo(DataSize.ofMegabytes(1)); + assertThat(this.properties.getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofMegabytes(1)); } @Test + @SuppressWarnings("removal") + @Deprecated(since = "3.0.0", forRemoval = true) void testCustomizeHeaderSizeUseBytesByDefault() { bind("server.max-http-header-size", "1024"); assertThat(this.properties.getMaxHttpHeaderSize()).isEqualTo(DataSize.ofKilobytes(1)); + assertThat(this.properties.getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofKilobytes(1)); + } + + @Test + void testCustomizeMaxHttpRequestHeaderSize() { + bind("server.max-http-request-header-size", "1MB"); + assertThat(this.properties.getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofMegabytes(1)); + } + + @Test + void testCustomizeMaxHttpRequestHeaderSizeUseBytesByDefault() { + bind("server.max-http-request-header-size", "1024"); + assertThat(this.properties.getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofKilobytes(1)); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java index 826e96303dd..9a907d61823 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java @@ -179,7 +179,7 @@ class TomcatWebServerFactoryCustomizerTests { bind("server.max-http-header-size=1KB"); customizeAndRunServer((server) -> assertThat( ((AbstractHttp11Protocol) server.getTomcat().getConnector().getProtocolHandler()) - .getMaxHttpHeaderSize()).isEqualTo(DataSize.ofKilobytes(1).toBytes())); + .getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofKilobytes(1).toBytes())); } @Test @@ -189,7 +189,7 @@ class TomcatWebServerFactoryCustomizerTests { AbstractHttp11Protocol protocolHandler = (AbstractHttp11Protocol) server.getTomcat().getConnector() .getProtocolHandler(); long expectedSize = DataSize.ofKilobytes(1).toBytes(); - assertThat(protocolHandler.getMaxHttpHeaderSize()).isEqualTo(expectedSize); + assertThat(protocolHandler.getMaxHttpRequestHeaderSize()).isEqualTo(expectedSize); assertThat(((Http2Protocol) protocolHandler.getUpgradeProtocol("h2c")).getMaxHeaderSize()) .isEqualTo(expectedSize); }); @@ -200,7 +200,7 @@ class TomcatWebServerFactoryCustomizerTests { bind("server.max-http-header-size=-1"); customizeAndRunServer((server) -> assertThat( ((AbstractHttp11Protocol) server.getTomcat().getConnector().getProtocolHandler()) - .getMaxHttpHeaderSize()).isEqualTo(DataSize.ofKilobytes(8).toBytes())); + .getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofKilobytes(8).toBytes())); } @Test @@ -208,7 +208,7 @@ class TomcatWebServerFactoryCustomizerTests { bind("server.max-http-header-size=0"); customizeAndRunServer((server) -> assertThat( ((AbstractHttp11Protocol) server.getTomcat().getConnector().getProtocolHandler()) - .getMaxHttpHeaderSize()).isEqualTo(DataSize.ofKilobytes(8).toBytes())); + .getMaxHttpRequestHeaderSize()).isEqualTo(DataSize.ofKilobytes(8).toBytes())); } @Test