jsr340-experts@servlet-spec.java.net

[jsr340-experts] Re: HTTP/2 Push Was: Server-Sent Events in Java EE 8

From: Mark Thomas <markt_at_apache.org>
Date: Thu, 07 Aug 2014 09:45:02 +0100

On 07/08/2014 07:26, Greg Wilkins wrote:
>
> All,
>
> We are at the stage where we need to play around with some http/2 push
> APIs in order to test the underlying mechanism. So it would be really
> good to get some feedback on some of these ideas below, as I'm a bit torn.
>
> Some background first....
>
> http/2 push is not general purpose pushing of messages from server to
> client like websocket is (or long polling). Rather it is a mechanism
> to push resources that are related to one that was fetched by a normal
> request.
>
> For example, when the server receives a request for /index.html it may
> decide that for minimum round trips that along with index.html response,
> it should push favicon.ico, logo.png, mysite.css and jquery.js. It does
> this by including a push promise frame for each of those associated
> resources in the response stream to /index.html. Each push promise
> contains a fake request (method, uri and fields) to which the push
> resource will pretend to be a response to, plus the stream id of the new
> stream on which that response will be sent.
>
> Clients receiving a push promise can decide that they already have the
> resource (or don't need it) and reset the new stream, or they can accept
> the new streams data and typically use it to populate their cache. So
> essentially http2 push is a way for a server to preload a clients cache.
>
>
> So an API for this could be put on the ServletResponse something like:
>
> doGet(ServletRequest request, ServletResponse response)
> {
> response.push("/jquery.js");
> response.push("/css/mysite.css");
> response.push("/images/logo.png");
> ...
> }
>
> This is good because it means we can use the response state to do an
> illegalStateException if the response is not in a state where a push
> promise can be sent (eg already closed).
>
> However, to be consistent with other API, the path passed would have to
> be relative to the current context. This means that you can't push
> resources from another context.
>
> Another slight issue, is that there is no scope to adjust the fake
> request, as you might like to add a Cookie or other header to reflect
> some state that has changed in the processing of the original request.
>
>
> So the alternative is to put the API on a request dispatcher:
>
> doGet(ServletRequest request, ServletResponse response)
> {
>
> getServletContext().getRequestDispatcher("/jquery.js").push(request,response);
>
> getServletContext().getRequestDispatcher("/css/mysite.css").push(request,response);
>
> getServletContext().getRequestDispatcher("/images/logo.png").push(request,response);
> ...
> }
>
> this is a little more verbose, but the dispatchers could be obtain ahead
> of time in init. The request object is passed, so it can be wrapped to
> add extra fields if need be. The response is there as that is where the
> push promise will be sent, so it's state needs to be checked. Note that
> it is not the response the pushed resource itself will go on, so
> wrapping the response object will not achieve anything.
> You can of course get request dispatchers from other contexts if you
> really really want to do cross context push.
>
>
>
> thoughts?

This is my initial impression based purely on what you have written
(still far too much other stuff on my plate to find time to look into
this properly at the moment).

If we go with the simple request.push() then I think users are going to
start raising the issues you highlighted - particularly the
cross-context push - quite quickly. Therefore it looks to me that the
RequestDispatcher option is the better one.

Mark