Merge pull request #16342 Pascal Zwick
* pr/16342: Polish "Simplify the configuration of the ProtocolHandler" Simplify the configuration of the ProtocolHandler
This commit is contained in:
commit
7587af343d
|
@ -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 {
|
||||||
@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;
|
||||||
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 {
|
||||||
@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;
|
||||||
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 {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class TomcatProtocolHandlerCustomizerConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() {
|
||||||
|
return (protocolHandler) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class TomcatProtocolHandlerCustomizerConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() {
|
||||||
|
return (protocolHandler) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
}
|
|
@ -34,9 +34,11 @@ import org.apache.catalina.core.AprLifecycleListener;
|
||||||
import org.apache.catalina.loader.WebappLoader;
|
import org.apache.catalina.loader.WebappLoader;
|
||||||
import org.apache.catalina.startup.Tomcat;
|
import org.apache.catalina.startup.Tomcat;
|
||||||
import org.apache.coyote.AbstractProtocol;
|
import org.apache.coyote.AbstractProtocol;
|
||||||
|
import org.apache.coyote.ProtocolHandler;
|
||||||
import org.apache.coyote.http2.Http2Protocol;
|
import org.apache.coyote.http2.Http2Protocol;
|
||||||
import org.apache.tomcat.util.scan.StandardJarScanFilter;
|
import org.apache.tomcat.util.scan.StandardJarScanFilter;
|
||||||
|
|
||||||
|
import org.springframework.boot.util.LambdaSafe;
|
||||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
||||||
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
|
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
|
||||||
import org.springframework.boot.web.server.WebServer;
|
import org.springframework.boot.web.server.WebServer;
|
||||||
|
@ -72,6 +74,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 +172,7 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||||
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
|
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
|
||||||
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
|
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
|
||||||
}
|
}
|
||||||
|
invokeProtocolHandlerCustomizers(connector);
|
||||||
if (getUriEncoding() != null) {
|
if (getUriEncoding() != null) {
|
||||||
connector.setURIEncoding(getUriEncoding().name());
|
connector.setURIEncoding(getUriEncoding().name());
|
||||||
}
|
}
|
||||||
|
@ -184,6 +189,15 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void invokeProtocolHandlerCustomizers(Connector connector) {
|
||||||
|
ProtocolHandler protocolHandler = connector.getProtocolHandler();
|
||||||
|
LambdaSafe
|
||||||
|
.callbacks(TomcatProtocolHandlerCustomizer.class,
|
||||||
|
this.tomcatProtocolHandlerCustomizers, protocolHandler)
|
||||||
|
.invoke((customizer) -> customizer.customize(protocolHandler));
|
||||||
|
}
|
||||||
|
|
||||||
private void customizeProtocol(AbstractProtocol<?> protocol) {
|
private void customizeProtocol(AbstractProtocol<?> protocol) {
|
||||||
if (getAddress() != null) {
|
if (getAddress() != null) {
|
||||||
protocol.setAddress(getAddress());
|
protocol.setAddress(getAddress());
|
||||||
|
@ -275,6 +289,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");
|
||||||
|
|
|
@ -58,9 +58,11 @@ import org.apache.catalina.webresources.AbstractResourceSet;
|
||||||
import org.apache.catalina.webresources.EmptyResource;
|
import org.apache.catalina.webresources.EmptyResource;
|
||||||
import org.apache.catalina.webresources.StandardRoot;
|
import org.apache.catalina.webresources.StandardRoot;
|
||||||
import org.apache.coyote.AbstractProtocol;
|
import org.apache.coyote.AbstractProtocol;
|
||||||
|
import org.apache.coyote.ProtocolHandler;
|
||||||
import org.apache.coyote.http2.Http2Protocol;
|
import org.apache.coyote.http2.Http2Protocol;
|
||||||
import org.apache.tomcat.util.scan.StandardJarScanFilter;
|
import org.apache.tomcat.util.scan.StandardJarScanFilter;
|
||||||
|
|
||||||
|
import org.springframework.boot.util.LambdaSafe;
|
||||||
import org.springframework.boot.web.server.ErrorPage;
|
import org.springframework.boot.web.server.ErrorPage;
|
||||||
import org.springframework.boot.web.server.MimeMappings;
|
import org.springframework.boot.web.server.MimeMappings;
|
||||||
import org.springframework.boot.web.server.WebServer;
|
import org.springframework.boot.web.server.WebServer;
|
||||||
|
@ -117,6 +119,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 +307,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||||
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
|
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
|
||||||
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
|
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
|
||||||
}
|
}
|
||||||
|
invokeProtocolHandlerCustomizers(connector);
|
||||||
if (getUriEncoding() != null) {
|
if (getUriEncoding() != null) {
|
||||||
connector.setURIEncoding(getUriEncoding().name());
|
connector.setURIEncoding(getUriEncoding().name());
|
||||||
}
|
}
|
||||||
|
@ -325,6 +330,15 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void invokeProtocolHandlerCustomizers(Connector connector) {
|
||||||
|
ProtocolHandler protocolHandler = connector.getProtocolHandler();
|
||||||
|
LambdaSafe
|
||||||
|
.callbacks(TomcatProtocolHandlerCustomizer.class,
|
||||||
|
this.tomcatProtocolHandlerCustomizers, protocolHandler)
|
||||||
|
.invoke((customizer) -> customizer.customize(protocolHandler));
|
||||||
|
}
|
||||||
|
|
||||||
private void customizeSsl(Connector connector) {
|
private void customizeSsl(Connector connector) {
|
||||||
new SslConnectorCustomizer(getSsl(), getSslStoreProvider()).customize(connector);
|
new SslConnectorCustomizer(getSsl(), getSslStoreProvider()).customize(connector);
|
||||||
if (getHttp2() != null && getHttp2().isEnabled()) {
|
if (getHttp2() != null && getHttp2().isEnabled()) {
|
||||||
|
@ -619,6 +633,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;
|
||||||
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
|
||||||
.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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
.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();
|
||||||
|
|
Loading…
Reference in New Issue