Implementing HTTP/2 push in Java

This is another guest post by my friend Tobi. —Jörn

The story:

Some months ago I started to play around with HTTP/2 and wondered what should get better with this piece of technology, where are the limitations and pitfalls. So I first went to Wikipedia and read the Wikipedia article about HTTP/2 and the RFC 7540 standard. I was quite impressed about the idea to reduce the latency of web pages.

Because I am familiar with JEE development I just had a look at how to integrate this technology in an existing JEE application and read about PushBuilder API. Cool – a Java API which handles to push resources before the actual response is submitted to the client. I thought this sounds good and build up my first application with it.

First I tried to configure tomcat with SSL and HTTP/2, but I failed sadly as you can read within this mailing list topic Apache Tomcat 9.0.0-M4 and http/2 on Mac OS X 10.11.4 (If you have any hints what I did wrong please let me know!). Then I tried it by configure a Jetty Servlet Container which was a great straight forward implementation as you can see in this Sample.

Ok the first implementation was made.

Then I had a look into the console of my browser and saw the resources are pushed all the time and I thought this might cause a big impact on the network traffic which outweighs the latency benefit. So I posted a question at stackoverflow about “Jetty respond with status 200 instead of 304 while using http2” and happily Martin Grigorov (Tomcat Committer) and Simone Bordet (Jetty core developer) helped me within this question and a corresponding issue ticket jetty.project issues 801 to understand that it is up to the developer when a resource should be pushed and when the browser should use the cache. One sentence I want to quote: “I think there is a misunderstanding of what the push APIs do. Right now, they just push.”

By consolidating those new information I came up with a new Implementation for Apache Wicket to handle HTTP/2 push very easily. You can find the implementation in the corresponding PushHeaderItem class in the wicket git repository

Here are some facts / pitfalls that you should consider when using HTTP/2 push:

  1. Think about when should resources be pushed and when it makes more sense to get them out of the browser cache with a minor “overhead request” – depending on this you have to build up your own implementation
  2. Some browsers like Chrome do not cache resources if the SSL cert is self signed – consider this if you check the caching behavior of your implementation
  3. Try to implement your push API docile so that the browser can also use HTTP/1 and get the resources in a normal way as fallback
  4. You can check the push behavior of your implementation / example application. Chrome example: chrome://net-internals/#http2

Conclusion:

When using HTTP/2 and PushBuilder API you have to think about a lot of marginal conditions like Caching, SSL implementations, traffic impact to find a good solution that does exactly what you want.

-Tobi