HTTP/2 Support in Helidon

Santiago Pericas-Geertsen
Helidon
Published in
3 min readOct 7, 2019

Helidon has had experimental support for HTTP/2 for about a year now, yet not many people know about this feature. HTTP/2 support can be enabled by simply tweaking your configuration and without the need to make any changes to your application code: Helidon will automatically detect HTTP/2 connections and make them look like regular HTTP/1.1 connections to your handlers — and this works for both Helidon SE and Helidon MP apps.

You can enable HTTP/2 support as follows:

server:
port: 8080
host: 0.0.0.0
experimental:
enable-http2: true
http2-max-content-length: 16384

Under experimental simply set enable-http2 to true and http2-max-content-length to an estimated maximum payload size in bytes (this is used in the process of mapping HTTP/2 requests to HTTP/1.1 requests). The default value for http2-max-content-length is 64 KB.

After enabling HTTP/2 support, you can easily test your application using curl by either starting a regular HTTP/1.1 connection and requesting an upgrade to HTTP/2 or by initiating an HTTP/2 connection directly, i.e. with prior knowledge of the server’s capabilities.

In what follows, we shall use the bookstore-se application that is part of the Helidon workspace. Let us start the application with HTTP/2 enabled (but SSL disabled, more on this later):

2019.10.03 10:46:38 INFO io.helidon.webserver.NettyWebServer Thread[main,5,main]: Version: 1.3.2-SNAPSHOT
2019.10.03 10:46:39 INFO io.helidon.webserver.NettyWebServer Thread[nioEventLoopGroup-2-1,10,main]: Channel '@default' started: [id: 0x50e4d7a4, L:/0:0:0:0:0:0:0:0:8080]
WEB server is up! http://localhost:8080/books [ssl=false, http2=true]

The following command issues an HTTP request that includes a connection upgrade to HTTP/2:

>> curl -v --http2 http://localhost:8080/books
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /books HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
>
< HTTP/1.1 101 Switching Protocols
< connection: upgrade
< upgrade: h2c
* Received 101
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< content-type: application/json
< date: Thu, 3 Oct 2019 10:52:33 -0400
< content-length: 2
<
* Connection #0 to host localhost left intact
[]

Note that the initial request is HTTP/1.1 but the response is HTTP/2, after the client and server were able to negotiate a connection upgrade. Once an upgrade is negotiated any further request-response interaction over the same connection would use the upgraded protocol, or HTTP/2 in this case.

The following command issues an HTTP/2 request with prior knowledge of the server’s capabilities:

>> curl -v --http2-prior-knowledge http://localhost:8080/books
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fee53804400)
> GET /books HTTP/2
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< content-type: application/json
< date: Thu, 3 Oct 2019 10:57:47 -0400
< x-http2-stream-weight: 16
< content-length: 2
<
* Connection #0 to host localhost left intact
[]

In this case, both the request and the response are in HTTP/2 and no protocol negotiation is necessary. Finally, you can also issue a regular HTTP/1.1 request on the same port (without an upgrade request) and obtain the same response as before the experimental HTTP/2 feature was enabled in your app.

HTTP/2 and TLS

In practice, most applications (e.g., Web browsers) that support HTTP/2 also use TLS to secure connections. Helidon PR #807 has more recently added support for TLS with HTTP/2.

Using TLS with HTTP/2 requires a compatible client, and the current version of curl does not have the necessary support. Readers interested in using TLS and HTTP/2 should stay tuned for a future story that will cover that (or review the changes in PR #807 for more information).

--

--