Support http/2 configuration with Reactor-Netty
Just like Jetty, Reactor Netty supports ALPN with JDK8 or with a dependency that delegates TLS to a native library using boringSSL. Closes gh-13333
This commit is contained in:
parent
c98bb40136
commit
dd79143d1a
|
@ -133,6 +133,7 @@
|
|||
<nekohtml.version>1.9.22</nekohtml.version>
|
||||
<neo4j-ogm.version>3.1.0</neo4j-ogm.version>
|
||||
<netty.version>4.1.27.Final</netty.version>
|
||||
<netty-tcnative.version>2.0.12.Final</netty-tcnative.version>
|
||||
<nio-multipart-parser.version>1.1.0</nio-multipart-parser.version>
|
||||
<postgresql.version>42.2.4</postgresql.version>
|
||||
<quartz.version>2.3.0</quartz.version>
|
||||
|
@ -924,6 +925,11 @@
|
|||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${netty-tcnative.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
|
|
|
@ -753,6 +753,22 @@ This error is not fatal, and the application still starts with HTTP/1.1 SSL supp
|
|||
|
||||
|
||||
|
||||
[[howto-configure-http2-netty]]
|
||||
==== HTTP/2 with Reactor Netty
|
||||
The `spring-boot-webflux-starter` is using by default Reactor Netty as a server.
|
||||
Reactor Netty can be configured for HTTP/2 using the JDK support with JDK 9 or later.
|
||||
For JDK 8 environments, or for optimal runtime performance, this server also supports
|
||||
HTTP/2 with native libraries. To enable that, your application needs to have an
|
||||
additional dependency.
|
||||
|
||||
Spring Boot manages the version for the
|
||||
`io.netty:netty-tcnative-boringssl-static` "uber jar", containing native libraries for
|
||||
all platforms. Developers can choose to import only the required dependendencies using
|
||||
a classifier (see http://netty.io/wiki/forked-tomcat-native.html[the Netty official
|
||||
documentation]).
|
||||
|
||||
|
||||
|
||||
[[howto-configure-webserver]]
|
||||
=== Configure the Web Server
|
||||
|
||||
|
|
|
@ -76,6 +76,11 @@
|
|||
<artifactId>reactor-netty</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
|
@ -373,6 +378,21 @@
|
|||
<artifactId>jaybird-jdk18</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-http-client-transport</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.netty.http.HttpProtocol;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
|
||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
||||
|
@ -110,10 +111,10 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
|
|||
|
||||
private HttpServer createHttpServer() {
|
||||
HttpServer server = HttpServer.create().tcpConfiguration(
|
||||
(tcpServer) -> tcpServer.addressSupplier(() -> getListenAddress()));
|
||||
(tcpServer) -> tcpServer.addressSupplier(this::getListenAddress));
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(getSsl(),
|
||||
getSslStoreProvider());
|
||||
getHttp2(), getSslStoreProvider());
|
||||
server = sslServerCustomizer.apply(server);
|
||||
}
|
||||
if (getCompression() != null && getCompression().getEnabled()) {
|
||||
|
@ -121,10 +122,23 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
|
|||
getCompression());
|
||||
server = compressionCustomizer.apply(server);
|
||||
}
|
||||
server = server.protocol(listProtocols());
|
||||
server = (this.useForwardHeaders ? server.forwarded() : server.noForwarded());
|
||||
return applyCustomizers(server);
|
||||
}
|
||||
|
||||
private HttpProtocol[] listProtocols() {
|
||||
if (getHttp2() != null && getHttp2().isEnabled()) {
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
return new HttpProtocol[] { HttpProtocol.H2, HttpProtocol.HTTP11 };
|
||||
}
|
||||
else {
|
||||
return new HttpProtocol[] { HttpProtocol.H2C, HttpProtocol.HTTP11 };
|
||||
}
|
||||
}
|
||||
return new HttpProtocol[] { HttpProtocol.HTTP11 };
|
||||
}
|
||||
|
||||
private InetSocketAddress getListenAddress() {
|
||||
if (getAddress() != null) {
|
||||
return new InetSocketAddress(getAddress().getHostAddress(), getPort());
|
||||
|
|
|
@ -26,8 +26,9 @@ import javax.net.ssl.TrustManagerFactory;
|
|||
import io.netty.handler.ssl.ClientAuth;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
import reactor.netty.tcp.SslProvider.DefaultConfigurationType;
|
||||
import reactor.netty.tcp.SslProvider;
|
||||
|
||||
import org.springframework.boot.web.server.Http2;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
import org.springframework.boot.web.server.SslStoreProvider;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
@ -42,19 +43,26 @@ public class SslServerCustomizer implements NettyServerCustomizer {
|
|||
|
||||
private final Ssl ssl;
|
||||
|
||||
private final Http2 http2;
|
||||
|
||||
private final SslStoreProvider sslStoreProvider;
|
||||
|
||||
public SslServerCustomizer(Ssl ssl, SslStoreProvider sslStoreProvider) {
|
||||
public SslServerCustomizer(Ssl ssl, Http2 http2, SslStoreProvider sslStoreProvider) {
|
||||
this.ssl = ssl;
|
||||
this.http2 = http2;
|
||||
this.sslStoreProvider = sslStoreProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServer apply(HttpServer server) {
|
||||
try {
|
||||
return server
|
||||
.secure((contextSpec) -> contextSpec.sslContext(getContextBuilder())
|
||||
.defaultConfiguration(DefaultConfigurationType.NONE));
|
||||
return server.secure((contextSpec) -> {
|
||||
SslProvider.DefaultConfigurationSpec spec = contextSpec
|
||||
.sslContext(getContextBuilder());
|
||||
if (this.http2 != null && this.http2.isEnabled()) {
|
||||
spec.defaultConfiguration(SslProvider.DefaultConfigurationType.H2);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
|
|
Loading…
Reference in New Issue