Polish
This commit is contained in:
@@ -193,10 +193,9 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
|
||||
*/
|
||||
protected void logError(ServerRequest request, HttpStatus errorStatus) {
|
||||
if (errorStatus.is5xxServerError()) {
|
||||
Throwable error = getError(request);
|
||||
final String message = "Failed to handle request ["
|
||||
+ request.methodName() + " " + request.uri() + "]";
|
||||
logger.error(message, error);
|
||||
Throwable ex = getError(request);
|
||||
logger.error("Failed to handle request [" + request.methodName() + " "
|
||||
+ request.uri() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ content into your application; rather pick only the properties that you need.
|
||||
server.error.include-stacktrace=never # When to include a "stacktrace" attribute.
|
||||
server.error.path=/error # Path of the error controller.
|
||||
server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error.
|
||||
server.http2.enabled=true # Enable HTTP/2 support if the current environment supports it.
|
||||
server.http2.enabled=true # Whether to enable HTTP/2 support, if the current environment supports it.
|
||||
server.jetty.acceptors= # Number of acceptor threads to use.
|
||||
server.jetty.accesslog.append=false # Append to log.
|
||||
server.jetty.accesslog.date-format=dd/MMM/yyyy:HH:mm:ss Z # Timestamp format of the request log.
|
||||
|
||||
@@ -737,50 +737,51 @@ sample project for an example.
|
||||
[[howto-configure-http2]]
|
||||
=== Configure HTTP/2
|
||||
You can enable HTTP/2 support in your Spring Boot application with the
|
||||
`+server.http2.enabled+` configuration property. This support depends on the
|
||||
chosen web server and the application environment, since that protocol is not
|
||||
supported out-of-the-box by JDK8.
|
||||
`+server.http2.enabled+` configuration property. This support depends on the chosen web
|
||||
server and the application environment, since that protocol is not supported
|
||||
out-of-the-box by JDK8.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Boot does not support `h2c`, the cleartext version of the HTTP/2
|
||||
protocol. So you must configure <<howto-configure-ssl, configure SSL first>>.
|
||||
Spring Boot does not support `h2c`, the cleartext version of the HTTP/2 protocol. So you
|
||||
must configure <<howto-configure-ssl, configure SSL first>>.
|
||||
====
|
||||
|
||||
Currently, only Undertow and Tomcat are supported with this configuration key.
|
||||
|
||||
|
||||
|
||||
[[howto-configure-http2-undertow]]
|
||||
==== HTTP/2 with Undertow
|
||||
As of Undertow 1.4.0+, HTTP/2 is supported without any additional requirement
|
||||
on JDK8.
|
||||
As of Undertow 1.4.0+, HTTP/2 is supported without any additional requirement on JDK8.
|
||||
|
||||
|
||||
|
||||
[[howto-configure-http2-tomcat]]
|
||||
==== HTTP/2 with Tomcat
|
||||
Spring Boot ships by default with Tomcat 8.5.x; with that version,
|
||||
HTTP/2 is only supported if the `libtcnative` library and its dependencies
|
||||
are installed on the host operating system.
|
||||
Spring Boot ships by default with Tomcat 8.5.x; with that version, HTTP/2 is only
|
||||
supported if the `libtcnative` library and its dependencies are installed on the host
|
||||
operating system.
|
||||
|
||||
The library folder must be made available, if not already, to the JVM library
|
||||
path; this can be done with a JVM argument such as
|
||||
The library folder must be made available, if not already, to the JVM library path; this
|
||||
can be done with a JVM argument such as
|
||||
`-Djava.library.path=/usr/local/opt/tomcat-native/lib`. More on this in the
|
||||
http://tomcat.apache.org/tomcat-8.5-doc/apr.html[official Tomcat
|
||||
documentation].
|
||||
http://tomcat.apache.org/tomcat-8.5-doc/apr.html[official Tomcat documentation].
|
||||
|
||||
Starting Tomcat 8.5.x without that native support will log the following error:
|
||||
|
||||
[indent=0,subs="attributes"]
|
||||
----
|
||||
ERROR 8787 --- [ main] o.a.coyote.http11.Http11NioProtocol : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.
|
||||
ERROR 8787 --- [ main] o.a.coyote.http11.Http11NioProtocol : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.
|
||||
----
|
||||
|
||||
This error is not fatal, and the application starts with HTTP/1.1 SSL
|
||||
support still.
|
||||
This error is not fatal, and the application starts with HTTP/1.1 SSL support still.
|
||||
|
||||
Running your application with Tomcat 9.0.x and JDK9 doesn't require any native library
|
||||
installed. To use Tomcat 9, you can override the `tomcat.version` build property with the
|
||||
version of your choice.
|
||||
|
||||
|
||||
Running your application with Tomcat 9.0.x and JDK9 doesn't require any native
|
||||
library installed. To use Tomcat 9, you can override the `tomcat.version`
|
||||
build property with the version of your choice.
|
||||
|
||||
[[howto-configure-accesslogs]]
|
||||
=== Configure Access Logging
|
||||
|
||||
@@ -97,10 +97,9 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
|
||||
ServletContextHandler contextHandler = new ServletContextHandler(server, "",
|
||||
false, false);
|
||||
contextHandler.addServlet(servletHolder, "/");
|
||||
this.logger.info("Server initialized with port: " + port);
|
||||
SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(port,
|
||||
getSsl(), getSslStoreProvider());
|
||||
sslServerCustomizer.customize(server);
|
||||
JettyReactiveWebServerFactory.logger
|
||||
.info("Server initialized with port: " + port);
|
||||
new SslServerCustomizer(port, getSsl(), getSslStoreProvider()).customize(server);
|
||||
for (JettyServerCustomizer customizer : getServerCustomizers()) {
|
||||
customizer.customize(server);
|
||||
}
|
||||
|
||||
@@ -153,9 +153,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
|
||||
configureWebAppContext(context, initializers);
|
||||
server.setHandler(addHandlerWrappers(context));
|
||||
this.logger.info("Server initialized with port: " + port);
|
||||
SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(port,
|
||||
getSsl(), getSslStoreProvider());
|
||||
sslServerCustomizer.customize(server);
|
||||
new SslServerCustomizer(port, getSsl(), getSslStoreProvider()).customize(server);
|
||||
for (JettyServerCustomizer customizer : getServerCustomizers()) {
|
||||
customizer.customize(server);
|
||||
}
|
||||
@@ -167,7 +165,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
|
||||
|
||||
private Server createServer(InetSocketAddress address) {
|
||||
Server server = new Server(getThreadPool());
|
||||
server.setConnectors(new Connector[] {createConnector(address, server)});
|
||||
server.setConnectors(new Connector[] { createConnector(address, server) });
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -338,7 +336,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
|
||||
context.getServletHandler().addServlet(holder);
|
||||
ServletMapping mapping = new ServletMapping();
|
||||
mapping.setServletName("jsp");
|
||||
mapping.setPathSpecs(new String[] {"*.jsp", "*.jspx"});
|
||||
mapping.setPathSpecs(new String[] { "*.jsp", "*.jspx" });
|
||||
context.getServletHandler().addServletMapping(mapping);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
/**
|
||||
* {@link JettyServerCustomizer} that configures SSL on the
|
||||
* given Jetty server instance.
|
||||
* {@link JettyServerCustomizer} that configures SSL on the given Jetty server instance.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
@@ -88,7 +87,8 @@ class SslServerCustomizer implements JettyServerCustomizer {
|
||||
* @param ssl the ssl details.
|
||||
* @param sslStoreProvider the ssl store provider
|
||||
*/
|
||||
protected void configureSsl(SslContextFactory factory, Ssl ssl, SslStoreProvider sslStoreProvider) {
|
||||
protected void configureSsl(SslContextFactory factory, Ssl ssl,
|
||||
SslStoreProvider sslStoreProvider) {
|
||||
factory.setProtocol(ssl.getProtocol());
|
||||
configureSslClientAuth(factory, ssl);
|
||||
configureSslPasswords(factory, ssl);
|
||||
@@ -172,4 +172,5 @@ class SslServerCustomizer implements JettyServerCustomizer {
|
||||
factory.setTrustStoreProvider(ssl.getTrustStoreProvider());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,14 +24,13 @@ import org.springframework.boot.web.server.Compression;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link TomcatConnectorCustomizer} that configures compression
|
||||
* support on the given Connector.
|
||||
* {@link TomcatConnectorCustomizer} that configures compression support on the given
|
||||
* Connector.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class CompressionConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
|
||||
|
||||
private final Compression compression;
|
||||
|
||||
CompressionConnectorCustomizer(Compression compression) {
|
||||
@@ -43,18 +42,21 @@ class CompressionConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
if (this.compression != null && this.compression.getEnabled()) {
|
||||
ProtocolHandler handler = connector.getProtocolHandler();
|
||||
if (handler instanceof AbstractHttp11Protocol) {
|
||||
AbstractHttp11Protocol<?> protocol = (AbstractHttp11Protocol<?>) handler;
|
||||
Compression compression = this.compression;
|
||||
protocol.setCompression("on");
|
||||
protocol.setCompressionMinSize(compression.getMinResponseSize());
|
||||
protocol.setCompressibleMimeType(
|
||||
StringUtils.arrayToCommaDelimitedString(compression.getMimeTypes()));
|
||||
if (this.compression.getExcludedUserAgents() != null) {
|
||||
protocol.setNoCompressionUserAgents(
|
||||
StringUtils.arrayToCommaDelimitedString(
|
||||
this.compression.getExcludedUserAgents()));
|
||||
}
|
||||
customize((AbstractHttp11Protocol<?>) handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void customize(AbstractHttp11Protocol<?> protocol) {
|
||||
Compression compression = this.compression;
|
||||
protocol.setCompression("on");
|
||||
protocol.setCompressionMinSize(compression.getMinResponseSize());
|
||||
protocol.setCompressibleMimeType(
|
||||
StringUtils.arrayToCommaDelimitedString(compression.getMimeTypes()));
|
||||
if (this.compression.getExcludedUserAgents() != null) {
|
||||
protocol.setNoCompressionUserAgents(StringUtils.arrayToCommaDelimitedString(
|
||||
this.compression.getExcludedUserAgents()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link TomcatConnectorCustomizer} that configures SSL support
|
||||
* on the given connector.
|
||||
* {@link TomcatConnectorCustomizer} that configures SSL support on the given connector.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
@@ -56,8 +55,8 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
Assert.state(handler instanceof AbstractHttp11JsseProtocol,
|
||||
"To use SSL, the connector's protocol handler must be an "
|
||||
+ "AbstractHttp11JsseProtocol subclass");
|
||||
configureSsl((AbstractHttp11JsseProtocol<?>) handler,
|
||||
this.ssl, this.sslStoreProvider);
|
||||
configureSsl((AbstractHttp11JsseProtocol<?>) handler, this.ssl,
|
||||
this.sslStoreProvider);
|
||||
connector.setScheme("https");
|
||||
connector.setSecure(true);
|
||||
}
|
||||
@@ -68,8 +67,8 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
* @param ssl the ssl details
|
||||
* @param sslStoreProvider the ssl store provider
|
||||
*/
|
||||
protected void configureSsl(AbstractHttp11JsseProtocol<?> protocol,
|
||||
Ssl ssl, SslStoreProvider sslStoreProvider) {
|
||||
protected void configureSsl(AbstractHttp11JsseProtocol<?> protocol, Ssl ssl,
|
||||
SslStoreProvider sslStoreProvider) {
|
||||
protocol.setSSLEnabled(true);
|
||||
protocol.setSslProtocol(ssl.getProtocol());
|
||||
configureSslClientAuth(protocol, ssl);
|
||||
@@ -112,8 +111,7 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
.getInstance();
|
||||
instance.addUserFactory(
|
||||
new SslStoreProviderUrlStreamHandlerFactory(sslStoreProvider));
|
||||
protocol.setKeystoreFile(
|
||||
SslStoreProviderUrlStreamHandlerFactory.KEY_STORE_URL);
|
||||
protocol.setKeystoreFile(SslStoreProviderUrlStreamHandlerFactory.KEY_STORE_URL);
|
||||
protocol.setTruststoreFile(
|
||||
SslStoreProviderUrlStreamHandlerFactory.TRUST_STORE_URL);
|
||||
}
|
||||
@@ -153,4 +151,5 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
protocol.setTruststoreProvider(ssl.getTrustStoreProvider());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
@@ -56,7 +57,8 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
|
||||
private String protocol = DEFAULT_PROTOCOL;
|
||||
|
||||
private List<LifecycleListener> contextLifecycleListeners = Arrays.asList(new AprLifecycleListener());
|
||||
private List<LifecycleListener> contextLifecycleListeners = new ArrayList<LifecycleListener>(
|
||||
Collections.singleton(new AprLifecycleListener()));
|
||||
|
||||
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<>();
|
||||
|
||||
@@ -120,15 +122,11 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
* @param context the Tomcat context
|
||||
*/
|
||||
protected void configureContext(Context context) {
|
||||
for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
|
||||
context.addLifecycleListener(lifecycleListener);
|
||||
}
|
||||
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
|
||||
customizer.customize(context);
|
||||
}
|
||||
this.contextLifecycleListeners.forEach(context::addLifecycleListener);
|
||||
this.tomcatContextCustomizers
|
||||
.forEach((customizer) -> customizer.customize(context));
|
||||
}
|
||||
|
||||
// Needs to be protected so it can be used by subclasses
|
||||
protected void customizeConnector(Connector connector) {
|
||||
int port = (getPort() >= 0 ? getPort() : 0);
|
||||
connector.setPort(port);
|
||||
@@ -138,18 +136,13 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
|
||||
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
|
||||
}
|
||||
|
||||
// If ApplicationContext is slow to start we want Tomcat not to bind to the socket
|
||||
// prematurely...
|
||||
// Don't bind to the socket prematurely if ApplicationContext is slow to start
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
customizeSsl(connector);
|
||||
}
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(
|
||||
getCompression());
|
||||
compression.customize(connector);
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
customizer.customize(connector);
|
||||
@@ -162,6 +155,13 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
}
|
||||
}
|
||||
|
||||
private void customizeSsl(Connector connector) {
|
||||
new SslConnectorCustomizer(getSsl(), getSslStoreProvider()).customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat
|
||||
* {@link Context} . Calling this method will replace any existing customizers.
|
||||
@@ -260,7 +260,6 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method called to create the {@link TomcatWebServer}. Subclasses can
|
||||
* override this method to return a different {@link TomcatWebServer} or apply
|
||||
|
||||
@@ -111,7 +111,8 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||
|
||||
private List<Valve> contextValves = new ArrayList<>();
|
||||
|
||||
private List<LifecycleListener> contextLifecycleListeners = Arrays.asList(new AprLifecycleListener());
|
||||
private List<LifecycleListener> contextLifecycleListeners = new ArrayList<>(
|
||||
Collections.singleton(new AprLifecycleListener()));
|
||||
|
||||
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<>();
|
||||
|
||||
@@ -293,19 +294,13 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||
if (getUriEncoding() != null) {
|
||||
connector.setURIEncoding(getUriEncoding().name());
|
||||
}
|
||||
|
||||
// If ApplicationContext is slow to start we want Tomcat not to bind to the socket
|
||||
// prematurely...
|
||||
// Don't bind to the socket prematurely if ApplicationContext is slow to start
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
customizeSsl(connector);
|
||||
}
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(
|
||||
getCompression());
|
||||
compression.customize(connector);
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
customizer.customize(connector);
|
||||
@@ -318,6 +313,13 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||
}
|
||||
}
|
||||
|
||||
private void customizeSsl(Connector connector) {
|
||||
new SslConnectorCustomizer(getSsl(), getSslStoreProvider()).customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the Tomcat {@link Context}.
|
||||
* @param context the Tomcat context
|
||||
|
||||
@@ -44,8 +44,7 @@ import org.springframework.boot.web.server.SslStoreProvider;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
/**
|
||||
* {@link UndertowBuilderCustomizer} that configures SSL
|
||||
* on the given builder instance.
|
||||
* {@link UndertowBuilderCustomizer} that configures SSL on the given builder instance.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
@@ -59,8 +58,8 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
|
||||
private final SslStoreProvider sslStoreProvider;
|
||||
|
||||
SslBuilderCustomizer(int port, InetAddress address,
|
||||
Ssl ssl, SslStoreProvider sslStoreProvider) {
|
||||
SslBuilderCustomizer(int port, InetAddress address, Ssl ssl,
|
||||
SslStoreProvider sslStoreProvider) {
|
||||
this.port = port;
|
||||
this.address = address;
|
||||
this.ssl = ssl;
|
||||
@@ -73,7 +72,8 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
SSLContext sslContext = SSLContext.getInstance(this.ssl.getProtocol());
|
||||
sslContext.init(getKeyManagers(this.ssl, this.sslStoreProvider),
|
||||
getTrustManagers(this.ssl, this.sslStoreProvider), null);
|
||||
builder.addHttpsListener(this.port, getListenAddress(this.address), sslContext);
|
||||
builder.addHttpsListener(this.port, getListenAddress(this.address),
|
||||
sslContext);
|
||||
builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE,
|
||||
getSslClientAuthMode(this.ssl));
|
||||
if (this.ssl.getEnabledProtocols() != null) {
|
||||
@@ -143,7 +143,8 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
return keyManagers;
|
||||
}
|
||||
|
||||
private KeyStore getKeyStore(Ssl ssl, SslStoreProvider sslStoreProvider) throws Exception {
|
||||
private KeyStore getKeyStore(Ssl ssl, SslStoreProvider sslStoreProvider)
|
||||
throws Exception {
|
||||
if (sslStoreProvider != null) {
|
||||
return sslStoreProvider.getKeyStore();
|
||||
}
|
||||
@@ -164,7 +165,8 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
}
|
||||
}
|
||||
|
||||
private KeyStore getTrustStore(Ssl ssl, SslStoreProvider sslStoreProvider) throws Exception {
|
||||
private KeyStore getTrustStore(Ssl ssl, SslStoreProvider sslStoreProvider)
|
||||
throws Exception {
|
||||
if (sslStoreProvider != null) {
|
||||
return sslStoreProvider.getTrustStore();
|
||||
}
|
||||
@@ -247,4 +249,5 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,12 +87,7 @@ public class UndertowReactiveWebServerFactory extends AbstractReactiveWebServerF
|
||||
builder.setDirectBuffers(this.directBuffers);
|
||||
}
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
SslBuilderCustomizer sslBuilderCustomizer =
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider());
|
||||
sslBuilderCustomizer.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, getHttp2().getEnabled());
|
||||
}
|
||||
customizeSsl(builder);
|
||||
}
|
||||
else {
|
||||
builder.addHttpListener(port, getListenAddress());
|
||||
@@ -103,6 +98,15 @@ public class UndertowReactiveWebServerFactory extends AbstractReactiveWebServerF
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void customizeSsl(Undertow.Builder builder) {
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider())
|
||||
.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2,
|
||||
getHttp2().getEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
private String getListenAddress() {
|
||||
if (getAddress() == null) {
|
||||
return "0.0.0.0";
|
||||
|
||||
@@ -233,12 +233,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
|
||||
builder.setDirectBuffers(this.directBuffers);
|
||||
}
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
SslBuilderCustomizer sslBuilderCustomizer =
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider());
|
||||
sslBuilderCustomizer.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, getHttp2().getEnabled());
|
||||
}
|
||||
customizeSsl(builder);
|
||||
}
|
||||
else {
|
||||
builder.addHttpListener(port, getListenAddress());
|
||||
@@ -249,6 +244,15 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void customizeSsl(Builder builder) {
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider())
|
||||
.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2,
|
||||
getHttp2().getEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
private String getListenAddress() {
|
||||
if (getAddress() == null) {
|
||||
return "0.0.0.0";
|
||||
@@ -602,7 +606,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class LoaderHidingResourceManager implements ResourceManager {
|
||||
|
||||
private final ResourceManager delegate;
|
||||
|
||||
@@ -36,4 +36,5 @@ public class Http2 {
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,13 +56,11 @@ public class SslConnectorCustomizerTests {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setCiphers(new String[] {"ALPHA", "BRAVO", "CHARLIE"});
|
||||
|
||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||
SslConnectorCustomizer customizer = new SslConnectorCustomizer(ssl, null);
|
||||
Connector connector = this.tomcat.getConnector();
|
||||
customizer.customize(connector);
|
||||
this.tomcat.start();
|
||||
|
||||
SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler()
|
||||
.findSslHostConfigs();
|
||||
assertThat(sslHostConfigs[0].getCiphers()).isEqualTo("ALPHA:BRAVO:CHARLIE");
|
||||
@@ -73,15 +71,12 @@ public class SslConnectorCustomizerTests {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
|
||||
ssl.setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
|
||||
ssl.setCiphers(new String[] {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO"});
|
||||
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
SslConnectorCustomizer customizer = new SslConnectorCustomizer(ssl, null);
|
||||
Connector connector = this.tomcat.getConnector();
|
||||
customizer.customize(connector);
|
||||
this.tomcat.start();
|
||||
|
||||
SSLHostConfig sslHostConfig = connector.getProtocolHandler()
|
||||
.findSslHostConfigs()[0];
|
||||
assertThat(sslHostConfig.getSslProtocol()).isEqualTo("TLS");
|
||||
@@ -94,18 +89,16 @@ public class SslConnectorCustomizerTests {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
|
||||
ssl.setEnabledProtocols(new String[] {"TLSv1.2"});
|
||||
ssl.setCiphers(new String[] {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO"});
|
||||
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
SslConnectorCustomizer customizer = new SslConnectorCustomizer(ssl, null);
|
||||
Connector connector = this.tomcat.getConnector();
|
||||
customizer.customize(connector);
|
||||
this.tomcat.start();
|
||||
|
||||
SSLHostConfig sslHostConfig = connector.getProtocolHandler()
|
||||
.findSslHostConfigs()[0];
|
||||
assertThat(sslHostConfig.getSslProtocol()).isEqualTo("TLS");
|
||||
assertThat(sslHostConfig.getEnabledProtocols()).containsExactly("TLSv1.2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,9 +67,8 @@ public class TomcatReactiveWebServerFactoryTests
|
||||
@Test
|
||||
public void defaultTomcatListeners() throws Exception {
|
||||
TomcatReactiveWebServerFactory factory = getFactory();
|
||||
assertThat(factory.getContextLifecycleListeners())
|
||||
.hasSize(1)
|
||||
.first().isInstanceOf(AprLifecycleListener.class);
|
||||
assertThat(factory.getContextLifecycleListeners()).hasSize(1).first()
|
||||
.isInstanceOf(AprLifecycleListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -104,9 +104,8 @@ public class TomcatServletWebServerFactoryTests
|
||||
@Test
|
||||
public void defaultTomcatListeners() throws Exception {
|
||||
TomcatServletWebServerFactory factory = getFactory();
|
||||
assertThat(factory.getContextLifecycleListeners())
|
||||
.hasSize(1)
|
||||
.first().isInstanceOf(AprLifecycleListener.class);
|
||||
assertThat(factory.getContextLifecycleListeners()).hasSize(1).first()
|
||||
.isInstanceOf(AprLifecycleListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -39,11 +39,13 @@ public class SslBuilderCustomizerTests {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
SslBuilderCustomizer customizer = new SslBuilderCustomizer(8080, InetAddress.getLocalHost(), ssl, null);
|
||||
SslBuilderCustomizer customizer = new SslBuilderCustomizer(8080,
|
||||
InetAddress.getLocalHost(), ssl, null);
|
||||
KeyManager[] keyManagers = ReflectionTestUtils.invokeMethod(customizer,
|
||||
"getKeyManagers", ssl, null);
|
||||
Class<?> name = Class.forName("org.springframework.boot.web.embedded.undertow"
|
||||
+ ".SslBuilderCustomizer$ConfigurableAliasKeyManager");
|
||||
assertThat(keyManagers[0]).isNotInstanceOf(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
factory.setPort(specificPort);
|
||||
this.webServer = factory.getWebServer(new EchoHandler());
|
||||
this.webServer.start();
|
||||
Mono<String> result = getWebClient().build().post()
|
||||
.uri("/test").contentType(MediaType.TEXT_PLAIN)
|
||||
Mono<String> result = getWebClient().build().post().uri("/test")
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.body(BodyInserters.fromObject("Hello World")).exchange()
|
||||
.flatMap((response) -> response.bodyToMono(String.class));
|
||||
assertThat(result.block()).isEqualTo("Hello World");
|
||||
@@ -97,7 +97,6 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
testBasicSslWithKeyStore("src/test/resources/test.jks");
|
||||
}
|
||||
|
||||
|
||||
protected final void testBasicSslWithKeyStore(String keyStore) throws Exception {
|
||||
AbstractReactiveWebServerFactory factory = getFactory();
|
||||
Ssl ssl = new Ssl();
|
||||
@@ -106,30 +105,27 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
factory.setSsl(ssl);
|
||||
this.webServer = factory.getWebServer(new EchoHandler());
|
||||
this.webServer.start();
|
||||
|
||||
ReactorClientHttpConnector connector = buildTrustAllSslConnector();
|
||||
WebClient client = WebClient.builder()
|
||||
.baseUrl("https://localhost:" + this.webServer.getPort())
|
||||
.clientConnector(connector).build();
|
||||
|
||||
Mono<String> result = client.post()
|
||||
.uri("/test").contentType(MediaType.TEXT_PLAIN)
|
||||
Mono<String> result = client.post().uri("/test").contentType(MediaType.TEXT_PLAIN)
|
||||
.body(BodyInserters.fromObject("Hello World")).exchange()
|
||||
.flatMap((response) -> response.bodyToMono(String.class));
|
||||
assertThat(result.block()).isEqualTo("Hello World");
|
||||
}
|
||||
|
||||
protected ReactorClientHttpConnector buildTrustAllSslConnector() {
|
||||
return new ReactorClientHttpConnector(options -> options
|
||||
.sslSupport(sslContextBuilder -> {
|
||||
sslContextBuilder
|
||||
.sslProvider(SslProvider.JDK)
|
||||
return new ReactorClientHttpConnector(
|
||||
(options) -> options.sslSupport(sslContextBuilder -> {
|
||||
sslContextBuilder.sslProvider(SslProvider.JDK)
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE);
|
||||
}));
|
||||
}
|
||||
|
||||
protected WebClient.Builder getWebClient() {
|
||||
return WebClient.builder().baseUrl("http://localhost:" + this.webServer.getPort());
|
||||
return WebClient.builder()
|
||||
.baseUrl("http://localhost:" + this.webServer.getPort());
|
||||
}
|
||||
|
||||
protected static class EchoHandler implements HttpHandler {
|
||||
|
||||
Reference in New Issue
Block a user