Hi,

I’m wondering if there is any work in progress to define an API for JavaScript 
clients to detect that an HTTP/2 server has pushed content, and to control the 
“half closed” vs “closed” state of HTTP/2 streams (to control whether or not a 
server can push content).

Use Case

The use-case I have in mind is MPEG DASH or HLS live streaming:

A server updates the manifest (MPD or m3u8) and pushes it. The client browser 
will cache it, but JavaScript applications don’t know that it exists. For newly 
generated segments, we need the MPD to use them anyway, but for adaptive 
streaming we need to know when the request started and when it finished so we 
can estimate bandwidth. If a server is pushing MPD updates, we want a way to 
tell it to stop (RST_STREAM on a pushed stream to end the transfer, or 
RST_STREAM on the original client request to prevent future pushes for that 
request).

The obvious question to ask is “why not just poll the server”? The answer its 
that live streaming latency depends (among other things) on how quickly you 
poll. Unless you can perfectly predict when the server will have an update 
available, you need to either poll slightly late (introducing latency) or poll 
significantly more often than the server creates updates. Using server push is 
equivalent to to polling infinitely fast, while simultaneously reducing load on 
the server by making fewer requests (win/win).

I imagine that this would be useful for JavaScript implementations of HTTP/2 
REST API’s, especially API’s using something like ATOM or RSS. Firefox has an 
API for addons to detect pushed streams, so presumably they think there is some 
use for this (but they didn’t propose this as a public API, so maybe not?).

Solution

I’m not really concerned with how this is solved, but an example would be to 
add to XMLHTTPRequest:

interface XMLHttpRequestEventTarget : EventTarget {
  // event handlers
  attribute EventHandler onloadstart;
  attribute EventHandler onprogress;
  attribute EventHandler onabort;
  attribute EventHandler onerror;
  attribute EventHandler onload;
  attribute EventHandler ontimeout;
  attribute EventHandler onloadend;
  attribute EventHandler onpush;
};

enum XMLHttpRequestLeaveRequestOpenType {
  “true”,
  “false”,
  “no-preference"
};

interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // most of this interface left out for readability

  void open(ByteString method, USVString url, boolean async, optional 
USVString? username = null, optional USVString? password = null, optional 
XMLHttpRequestLeaveRequestOpenType leaveRequestOpen = “no-preference");

  void abort(); // can already be used to fully close client request stream
};

interface XMLHttpPushResponse {
  // event handlers
  attribute EventHandler onprogress;
  attribute EventHandler onabort;
  attribute EventHandler onerror;
  attribute EventHandler onload;
  attribute EventHandler ontimeout;
  attribute EventHandler onloadend;

  void abort();

  // response
  readonly attribute USVString responseURL;
  readonly attribute unsigned short status;
  readonly attribute ByteString statusText;
  ByteString? getResponseHeader(ByteString name);
  ByteString getAllResponseHeaders();
  void overrideMimeType(DOMString mime);
           attribute XMLHttpRequestResponseType responseType;
  readonly attribute any response;
  readonly attribute USVString responseText;
  [Exposed=Window] readonly attribute Document? responseXML;
}

interface XMLHttpRequestPushEvent : Event {
  attribute XMLHttpPushResponse response;
};

And then we’d need some text to say:

If leaveRequestOpen is “true” and the request was made over HTTP/2, the user 
agent should not fully close the request stream until XMLHttpRequest is garbage 
collected or abort() is called on it. If it is “false”, the user agent must 
immediately close the HTTP/2 stream after receiving a complete response.

If a user agent receives a PUSH_PROMISE on the HTTP/2 stream for an 
XMLHttpRequest, it must create an XMLHttpPushResponse, attach it to a 
XMLHttpRequestPushEvent, and fire it for XMLHttpRequestEventTarget.onpush.

XMLHttpPushResponse's attributes and methods all have identical semantics to 
the versions on XMLHttpRequest.

Thoughts?

Brendan Long

Reply via email to