Server-Side HTTP/2 (Preview)

Warning

Server-Side HTTP/2 support in akka-http is currently available as a preview. This means it is ready to be evaluated, but the APIs and behavior are likely to change.

Enable HTTP/2 support

To enabled HTTP/2 support akka-http2-support must be added as a dependency:

sbt
libraryDependencies += "com.typesafe.akka" %% "akka-http2-support" % "10.0.15"
Gradle
dependencies {
  compile group: 'com.typesafe.akka', name: 'akka-http2-support_2.12', version: '10.0.15'
}
Maven
<dependency>
  <groupId>com.typesafe.akka</groupId>
  <artifactId>akka-http2-support_2.12</artifactId>
  <version>10.0.15</version>
</dependency>

HTTP/2 can then be enabled through configuration:

akka.http.server.preview.enable-http2 = on

Use bindAndHandleAsync and HTTPS

Only secure HTTP/2 (also known as “over HTTPS” or “with TLS”) connections are supported as this is the prime mode of operation for this protocol. While un-encrypted connections are allowed by HTTP/2, clients that support this are rare. See the HTTPS section for how to set up HTTPS.

You can use Http().bindAndHandleAsync as long as you followed the above steps:

Scala
import akka.http.scaladsl.Http

  Http().bindAndHandleAsync(asyncHandler, interface = "localhost", port = 8443, httpsServerContext)
Java
import akka.http.javadsl.Http;
import static akka.http.javadsl.ConnectHttp.toHostHttps;

    Http.get(system)
      .bindAndHandleAsync(
        asyncHandler,
        toHostHttps("127.0.0.1", 8443).withCustomHttpsContext(httpsConnectionContext),
        materializer);

Note that bindAndHandle currently does not support HTTP/2, you must use bindAndHandleAsync.

Testing with cURL

At this point you should be able to connect, but HTTP/2 may still not be available.

You’ll need a recent version of cURL compiled with HTTP/2 support (for OSX see this article). You can check whether your version supports HTTP2 with curl --version, look for the nghttp2 extension and the HTTP2 feature:

curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2l zlib/1.2.8 libidn2/0.16 libpsl/0.17.0 (+libidn2/0.16) libssh2/1.8.0 nghttp2/1.23.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

When you connect to your service you may now see something like:

$ curl -k -v https://localhost:8443
(...)
* ALPN, offering h2
* ALPN, offering http/1.1
(...)
* ALPN, server accepted to use h2
(...)
> GET / HTTP/1.1
(...)
< HTTP/2 200
(...)

If your curl output looks like above, you have successfully configured HTTP/2. However, on JDKs up to version 9, it is likely to look like this instead:

$ curl -k -v https://localhost:8443
(...)
* ALPN, offering h2
* ALPN, offering http/1.1
(...)
* ALPN, server did not agree to a protocol
(...)
> GET / HTTP/1.1
(...)
< HTTP/1.1 200 OK
(...)

This shows curl declaring it is ready to speak h2 (the shorthand name of HTTP/2), but could not determine whether the server is ready to, so it fell back to HTTP/1.1. To make this negotiation work you’ll have to configure ALPN as described below.

Application-Layer Protocol Negotiation (ALPN)

Application-Layer Protocol Negotiation (ALPN) is used to negotiate whether both client and server support HTTP/2.

ALPN support comes with the JVM starting from version 9. If you’re on a previous version of the JVM, you’ll have to load a Java Agent to provide this functionality. We recommend the agent from the Jetty project, jetty-alpn-agent.

manually

This agent can be loaded with the JVM option -javaagent:/path/to/jetty-alpn-agent-2.0.6.jar.

  java -javaagent:/path/to/jetty-alpn-agent-2.0.6.jar -jar app.jar

sbt

sbt can be configured to load the agent with the sbt-javaagent plugin:

  .enablePlugins(JavaAgent)
  .settings(
    javaAgents += "org.mortbay.jetty.alpn" % "jetty-alpn-agent" % "2.0.6" % "runtime"
  )

This should automatically load the agent when running, testing, or even in distributions made with sbt-native-package.

The source code for this page can be found here.