As promised on my last post on HTTP/2, we have implemented and deployed the HTTP/2 Push functionality on this very website, webtide.com. For the other HTTP/2 implementers out there, if you request
"/" on webtide.com, you will get
"/wp-includes/js/jquery/jquery.js" pushed. We have already implemented SPDY Push in the past, but this time we wanted to go a step further and implement HTTP/2 Push in the context of an experimental Servlet API that applications can use to decide what to resources needs to be pushed.
The experimental Servlet API (designed by @gregwilkins) is very simple and would consist of only one additional method in
public interface RequestDispatcher
public void push(ServletRequest request);
An application receiving a request for a primary resource, say
index.html, would identify what secondary resources it would like to push along with the primary resource. For each secondary resource, the application would obtain a
RequestDispatcher, and then call
push() on it, passing the primary resource request:
public class MyServlet extends HttpServlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
String uri = request.getRequestURI();
String resourceToPush = "/js/jquery.js";
RequestDispatcher dispatcher =
Browsers, on the other hand, are in a much better position to identify secondary resources belonging to a primary resource, when they parse the primary resource. It would be great if browsers could request those resources with a special HTTP header that marks the secondary resource request as associated to the primary resource. Not only, it would be great if this could be completely automated, so that applications need not to worry about primary and secondary resources.
This is exactly what we have done in
PushCacheFilter. We have implemented a strategy where the
Referer header is being used to associate secondary resources to primary resources. With this association information, the filter builds a cache where secondary resources are linked to a primary resource, and every time a primary resource is being requested, we push also the associated secondary resources.
PushCacheFilter looks for the resource being requested; if it is not known to the filter, it assumes it is a primary resource and assigns a timestamp to it. Then it “opens” a window of – by default – 2000 ms where other requests may arrive; if these other requests have the former request as referrer, then these are secondary resources associated to the primary resource. The next time that the primary resource is requested, the filter knows about it, and pushes its secondary resources via the experimental Servlet API discussed above.
We have kept the filter intentionally simple to foster discussion about what strategies could be more useful, and what features would be needed, for example:
- Would browsers use a special header (not the
Refererheader) to mark the a resource as associated to another resource ?
- How would be possible to evict entries from the push cache without manual intervention ?
- Is there a relationship between the cacheability of the primary resource and that of the secondary resources that we can leverage ?
- How can a browser tell the server to not push a resource that it is already in the browser’s cache ?
We encourage anyone that is interested to join the Jetty mailing lists and contribute to the discussion.