The examples show how to run multiple requests over a single connection with HTTP/2’s multiplexing. Multiplexing is HTTP/2’s ability to handle multiple requests within one TCP connection independent of each other, so a blocked or stalled request or response does not prevent progress on other streams.
The example server takes GET requests and responds after 6 seconds delay. Each client sends three GET requests over a single connection. With HTTP/1 this would imply that the last response is received after 3*6=18 seconds. As the clients use HTTP/2, all requests are processed in parallel, so all three responses are received after 6 seconds.
The implementations exemplify the three most common HTTP/2 client libraries for Java developers.
The Jetty HTTP/2 client provides a low level API and a high level API.
As of now, the high level API seems still not very stable,
and I found it easier to use the low level API to implement the example.
The code is mostly copied from an example in the Javadoc for Jetty’s
To send the request, you have to create a HEADERS frame from a
template and send it in a new stream:
The response is received in the
responseListener callback. The
onData() method that is invoked when response data is received:
To create a request, you have to create an HTTP/1 request object. As the connection is an HTTP/2 connection, the request will be implicitly converted to HTTP/2 frames internally.
In order to receive the response, you have to implement a response handler and register it with the socket channel’s pipeline in the client’s bootstrap code:
HttpResponseHandler in Netty’s example code uses the stream ID
for mapping response messages to the corresponding
In order to do that, the implementation assumes that the stream ID of the first
request is 3, and the stream ID for each subsequent request is incremented by 2.
That’s an easy way to allow the
HttpResponseHandler to learn which
promise is associated with a response, but it means that the client needs
to keep track of the number of requests sent.
HttpResponseHandler implements a
messageReceived() callback that
is invoked when responses are received.
The OkHttp example uses a much more high level API than the two other examples:
Requests are created with a
Request.Builder, and sent by registering a
callback for the response.
Responses are handled in the callback’s
All three Java client libraries are able to re-use HTTP/2 connections for multiple requests, and to implement efficient multiplexing within the connection. As of now, OkHttp seems to have the most easy to use API. However, it should be easy to wrap the other two examples into a higher level API if needed.