Enable HTTP/2 support for Tomcat and Undertow
This commit enables HTTP/2 support for Tomcat and Undertow, for both Servlet-based and Reactive applications. Enabling the `server.http2.enabled` configuration flag is enough with Undertow. Tomcat has a few prerequisites: * Tomcat 8.5 requires JDK8+ and the proper libtcnative version installed on the host * Tomcat 9.0.x requires JDK9+ Closes gh-10043
This commit is contained in:
parent
58db841c8f
commit
bb9396e3a4
|
@ -734,6 +734,54 @@ 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.
|
||||
|
||||
[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>>.
|
||||
====
|
||||
|
||||
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.
|
||||
|
||||
|
||||
[[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.
|
||||
|
||||
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].
|
||||
|
||||
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.
|
||||
----
|
||||
|
||||
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.
|
||||
|
||||
[[howto-configure-accesslogs]]
|
||||
=== Configure Access Logging
|
||||
Access logs can be configured for Tomcat, Undertow, and Jetty through their respective
|
||||
|
|
|
@ -45,22 +45,21 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer {
|
|||
private final SslStoreProvider sslStoreProvider;
|
||||
|
||||
SslConnectorCustomizer(Ssl ssl, SslStoreProvider sslStoreProvider) {
|
||||
Assert.notNull(ssl, "Ssl configuration should not be null");
|
||||
this.ssl = ssl;
|
||||
this.sslStoreProvider = sslStoreProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(Connector connector) {
|
||||
if (this.ssl != null && this.ssl.isEnabled()) {
|
||||
ProtocolHandler handler = connector.getProtocolHandler();
|
||||
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);
|
||||
connector.setScheme("https");
|
||||
connector.setSecure(true);
|
||||
}
|
||||
ProtocolHandler handler = connector.getProtocolHandler();
|
||||
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);
|
||||
connector.setScheme("https");
|
||||
connector.setSecure(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.catalina.core.AprLifecycleListener;
|
|||
import org.apache.catalina.loader.WebappLoader;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.http2.Http2Protocol;
|
||||
|
||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
||||
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
|
||||
|
@ -141,8 +142,13 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
|||
// If ApplicationContext is slow to start we want Tomcat not to bind to the socket
|
||||
// prematurely...
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
}
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
|
||||
compression.customize(connector);
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.apache.catalina.webresources.AbstractResourceSet;
|
|||
import org.apache.catalina.webresources.EmptyResource;
|
||||
import org.apache.catalina.webresources.StandardRoot;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.http2.Http2Protocol;
|
||||
|
||||
import org.springframework.boot.web.server.ErrorPage;
|
||||
import org.springframework.boot.web.server.MimeMappings;
|
||||
|
@ -297,8 +298,13 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
|||
// prematurely...
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
TomcatConnectorCustomizer ssl = new SslConnectorCustomizer(getSsl(), getSslStoreProvider());
|
||||
ssl.customize(connector);
|
||||
if (getHttp2() != null && getHttp2().getEnabled()) {
|
||||
connector.addUpgradeProtocol(new Http2Protocol());
|
||||
}
|
||||
}
|
||||
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
|
||||
compression.customize(connector);
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
|
||||
import io.undertow.Undertow;
|
||||
import io.undertow.UndertowOptions;
|
||||
|
||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
||||
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
|
||||
|
@ -89,6 +90,9 @@ public class UndertowReactiveWebServerFactory extends AbstractReactiveWebServerF
|
|||
SslBuilderCustomizer sslBuilderCustomizer =
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider());
|
||||
sslBuilderCustomizer.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, getHttp2().getEnabled());
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.addHttpListener(port, getListenAddress());
|
||||
|
|
|
@ -36,6 +36,7 @@ import javax.servlet.ServletException;
|
|||
|
||||
import io.undertow.Undertow;
|
||||
import io.undertow.Undertow.Builder;
|
||||
import io.undertow.UndertowOptions;
|
||||
import io.undertow.server.HttpHandler;
|
||||
import io.undertow.server.handlers.accesslog.AccessLogHandler;
|
||||
import io.undertow.server.handlers.accesslog.AccessLogReceiver;
|
||||
|
@ -235,6 +236,9 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
|
|||
SslBuilderCustomizer sslBuilderCustomizer =
|
||||
new SslBuilderCustomizer(getPort(), getAddress(), getSsl(), getSslStoreProvider());
|
||||
sslBuilderCustomizer.customize(builder);
|
||||
if (getHttp2() != null) {
|
||||
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, getHttp2().getEnabled());
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.addHttpListener(port, getListenAddress());
|
||||
|
|
Loading…
Reference in New Issue