I was playing with Vert.x’s excellent HTTP/2 functionality with the aim of determining how difficult it’d be to add support into apiman's Vert.x gateway implementation (which is still somewhat of a tech preview, but it’s finally getting some love). Many HTTP/2 clients don’t support non-TLS connections, so transport security is a de facto requirement in the real-world usage (particularly with browsers).
There’s already an example in the Vert.x core-examples
repository demonstrating how to set up and use HTTP/2. However, when using a keystore in JKS format, Vert.x (in v3.3.2, at least) tries to use Jetty’s alpn-boot
ALPN implementation rather than OpenSSL.
A few simple steps…
So, here’s how to go about making it work:
-
Download the version of
apln-boot
corresponding to your version of Java. The binaries are available on Maven Central, or you can build your own if you prefer. -
When launching your verticle, put
alpn-boot
on the JVM’s boot classpath; it’s altering core library functionality and needs to be available early. There are a few ways to do this, here’s the easiest one:$ JAVA_OPTS=-Xbootclasspath/p:<path-to-apln-boot.jar> vertx run Example.java
If you’re using an IDE you should add
-Xbootclasspath/p:<path-to-apln-boot.jar>
to the VM Arguments of your run configuration. -
Set
setUseAlpn(true)
on yourHttpServerOptions
.
Testing it out
Here’s some code to test it with.
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.JksOptions;
public class Example extends AbstractVerticle {
@Override
public void start() throws Exception {
HttpServer server =
vertx.createHttpServer(new HttpServerOptions()
.setUseAlpn(true)
.setSsl(true)
.setKeyStoreOptions(
new JksOptions()
.setPath(<Path to your JKS>)
.setPassword(<The JKS password>)
)
);
server.requestHandler(req -> {
req.response().putHeader("Content-Type", "text/plain")
.end("Greetings, Earthicans!\n");
}).listen(8443);
}
}
You’ll likely want to check that it’s really working. I’ve been using cURL
compiled with nghttp2
to enable HTTP/2 support; depending on your OS or distro, the shipping version may have been built with it. If you’re using OS X, you can use brew install curl --with-nghttp2
. [1]
$ curl -k -v --http2 https://localhost:8443/
* Trying ::1...
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /usr/local/etc/openssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=lo; ST=localhost; L=localhost; O=localhost; OU=localhost; CN=localhost
* start date: Aug 20 15:23:02 2016 GMT
* expire date: Nov 18 15:23:02 2016 GMT
* issuer: C=lo; ST=localhost; L=localhost; O=localhost; OU=localhost; CN=localhost
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* TCP_NODELAY set
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fb8aa008800)
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.50.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< content-type: text/plain
< content-length: 22
<
* Connection #0 to host localhost left intact
Greetings, Earthicans!
Hooray!
Vert.x really is a gratifyingly well-thought-out and easy-to-use.