HTTP/2
is a modern binary duplex multiplexing protocol designed as a replacement for HTTP/1.x.
Jetty, Netty, and Tomcat engines provide HTTP/2 implementations that Ktor can use. However, there are significant differences, and each engine requires additional configuration. Once your host is configured properly for Ktor, HTTP/2 support will be activated automatically.
Key requirements:
SSL certificate (can be self-signed)
ALPN implementation suitable for a particular engine (see corresponding sections for Netty, Jetty, and Tomcat)
As per the specification, HTTP/2 does not require encryption, but all browsers will require encrypted connections to be used with HTTP/2. That’s why a working TLS environment is a prerequisite for enabling HTTP/2. Therefore, a certificate is required to enable encryption. For testing purposes, it can be generated with from the JDK:
The next step is configuring Ktor to use your keystore. See the example application.conf:
ktor {
deployment {
port = 8080
sslPort = 8443
watch = [ ]
}
application {
modules = [ com.example.ModuleKt.main ]
security {
ssl {
keyStore = /path/to/test.jks
keyAlias = testkey
keyStorePassword = changeit
}
}
}
ALPN implementation
HTTP/2 requires ALPN () to be enabled. Unfortunately, the JDK’s TLS implementation doesn’t have support for ALPN, so your application engine must be configured properly. The first option is to use an external ALPN implementation that needs to be added to the boot classpath. Another option is to use OpenSSL native bindings and precompiled native binaries. Both approaches are error-prone and require extra attention when being configured. Also, each particular engine can support only one of these methods.
Jetty supports the JDK ALPN extension, and to get it working you have to add an extra-dependency to the java boot classpath. It is very important to add it to the boot classpath, as adding it to a regular classpath doesn’t work.
The other issue is that the exact dependency version depends on the JDK version. For example, for JDK 8u144, alpn boot 8.1.11.v20170118 should be used (see https://www.eclipse.org/jetty/documentation/9.4.x/alpn-chapter.html#alpn-versions for the full compatibility list).
The following JVM options should be applied (the path can be relative):
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-jetty-alpn</id>
<goals>
</goals>
<configuration>
<includeArtifactIds>alpn-boot</includeArtifactIds>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
If all of the above is done properly, Jetty will log that ssl, alpn, and h2 are enabled:
The easiest way to enable HTTP/2 in Netty is to use OpenSSL bindings (). Add an API jar to dependencies:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<version>${tcnative.version}</version>
</dependency>
and then native implementation (statically linked BoringSSL library, a fork of OpenSSL):
where tc.native.classifier
should be one of the following: linux-x86_64
, or windows-x86_64
.
Once all dependencies have been provided, Ktor will enable HTTP/2 support on the SSL port.
Similar to Netty, to get HTTP/2 working in Tomcat you need native OpenSSL bindings. Unfortunately, Tomcat’s tcnative is not completely compatible with the Netty one. This is why you need a slightly different binary. You can get it here (https://tomcat.apache.org/native-doc/), or you can try Netty’s tcnative. However, you’ll have to guess which exact version is compatible with your specific Tomcat version.