diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index af368d9a6f..c719cf0db2 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -851,7 +851,7 @@ public class ServerProperties valve.setPortHeader(getPortHeader()); valve.setProtocolHeaderHttpsValue(getProtocolHeaderHttpsValue()); // ... so it's safe to add this valve by default. - factory.addContextValves(valve); + factory.addEngineValves(valve); } } @@ -925,7 +925,7 @@ public class ServerProperties valve.setPrefix(this.accesslog.getPrefix()); valve.setSuffix(this.accesslog.getSuffix()); valve.setRenameOnRotate(this.accesslog.isRenameOnRotate()); - factory.addContextValves(valve); + factory.addEngineValves(valve); } private void customizeRedirectContextRoot( diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index af1a001446..0db14c7cf9 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -339,7 +339,7 @@ public class ServerPropertiesTests { bindProperties(map); TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); this.properties.customize(container); - assertThat(container.getValves()).isEmpty(); + assertThat(container.getEngineValves()).isEmpty(); } @Test @@ -368,8 +368,8 @@ public class ServerPropertiesTests { private void testRemoteIpValveConfigured() { TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); this.properties.customize(container); - assertThat(container.getValves()).hasSize(1); - Valve valve = container.getValves().iterator().next(); + assertThat(container.getEngineValves()).hasSize(1); + Valve valve = container.getEngineValves().iterator().next(); assertThat(valve).isInstanceOf(RemoteIpValve.class); RemoteIpValve remoteIpValve = (RemoteIpValve) valve; assertThat(remoteIpValve.getProtocolHeader()).isEqualTo("X-Forwarded-Proto"); @@ -398,8 +398,8 @@ public class ServerPropertiesTests { TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); this.properties.customize(container); - assertThat(container.getValves()).hasSize(1); - Valve valve = container.getValves().iterator().next(); + assertThat(container.getEngineValves()).hasSize(1); + Valve valve = container.getEngineValves().iterator().next(); assertThat(valve).isInstanceOf(RemoteIpValve.class); RemoteIpValve remoteIpValve = (RemoteIpValve) valve; assertThat(remoteIpValve.getProtocolHeader()).isEqualTo("x-my-protocol-header"); diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index 5aad85009b..30e4c0b192 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -34,6 +34,7 @@ import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import org.apache.catalina.Context; +import org.apache.catalina.Engine; import org.apache.catalina.Host; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; @@ -88,6 +89,7 @@ import org.springframework.util.StringUtils; * @author Stephane Nicoll * @author Andy Wilkinson * @author EddĂș MelĂ©ndez + * @author Christoffer Sawicki * @see #setPort(int) * @see #setContextLifecycleListeners(Collection) * @see TomcatEmbeddedServletContainer @@ -106,6 +108,8 @@ public class TomcatEmbeddedServletContainerFactory private File baseDirectory; + private List engineValves = new ArrayList(); + private List contextValves = new ArrayList(); private List contextLifecycleListeners = new ArrayList(); @@ -162,7 +166,7 @@ public class TomcatEmbeddedServletContainerFactory customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); - tomcat.getEngine().setBackgroundProcessorDelay(-1); + configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } @@ -170,6 +174,13 @@ public class TomcatEmbeddedServletContainerFactory return getTomcatEmbeddedServletContainer(tomcat); } + private void configureEngine(Engine engine) { + engine.setBackgroundProcessorDelay(-1); + for (Valve valve : this.engineValves) { + engine.getPipeline().addValve(valve); + } + } + protected void prepareContext(Host host, ServletContextInitializer[] initializers) { File docBase = getValidDocumentRoot(); docBase = (docBase != null ? docBase : createTempDir("tomcat-docbase")); @@ -527,9 +538,37 @@ public class TomcatEmbeddedServletContainerFactory this.protocol = protocol; } + /** + * Set {@link Valve}s that should be applied to the Tomcat {@link Engine}. Calling + * this method will replace any existing valves. + * @param engineValves the valves to set + */ + public void setEngineValves(Collection engineValves) { + Assert.notNull(engineValves, "Valves must not be null"); + this.engineValves = new ArrayList(engineValves); + } + + /** + * Returns a mutable collection of the {@link Valve}s that will be applied to the + * Tomcat {@link Engine}. + * @return the engineValves the valves that will be applied + */ + public Collection getEngineValves() { + return this.engineValves; + } + + /** + * Add {@link Valve}s that should be applied to the Tomcat {@link Engine}. + * @param engineValves the valves to add + */ + public void addEngineValves(Valve... engineValves) { + Assert.notNull(engineValves, "Valves must not be null"); + this.engineValves.addAll(Arrays.asList(engineValves)); + } + /** * Set {@link Valve}s that should be applied to the Tomcat {@link Context}. Calling - * this method will replace any existing listeners. + * this method will replace any existing valves. * @param contextValves the valves to set */ public void setContextValves(Collection contextValves) { @@ -541,8 +580,20 @@ public class TomcatEmbeddedServletContainerFactory * Returns a mutable collection of the {@link Valve}s that will be applied to the * Tomcat {@link Context}. * @return the contextValves the valves that will be applied + * @deprecated as of 1.4 in favor of {@link #getContextValves()} */ + @Deprecated public Collection getValves() { + return getContextValves(); + } + + /** + * Returns a mutable collection of the {@link Valve}s that will be applied to the + * Tomcat {@link Context}. + * @return the contextValves the valves that will be applied + * @see #getEngineValves() + */ + public Collection getContextValves() { return this.contextValves; }