Commit 2eaa64f8 authored by Pascal Zwick's avatar Pascal Zwick Committed by Madhura Bhave

Simplify the configuration of the ProtocolHandler

This commit introduces a new callback interface that can
be used to customize the ProtocolHandler on a Tomcat Connector.

See gh-16342
parent 6bb53119
...@@ -28,6 +28,7 @@ import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory ...@@ -28,6 +28,7 @@ import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory; import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
...@@ -76,12 +77,16 @@ abstract class ReactiveWebServerFactoryConfiguration { ...@@ -76,12 +77,16 @@ abstract class ReactiveWebServerFactoryConfiguration {
@Bean @Bean
public TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory( public TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers, ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers) { ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer> protocolHandlerCustomizers) {
TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory(); TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory();
factory.getTomcatConnectorCustomizers().addAll( factory.getTomcatConnectorCustomizers().addAll(
connectorCustomizers.orderedStream().collect(Collectors.toList())); connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers().addAll( factory.getTomcatContextCustomizers().addAll(
contextCustomizers.orderedStream().collect(Collectors.toList())); contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream()
.collect(Collectors.toList()));
return factory; return factory;
} }
......
...@@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy; ...@@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
...@@ -66,12 +67,16 @@ class ServletWebServerFactoryConfiguration { ...@@ -66,12 +67,16 @@ class ServletWebServerFactoryConfiguration {
@Bean @Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory( public TomcatServletWebServerFactory tomcatServletWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers, ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers) { ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer> protocolHandlerCustomizers) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.getTomcatConnectorCustomizers().addAll( factory.getTomcatConnectorCustomizers().addAll(
connectorCustomizers.orderedStream().collect(Collectors.toList())); connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers().addAll( factory.getTomcatContextCustomizers().addAll(
contextCustomizers.orderedStream().collect(Collectors.toList())); contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream()
.collect(Collectors.toList()));
return factory; return factory;
} }
......
...@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; ...@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
...@@ -131,6 +132,21 @@ public class ReactiveWebServerFactoryAutoConfigurationTests { ...@@ -131,6 +132,21 @@ public class ReactiveWebServerFactoryAutoConfigurationTests {
}); });
} }
@Test
public void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() {
ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner(
AnnotationConfigReactiveWebApplicationContext::new)
.withConfiguration(AutoConfigurations
.of(ReactiveWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(
TomcatProtocolHandlerCustomizerConfiguration.class);
runner.run((context) -> {
TomcatReactiveWebServerFactory factory = context
.getBean(TomcatReactiveWebServerFactory.class);
assertThat(factory.getTomcatProtocolHandlerCustomizers()).hasSize(1);
});
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
protected static class HttpHandlerConfiguration { protected static class HttpHandlerConfiguration {
...@@ -193,4 +209,15 @@ public class ReactiveWebServerFactoryAutoConfigurationTests { ...@@ -193,4 +209,15 @@ public class ReactiveWebServerFactoryAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class TomcatProtocolHandlerCustomizerConfiguration {
@Bean
public TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() {
return (protocolHandler) -> {
};
}
}
} }
...@@ -32,6 +32,7 @@ import org.springframework.boot.test.context.runner.ContextConsumer; ...@@ -32,6 +32,7 @@ import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean;
...@@ -170,6 +171,21 @@ public class ServletWebServerFactoryAutoConfigurationTests { ...@@ -170,6 +171,21 @@ public class ServletWebServerFactoryAutoConfigurationTests {
}); });
} }
@Test
public void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations
.of(ServletWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(
TomcatProtocolHandlerCustomizerConfiguration.class);
runner.run((context) -> {
TomcatServletWebServerFactory factory = context
.getBean(TomcatServletWebServerFactory.class);
assertThat(factory.getTomcatProtocolHandlerCustomizers()).hasSize(1);
});
}
private ContextConsumer<AssertableWebApplicationContext> verifyContext() { private ContextConsumer<AssertableWebApplicationContext> verifyContext() {
return this::verifyContext; return this::verifyContext;
} }
...@@ -308,4 +324,15 @@ public class ServletWebServerFactoryAutoConfigurationTests { ...@@ -308,4 +324,15 @@ public class ServletWebServerFactoryAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class TomcatProtocolHandlerCustomizerConfiguration {
@Bean
public TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() {
return (protocolHandler) -> {
};
}
}
} }
...@@ -68,6 +68,14 @@ public interface ConfigurableTomcatWebServerFactory extends ConfigurableWebServe ...@@ -68,6 +68,14 @@ public interface ConfigurableTomcatWebServerFactory extends ConfigurableWebServe
*/ */
void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers); void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers);
/**
* Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat
* {@link Connector}.
* @param tomcatProtocolHandlerCustomizers the customizers to add
*/
void addProtocolHandlerCustomizers(
TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers);
/** /**
* Set the character encoding to use for URL decoding. If not specified 'UTF-8' will * Set the character encoding to use for URL decoding. If not specified 'UTF-8' will
* be used. * be used.
......
/*
* Copyright 2012-2019 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.web.embedded.tomcat;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.ProtocolHandler;
/**
* Callback interface that can be used to customize the {@link ProtocolHandler} on the
* {@link Connector}.
*
* @param <T> specified type for customization based on {@link ProtocolHandler}
* @author Pascal Zwick
* @see ConfigurableTomcatWebServerFactory
* @since 2.2.0
*/
@FunctionalInterface
public interface TomcatProtocolHandlerCustomizer<T extends ProtocolHandler> {
/**
* Customize the protocol handler.
* @param protocolHandler the protocol handler to customize
*/
void customize(T protocolHandler);
}
...@@ -72,6 +72,8 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac ...@@ -72,6 +72,8 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<>(); private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<>();
private List<TomcatProtocolHandlerCustomizer> tomcatProtocolHandlerCustomizers = new ArrayList<>();
private String protocol = DEFAULT_PROTOCOL; private String protocol = DEFAULT_PROTOCOL;
private Charset uriEncoding = DEFAULT_CHARSET; private Charset uriEncoding = DEFAULT_CHARSET;
...@@ -168,6 +170,10 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac ...@@ -168,6 +170,10 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
if (connector.getProtocolHandler() instanceof AbstractProtocol) { if (connector.getProtocolHandler() instanceof AbstractProtocol) {
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler()); customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
} }
this.tomcatProtocolHandlerCustomizers.forEach(
(customizer) -> customizer.customize(connector.getProtocolHandler()));
if (getUriEncoding() != null) { if (getUriEncoding() != null) {
connector.setURIEncoding(getUriEncoding().name()); connector.setURIEncoding(getUriEncoding().name());
} }
...@@ -275,6 +281,42 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac ...@@ -275,6 +281,42 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
return this.tomcatConnectorCustomizers; return this.tomcatConnectorCustomizers;
} }
/**
* Set {@link TomcatProtocolHandlerCustomizer}s that should be applied to the Tomcat
* {@link Connector}. Calling this method will replace any existing customizers.
* @param tomcatProtocolHandlerCustomizers the customizers to set
*/
public void setTomcatProtocolHandlerCustomizers(
Collection<? extends TomcatProtocolHandlerCustomizer> tomcatProtocolHandlerCustomizers) {
Assert.notNull(tomcatProtocolHandlerCustomizers,
"TomcatProtocolHandlerCustomizers must not be null");
this.tomcatProtocolHandlerCustomizers = new ArrayList<>(
tomcatProtocolHandlerCustomizers);
}
/**
* Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat
* {@link Connector}.
* @param tomcatProtocolHandlerCustomizers the customizers to add
*/
@Override
public void addProtocolHandlerCustomizers(
TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers) {
Assert.notNull(tomcatProtocolHandlerCustomizers,
"TomcatProtocolHandlerCustomizers must not be null");
this.tomcatProtocolHandlerCustomizers
.addAll(Arrays.asList(tomcatProtocolHandlerCustomizers));
}
/**
* Returns a mutable collection of the {@link TomcatProtocolHandlerCustomizer}s that
* will be applied to the Tomcat {@link Connector}.
* @return the customizers that will be applied
*/
public Collection<TomcatProtocolHandlerCustomizer> getTomcatProtocolHandlerCustomizers() {
return this.tomcatProtocolHandlerCustomizers;
}
@Override @Override
public void addEngineValves(Valve... engineValves) { public void addEngineValves(Valve... engineValves) {
Assert.notNull(engineValves, "Valves must not be null"); Assert.notNull(engineValves, "Valves must not be null");
......
...@@ -117,6 +117,8 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto ...@@ -117,6 +117,8 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<>(); private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<>();
private List<TomcatProtocolHandlerCustomizer> tomcatProtocolHandlerCustomizers = new ArrayList<>();
private List<Connector> additionalTomcatConnectors = new ArrayList<>(); private List<Connector> additionalTomcatConnectors = new ArrayList<>();
private ResourceLoader resourceLoader; private ResourceLoader resourceLoader;
...@@ -303,6 +305,10 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto ...@@ -303,6 +305,10 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
if (connector.getProtocolHandler() instanceof AbstractProtocol) { if (connector.getProtocolHandler() instanceof AbstractProtocol) {
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler()); customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
} }
this.tomcatProtocolHandlerCustomizers.forEach(
(customizer) -> customizer.customize(connector.getProtocolHandler()));
if (getUriEncoding() != null) { if (getUriEncoding() != null) {
connector.setURIEncoding(getUriEncoding().name()); connector.setURIEncoding(getUriEncoding().name());
} }
...@@ -619,6 +625,42 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto ...@@ -619,6 +625,42 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
return this.tomcatConnectorCustomizers; return this.tomcatConnectorCustomizers;
} }
/**
* Set {@link TomcatProtocolHandlerCustomizer}s that should be applied to the Tomcat
* {@link Connector}. Calling this method will replace any existing customizers.
* @param tomcatProtocolHandlerCustomizer the customizers to set
*/
public void setTomcatProtocolHandlerCustomizers(
Collection<? extends TomcatProtocolHandlerCustomizer> tomcatProtocolHandlerCustomizer) {
Assert.notNull(tomcatProtocolHandlerCustomizer,
"TomcatProtocolHandlerCustomizers must not be null");
this.tomcatProtocolHandlerCustomizers = new ArrayList<>(
tomcatProtocolHandlerCustomizer);
}
/**
* Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat
* {@link Connector}.
* @param tomcatProtocolHandlerCustomizers the customizers to add
*/
@Override
public void addProtocolHandlerCustomizers(
TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers) {
Assert.notNull(tomcatProtocolHandlerCustomizers,
"TomcatProtocolHandlerCustomizers must not be null");
this.tomcatProtocolHandlerCustomizers
.addAll(Arrays.asList(tomcatProtocolHandlerCustomizers));
}
/**
* Returns a mutable collection of the {@link TomcatProtocolHandlerCustomizer}s that
* will be applied to the Tomcat {@link Connector}.
* @return the customizers that will be applied
*/
public Collection<TomcatProtocolHandlerCustomizer> getTomcatProtocolHandlerCustomizers() {
return this.tomcatProtocolHandlerCustomizers;
}
/** /**
* Add {@link Connector}s in addition to the default connector, e.g. for SSL or AJP * Add {@link Connector}s in addition to the default connector, e.g. for SSL or AJP
* @param connectors the connectors to add * @param connectors the connectors to add
......
...@@ -26,6 +26,8 @@ import org.apache.catalina.core.AprLifecycleListener; ...@@ -26,6 +26,8 @@ import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.RemoteIpValve; import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.InOrder; import org.mockito.InOrder;
...@@ -121,6 +123,24 @@ public class TomcatReactiveWebServerFactoryTests ...@@ -121,6 +123,24 @@ public class TomcatReactiveWebServerFactoryTests
.withMessageContaining("Customizers must not be null"); .withMessageContaining("Customizers must not be null");
} }
@Test
public void setNullProtocolHandlerCustomizersShouldThrowException() {
TomcatReactiveWebServerFactory factory = getFactory();
assertThatIllegalArgumentException()
.isThrownBy(() -> factory.setTomcatProtocolHandlerCustomizers(null))
.withMessageContaining(
"TomcatProtocolHandlerCustomizers must not be null");
}
@Test
public void addNullProtocolHandlerCustomizersShouldThrowException() {
TomcatReactiveWebServerFactory factory = getFactory();
assertThatIllegalArgumentException().isThrownBy(() -> factory
.addProtocolHandlerCustomizers((TomcatProtocolHandlerCustomizer[]) null))
.withMessageContaining(
"TomcatProtocolHandlerCustomizers must not be null");
}
@Test @Test
public void tomcatConnectorCustomizersShouldBeInvoked() { public void tomcatConnectorCustomizersShouldBeInvoked() {
TomcatReactiveWebServerFactory factory = getFactory(); TomcatReactiveWebServerFactory factory = getFactory();
...@@ -136,6 +156,22 @@ public class TomcatReactiveWebServerFactoryTests ...@@ -136,6 +156,22 @@ public class TomcatReactiveWebServerFactoryTests
} }
} }
@Test
public void tomcatProtocolHandlerCustomizersShouldBeInvoked() {
TomcatReactiveWebServerFactory factory = getFactory();
HttpHandler handler = mock(HttpHandler.class);
TomcatProtocolHandlerCustomizer<AbstractHttp11Protocol>[] listeners = new TomcatProtocolHandlerCustomizer[4];
Arrays.setAll(listeners, (i) -> mock(TomcatProtocolHandlerCustomizer.class));
factory.setTomcatProtocolHandlerCustomizers(
Arrays.asList(listeners[0], listeners[1]));
factory.addProtocolHandlerCustomizers(listeners[2], listeners[3]);
this.webServer = factory.getWebServer(handler);
InOrder ordered = inOrder((Object[]) listeners);
for (TomcatProtocolHandlerCustomizer listener : listeners) {
ordered.verify(listener).customize(any(ProtocolHandler.class));
}
}
@Test @Test
public void useForwardedHeaders() { public void useForwardedHeaders() {
TomcatReactiveWebServerFactory factory = getFactory(); TomcatReactiveWebServerFactory factory = getFactory();
......
...@@ -55,6 +55,8 @@ import org.apache.catalina.startup.Tomcat; ...@@ -55,6 +55,8 @@ import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.util.CharsetMapper; import org.apache.catalina.util.CharsetMapper;
import org.apache.catalina.valves.RemoteIpValve; import org.apache.catalina.valves.RemoteIpValve;
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.jasper.servlet.JspServlet; import org.apache.jasper.servlet.JspServlet;
import org.apache.tomcat.JarScanFilter; import org.apache.tomcat.JarScanFilter;
import org.apache.tomcat.JarScanType; import org.apache.tomcat.JarScanType;
...@@ -196,6 +198,35 @@ public class TomcatServletWebServerFactoryTests ...@@ -196,6 +198,35 @@ public class TomcatServletWebServerFactoryTests
} }
} }
@Test
public void tomcatProtocolHandlerCustomizersShouldBeInvoked() {
TomcatServletWebServerFactory factory = getFactory();
TomcatProtocolHandlerCustomizer<AbstractHttp11Protocol>[] listeners = new TomcatProtocolHandlerCustomizer[4];
Arrays.setAll(listeners, (i) -> mock(TomcatProtocolHandlerCustomizer.class));
factory.setTomcatProtocolHandlerCustomizers(
Arrays.asList(listeners[0], listeners[1]));
factory.addProtocolHandlerCustomizers(listeners[2], listeners[3]);
this.webServer = factory.getWebServer();
InOrder ordered = inOrder((Object[]) listeners);
for (TomcatProtocolHandlerCustomizer listener : listeners) {
ordered.verify(listener).customize(any(ProtocolHandler.class));
}
}
@Test
public void tomcatProtocolHandlerCanBeCustomized() {
TomcatServletWebServerFactory factory = getFactory();
TomcatProtocolHandlerCustomizer<AbstractHttp11Protocol> customizer = (
protocolHandler) -> protocolHandler.setProcessorCache(250);
factory.addProtocolHandlerCustomizers(customizer);
Tomcat tomcat = getTomcat(factory);
Connector connector = ((TomcatWebServer) this.webServer).getServiceConnectors()
.get(tomcat.getService())[0];
AbstractHttp11Protocol protocolHandler = (AbstractHttp11Protocol) connector
.getProtocolHandler();
assertThat(protocolHandler.getProcessorCache()).isEqualTo(250);
}
@Test @Test
public void tomcatAdditionalConnectors() { public void tomcatAdditionalConnectors() {
TomcatServletWebServerFactory factory = getFactory(); TomcatServletWebServerFactory factory = getFactory();
...@@ -280,6 +311,24 @@ public class TomcatServletWebServerFactoryTests ...@@ -280,6 +311,24 @@ public class TomcatServletWebServerFactoryTests
.withMessageContaining("TomcatConnectorCustomizers must not be null"); .withMessageContaining("TomcatConnectorCustomizers must not be null");
} }
@Test
public void setNullTomcatProtocolHandlerCustomizersThrows() {
TomcatServletWebServerFactory factory = getFactory();
assertThatIllegalArgumentException()
.isThrownBy(() -> factory.setTomcatProtocolHandlerCustomizers(null))
.withMessageContaining(
"TomcatProtocolHandlerCustomizers must not be null");
}
@Test
public void addNullTomcatProtocolHandlerCustomizersThrows() {
TomcatServletWebServerFactory factory = getFactory();
assertThatIllegalArgumentException().isThrownBy(() -> factory
.addProtocolHandlerCustomizers((TomcatProtocolHandlerCustomizer[]) null))
.withMessageContaining(
"TomcatProtocolHandlerCustomizers must not be null");
}
@Test @Test
public void uriEncoding() { public void uriEncoding() {
TomcatServletWebServerFactory factory = getFactory(); TomcatServletWebServerFactory factory = getFactory();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment