W3C home > Mailing lists > Public > whatwg@whatwg.org > February 2015

[whatwg] HTTP/2 push detection and control in JavaScript

From: Brendan Long <self@brendanlong.com>
Date: Fri, 20 Feb 2015 11:48:40 +0100
Message-Id: <066ED65A-0D8A-4805-B0AB-4AFCDE2E43F6@brendanlong.com>
To: whatwg@whatwg.org
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
Received on Friday, 20 February 2015 10:49:14 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 17:00:27 UTC