From 780517ca4d8002bb7dcee3e12746c107d4516b19 Mon Sep 17 00:00:00 2001 From: qingbozhang Date: Wed, 25 Sep 2024 23:04:55 +0800 Subject: [PATCH 1/2] feat: add `maxFormKeys` for jetty --- .../boot/autoconfigure/web/ServerProperties.java | 13 +++++++++++++ .../embedded/JettyWebServerFactoryCustomizer.java | 11 ++++++++--- .../autoconfigure/web/ServerPropertiesTests.java | 9 +++++++++ 3 files changed, 30 insertions(+), 3 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 0142e34a6916..83b5156ac9b0 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 @@ -1148,6 +1148,11 @@ public static class Jetty { */ private DataSize maxHttpFormPostSize = DataSize.ofBytes(200000); + /** + * Maximum size of the form keys. + */ + private int maxFormKeys = 1000; + /** * Time that the connection can be idle before it is closed. */ @@ -1180,6 +1185,14 @@ public void setMaxHttpFormPostSize(DataSize maxHttpFormPostSize) { this.maxHttpFormPostSize = maxHttpFormPostSize; } + public int getMaxFormKeys() { + return maxFormKeys; + } + + public void setMaxFormKeys(int maxFormKeys) { + this.maxFormKeys = maxFormKeys; + } + public Duration getConnectionIdleTimeout() { return this.connectionIdleTimeout; } 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 c12333dc9cfc..8947eff2b412 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 @@ -19,6 +19,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import org.eclipse.jetty.ee10.servlet.ServletContextHandler; import org.eclipse.jetty.server.AbstractConnector; @@ -93,7 +94,11 @@ public void customize(ConfigurableJettyWebServerFactory factory) { map.from(properties::getMaxHttpFormPostSize) .asInt(DataSize::toBytes) .when(this::isPositive) - .to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize)); + .to((maxHttpFormPostSize) -> customizeServletContextHandler(factory, contextHandler -> contextHandler.setMaxFormContentSize(maxHttpFormPostSize))); + map.from(properties::getMaxFormKeys) + .when(this::isPositive) + .to((maxFormKeys) -> customizeServletContextHandler(factory, contextHandler -> contextHandler.setMaxFormKeys(maxFormKeys))); + map.from(properties::getConnectionIdleTimeout).to((idleTimeout) -> customizeIdleTimeout(factory, idleTimeout)); map.from(properties::getAccesslog) .when(ServerProperties.Jetty.Accesslog::isEnabled) @@ -122,7 +127,7 @@ private void customizeIdleTimeout(ConfigurableJettyWebServerFactory factory, Dur }); } - private void customizeMaxHttpFormPostSize(ConfigurableJettyWebServerFactory factory, int maxHttpFormPostSize) { + private void customizeServletContextHandler(ConfigurableJettyWebServerFactory factory, Consumer customFunc) { factory.addServerCustomizers(new JettyServerCustomizer() { @Override @@ -138,7 +143,7 @@ private void setHandlerMaxHttpFormPostSize(List handlers) { private void setHandlerMaxHttpFormPostSize(Handler handler) { if (handler instanceof ServletContextHandler contextHandler) { - contextHandler.setMaxFormContentSize(maxHttpFormPostSize); + customFunc.accept(contextHandler); } else if (handler instanceof Handler.Wrapper wrapper) { setHandlerMaxHttpFormPostSize(wrapper.getHandler()); 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 0bfeacf8ec67..01baba2092d6 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 @@ -465,6 +465,15 @@ void jettyMaxHttpFormPostSizeMatchesDefault() { .isEqualTo(((ServletContextHandler) server.getHandler()).getMaxFormContentSize()); } + @Test + void jettyMaxFormKeysMatchesDefault() { + JettyServletWebServerFactory jettyFactory = new JettyServletWebServerFactory(0); + JettyWebServer jetty = (JettyWebServer) jettyFactory.getWebServer(); + Server server = jetty.getServer(); + assertThat(this.properties.getJetty().getMaxFormKeys()) + .isEqualTo(((ServletContextHandler) server.getHandler()).getMaxFormKeys()); + } + @Test void undertowMaxHttpPostSizeMatchesDefault() { assertThat(this.properties.getUndertow().getMaxHttpPostSize().toBytes()) From d47e4d980c2fc17d76c5805650d0566a72c62d65 Mon Sep 17 00:00:00 2001 From: qingbozhang Date: Wed, 2 Oct 2024 23:55:51 +0800 Subject: [PATCH 2/2] Fix comment & method name and add test case --- .../autoconfigure/web/ServerProperties.java | 4 ++-- .../JettyWebServerFactoryCustomizer.java | 12 ++++++------ .../JettyWebServerFactoryCustomizerTests.java | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 8 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 83b5156ac9b0..73f684f62ed1 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 @@ -1149,7 +1149,7 @@ public static class Jetty { private DataSize maxHttpFormPostSize = DataSize.ofBytes(200000); /** - * Maximum size of the form keys. + * Maximum number of form keys. */ private int maxFormKeys = 1000; @@ -1186,7 +1186,7 @@ public void setMaxHttpFormPostSize(DataSize maxHttpFormPostSize) { } public int getMaxFormKeys() { - return maxFormKeys; + return this.maxFormKeys; } public void setMaxFormKeys(int maxFormKeys) { 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 8947eff2b412..59387856bb8d 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 @@ -132,24 +132,24 @@ private void customizeServletContextHandler(ConfigurableJettyWebServerFactory fa @Override public void customize(Server server) { - setHandlerMaxHttpFormPostSize(server.getHandlers()); + acceptCustomizeServletContextHandler(server.getHandlers()); } - private void setHandlerMaxHttpFormPostSize(List handlers) { + private void acceptCustomizeServletContextHandler(List handlers) { for (Handler handler : handlers) { - setHandlerMaxHttpFormPostSize(handler); + acceptCustomizeServletContextHandler(handler); } } - private void setHandlerMaxHttpFormPostSize(Handler handler) { + private void acceptCustomizeServletContextHandler(Handler handler) { if (handler instanceof ServletContextHandler contextHandler) { customFunc.accept(contextHandler); } else if (handler instanceof Handler.Wrapper wrapper) { - setHandlerMaxHttpFormPostSize(wrapper.getHandler()); + acceptCustomizeServletContextHandler(wrapper.getHandler()); } else if (handler instanceof Handler.Collection collection) { - setHandlerMaxHttpFormPostSize(collection.getHandlers()); + acceptCustomizeServletContextHandler(collection.getHandlers()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java index eef94bb88a20..70a2b2c3e9ef 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java @@ -26,6 +26,7 @@ import java.util.concurrent.SynchronousQueue; import java.util.function.Function; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.CustomRequestLog; @@ -324,6 +325,23 @@ void customIdleTimeout() { assertThat(timeouts).containsOnly(60000L); } + @Test + void customMaxFormKeys() { + bind("server.jetty.max-form-keys=2048"); + JettyWebServer server = customizeAndGetServer(); + List maxFormKeys = getMaxFormKeys(server); + assertThat(maxFormKeys).containsOnly(2048); + } + + private List getMaxFormKeys(JettyWebServer server) { + server.start(); + server.stop(); + return server.getServer().getHandlers().stream() + .filter(handler -> handler instanceof ServletContextHandler) + .map(handler -> ((ServletContextHandler) handler).getMaxFormKeys()) + .toList(); + } + private List connectorsIdleTimeouts(JettyWebServer server) { // Start (and directly stop) server to have connectors available server.start();