Commit fea535d1 authored by Brian Clozel's avatar Brian Clozel

Update HTTP/2 auto-configuration for Jetty

Prior to this commit, the HTTP/2 server auto-configuration for Jetty
would require Conscrypt as a hard dependency.

This commit updates the auto-configuration for more flexibility and now
allows the following deployments:

* JDK9+ with the JDK ALPN implementation
* JDK8u252+ with the backported ALPN implementation
* Conscrypt with no JDK requirement

The auto-configuration now improves detection and guides developers in
case there is a missing `jetty-alpn-*-server` dependency.

The reference docs in the HOWTO section has been updated accordingly.

Closes gh-22188
parent be32843d
......@@ -581,7 +581,7 @@ We recommend using `application.properties` to configure HTTPS, as the HTTP conn
[[howto-configure-http2]]
=== Configure HTTP/2
You can enable HTTP/2 support in your Spring Boot application with the configprop: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.
This support depends on the chosen web server and the application environment, since that protocol is not supported out-of-the-box by all JDK8 releases.
[NOTE]
====
......@@ -599,8 +599,12 @@ As of Undertow 1.4.0+, HTTP/2 is supported without any additional requirement on
[[howto-configure-http2-jetty]]
==== HTTP/2 with Jetty
As of Jetty 9.4.8, HTTP/2 is also supported with the https://www.conscrypt.org/[Conscrypt library].
To enable that support, your application needs to have two additional dependencies: `org.eclipse.jetty:jetty-alpn-conscrypt-server` and `org.eclipse.jetty.http2:http2-server`.
For HTTP/2 support, Jetty requires the additional `org.eclipse.jetty.http2:http2-server` dependency.
Now depending on your deployment, you also need to choose other dependencies:
* `org.eclipse.jetty:jetty-alpn-java-server` for applications running on JDK9+
* `org.eclipse.jetty:jetty-alpn-openjdk8-server` for applications running on JDK8u252+
* `org.eclipse.jetty:jetty-alpn-conscrypt-server` and the https://www.conscrypt.org/[Conscrypt library] with no JDK requirement
......
......@@ -96,10 +96,10 @@ class SslServerCustomizer implements JettyServerCustomizer {
if (this.http2 == null || !this.http2.isEnabled()) {
return createHttp11ServerConnector(server, config, sslContextFactory);
}
Assert.state(isAlpnPresent(),
() -> "The 'org.eclipse.jetty:jetty-alpn-server' dependency is required for HTTP/2 support.");
Assert.state(isConscryptPresent(), () -> "The 'org.eclipse.jetty.http2:http2-server' and Conscrypt "
+ "dependencies are required for HTTP/2 support.");
Assert.state(isJettyAlpnPresent(),
() -> "An 'org.eclipse.jetty:jetty-alpn-*-server' dependency is required for HTTP/2 support.");
Assert.state(isJettyHttp2Present(),
() -> "The 'org.eclipse.jetty.http2:http2-server' dependency is required for HTTP/2 support.");
return createHttp2ServerConnector(server, config, sslContextFactory);
}
......@@ -112,23 +112,40 @@ class SslServerCustomizer implements JettyServerCustomizer {
connectionFactory);
}
private boolean isAlpnPresent() {
return ClassUtils.isPresent("org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory", null);
private boolean isJettyAlpnPresent() {
return ClassUtils.isPresent("org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory", null);
}
private boolean isConscryptPresent() {
return ClassUtils.isPresent("org.conscrypt.Conscrypt", null);
private boolean isJettyHttp2Present() {
return ClassUtils.isPresent("org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory", null);
}
private ServerConnector createHttp2ServerConnector(Server server, HttpConfiguration config,
SslContextFactory.Server sslContextFactory) {
HttpConnectionFactory http = new HttpConnectionFactory(config);
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(config);
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
ALPNServerConnectionFactory alpn = createAlpnServerConnectionFactory();
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
if (isConscryptPresent()) {
sslContextFactory.setProvider("Conscrypt");
}
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
return new SslValidatingServerConnector(server, sslContextFactory, this.ssl.getKeyAlias(), ssl, alpn, h2,
new HttpConnectionFactory(config));
return new SslValidatingServerConnector(server, sslContextFactory, this.ssl.getKeyAlias(), ssl, alpn, h2, http);
}
private ALPNServerConnectionFactory createAlpnServerConnectionFactory() {
try {
return new ALPNServerConnectionFactory();
}
catch (IllegalStateException ex) {
throw new IllegalStateException(
"An 'org.eclipse.jetty:jetty-alpn-*-server' dependency is required for HTTP/2 support.", ex);
}
}
private boolean isConscryptPresent() {
return ClassUtils.isPresent("org.conscrypt.Conscrypt", null)
&& ClassUtils.isPresent("org.eclipse.jetty.alpn.conscrypt.server.ConscryptServerALPNProcessor", null);
}
/**
......@@ -225,9 +242,9 @@ class SslServerCustomizer implements JettyServerCustomizer {
*/
static class SslValidatingServerConnector extends ServerConnector {
private SslContextFactory sslContextFactory;
private final SslContextFactory sslContextFactory;
private String keyAlias;
private final String keyAlias;
SslValidatingServerConnector(Server server, SslContextFactory sslContextFactory, String keyAlias,
SslConnectionFactory sslConnectionFactory, HttpConnectionFactory connectionFactory) {
......
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