Subject: Specifying Range in Link preload header for HTTP/2 Push?

From: Roger Pantos <[email-masked]>
Date: Tue, 09 Jul 2019 09:55:47 -0700

Greetings HTTP experts,

I’m interested in employing HTTP/2 Push of Range requests for media streaming. It seems like the core h2 protocol handles this well enough; the PUSH_PROMISE can contain a Range header, and at the very least if that ends up in the client push cache then a request for that exact Range should match.

That being said, I’d also like to signal the push request to downstream HTTP caches. Push is typically signaled via the Link header with rel=preload, but https://www.w3.org/TR/preload/ doesn’t seem to define signaling and associated Range.

Has anyone defined a Link extension to signal an associated Range?

If not, would anyone object to the following Link extension?

range-link-extension = “range” = ranges-specifier

where ranges-specifier is defined in RFC 2616.

An example would be:

Link: </media.mp4>; rel=preload; as=video; type=video/mp4; range=1380-14226

thanks,

Roger Pantos
Apple Inc.

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 10 Jul 2019 00:03:11 +0100

Hi Roger,

On Tue, 9 Jul 2019, 21:36 Roger Pantos, <[email-masked]> wrote:

> Greetings HTTP experts,
>
> I’m interested in employing HTTP/2 Push of Range requests for media
> streaming. It seems like the core h2 protocol handles this well enough; the
> PUSH_PROMISE can contain a Range header, and at the very least if that ends
> up in the client push cache then a request for that exact Range should
> match.
>
> That being said, I’d also like to signal the push request to downstream
> HTTP caches. Push is typically signaled via the Link header with
> rel=preload, but https://www.w3.org/TR/preload/ doesn’t seem to define
> signaling and associated Range.
>

I've spoken informally to some people on related topics. I presume this is
related to Apple's LHLS? Or in lay speak, one approach to low-latency
HTTP-based streaming. It'd be great to have a reference to cite when
talking around the topic.

> Link: </media.mp4>; rel=preload; as=video; type=video/mp4; range=1380-14226

The general impression I've observed is that such a range signal in Link
would be useful to a number of services, and that there would be benefit in
adopting a common signal.

Furthermore, while the use of server push might have debatable benefits for
the web browsing use case. I'm led to believe that it has affirmative uses
in this streaming model. Again, some evidential data would be really
interesting.

Finally, server push and caching is an interesting area that might benefit
from some more information. Some of the WG might be interested in how this
gets implemented in your use case.

Cheers
Lucas

---

From: Roger Pantos <[email-masked]>
Date: Tue, 09 Jul 2019 18:05:54 -0700

> On Jul 9, 2019, at 4:03 PM, Lucas Pardue <[email-masked]> wrote:
> 
> Hi Roger,
> 
> On Tue, 9 Jul 2019, 21:36 Roger Pantos, <[email-masked] <mailto:[email-masked]>> wrote:
> Greetings HTTP experts,
> 
> That being said, I’d also like to signal the push request to downstream HTTP caches. Push is typically signaled via the Link header with rel=preload, but https://www.w3.org/TR/preload/ <https://www.w3.org/TR/preload/> doesn’t seem to define signaling and associated Range.
> 
> I've spoken informally to some people on related topics. I presume this is related to Apple's LHLS? Or in lay speak, one approach to low-latency HTTP-based streaming. It'd be great to have a reference to cite when talking around the topic.

That’s right. Here’s a link to the current white paper: https://developer.apple.com/documentation/http_live_streaming/protocol_extension_for_low-latency_hls_preliminary_specification

> The general impression I've observed is that such a range signal in Link would be useful to a number of services, and that there would be benefit in adopting a common signal.
> 
> Furthermore, while the use of server push might have debatable benefits for the web browsing use case. I'm led to believe that it has affirmative uses in this streaming model. Again, some evidential data would be really interesting. 

The use of Push in our LL-HLS design eliminates one round trip per (partial) media segment downloaded. We’ve got data that shows round trip times to media servers can exceed 100 (or even 200) ms, particularly on cellular networks, even in the U.S. 

When playing at very low delay-from-live (2s or less), the client can only buffer around 1s ahead of the playhead (because that’s all there is). New segments must be loaded in a timely fashion to prevent playback from stalling. Speeding that up by 10% of the overall budget is a significant win. 

In addition, keeping the TCP send pipe full improves lost-packet recovery performance of the primary resource that accompanies the push (via fast retransmit).

> 
> Finally, server push and caching is an interesting area that might benefit from some more information. Some of the WG might be interested in how this gets implemented in your use case.

Certainly. I’d be happy to answer as I’m able to.

If there’s nothing currently defined, what would be the next step? To write an Internet-Draft specifying the Link extension?

(I’m also interested in a way for a server to indicate that pushed resources are to be strictly ordered (such as via a dependency tree). Today, multiple pushes get multiplexed at the default priority. But that’s a different discussion.)

Roger.

---

From: Roger Pantos <[email-masked]>
Date: Tue, 09 Jul 2019 20:21:01 -0700

> On Jul 9, 2019, at 7:01 PM, Leif Hedstrom <[email-masked]> wrote:
> 
> 
> 
> On Jul 9, 2019, at 19:05, Roger Pantos <[email-masked] <mailto:[email-masked]>> wrote:
> 
>> 
>> 
>>> On Jul 9, 2019, at 4:03 PM, Lucas Pardue <[email-masked] <mailto:[email-masked]>> wrote:
>>> 
>>> Hi Roger,
>>> 
>> That’s right. Here’s a link to the current white paper: https://developer.apple.com/documentation/http_live_streaming/protocol_extension_for_low-latency_hls_preliminary_specification <https://developer.apple.com/documentation/http_live_streaming/protocol_extension_for_low-latency_hls_preliminary_specification>
>> 
>>>  
> FWIW, server push sort of dictates that you can write the object to cache if I recall.

Absolutely. That’s what we want.

> 
> That much said, caching partial objects can be tricky at best. Do you treat each range as a unique object ?

That’s the simplest approach, and it should work pretty well for LL-HLS. From a cache point of view it’s effectively the same as the non-byterange case, where each partial segment has its own URL.

> If so, how do you avoid an explosion in various range sizes?

There shouldn’t be much of an explosion. The byte ranges pushed are determined by the origin, and there won’t be more than about 20 per URL. So it hopefully won’t hurt cache search performance too much.

> If you try to combine partial objects into one larger object,  the cache code tend to get tricky (we gave up in ATS).
> 
> This is probably something worthwhile discussing to understand the implications both on servers and clients. It’s non trivial, but definitely interesting!

Agreed,

Roger.

> Cheers,
> — Leif

---

From: Bence Béky <[email-masked]>
Date: Wed, 10 Jul 2019 08:10:40 -0400

Hi,

FYI I worked on this in Chrome a little more about a year ago, aiming
to do something simple, with no particular use case in mind.
Currently range request pushes are accepted, but matched with requests
only if the range matches exactly.  Caching in this case is trivial.
I imagine this would be relatively easy to implement in other clients
as well.

If you could work some client side JS magic to issue requests with the
same range that the server has pushed, it would work with Chrome
today.  The only caveat is that Chrome only allows one pushed stream
with any given URL, so you wouldn't be able to push the second range
for the same resource until the first one is matched by a request,
which of course the server has no insight into seeing when it happens.
I imagine other client might have a similar restriction.  In fact,
about 40% of incoming pushes are rejected as duplicate URL, indicating
that many servers are pushing the same request repeatedly on a single
connection, therefore rejecting such pushes seems like a necessary
optimization to avoid wasting downlink.

Cheers,

Bence

On Tue, Jul 9, 2019 at 11:26 PM Roger Pantos <[email-masked]> wrote:
> On Jul 9, 2019, at 19:05, Roger Pantos <[email-masked]> wrote:
>
>
>

---

From: Roger Pantos <[email-masked]>
Date: Wed, 10 Jul 2019 09:30:16 -0700

> On Jul 10, 2019, at 5:10 AM, Bence Béky <[email-masked]> wrote:
> 
> Hi,
> 

> I imagine this would be relatively easy to implement in other clients

Hi Bence. Thanks for the additional detail.

> today.  

That will be the case in LL-HLS. The primary resource (that triggers the push) is actually the active manifest. It contains the URI and byte range of the pushed resource. Upon receiving the manifest update the client will request that specific range.

> The only caveat is that Chrome only allows one pushed stream

That should be workable.

> optimization to avoid wasting downlink.

Agreed, but that shouldn’t happen with LL-HLS. The client affirmatively asks for the push at the application layer (via a query parameter on the manifest request). It will only ask if it needs the media resource. 

thanks,

Roger.

---

From: Yoav Weiss <[email-masked]>
Date: Wed, 10 Jul 2019 22:57:58 +0200

Hey Roger,

If the goal is to extend preload (e.g. with a new attribute), I believe the
best route would be to open an issue on the preload repo
<https://github.com/w3c/preload/issues> with your use-case and we can
discuss it further there. I also believe that such an attribute would be
considered an extension attribute
<https://tools.ietf.org/html/rfc8288#section-3.4.2> from a WebLinking
perspective, but I may be wrong on that front.

Regarding such an attribute, have you considered what would be its impact
on the browser itself? Should the browser use that range for the request as
well? (assuming the header doesn't get stripped off by the server)

Cheers,
Yoav

On Wed, Jul 10, 2019 at 6:34 PM Roger Pantos <[email-masked]> wrote:

> That will be the case in LL-HLS. The primary resource (that triggers the
> push) is actually the active manifest. It contains the URI and byte range
> of the pushed resource. Upon receiving the manifest update the client will
> request that specific range.
>
> Agreed, but that shouldn’t happen with LL-HLS. The client affirmatively
> asks for the push at the application layer (via a query parameter on the
> manifest request). It will only ask if it needs the media resource.
>
>
> thanks,
>
> Roger.
>
> >
> > Cheers,
> >
> > Bence
> >
> >
> >>> That being said, I’d also like to signal the push request to
> downstream HTTP caches. Push is typically signaled via the Link header with
> >> I've spoken informally to some people on related topics. I presume this
> is related to Apple's LHLS? Or in lay speak, one approach to low-latency
> >> That’s right. Here’s a link to the current white paper:
> https://developer.apple.com/documentation/http_live_streaming/protocol_extension_for_low-latency_hls_preliminary_specification
> >>
> >>
> >>>
> >> The general impression I've observed is that such a range signal in
> Link would be useful to a number of services, and that there would be
> benefit in adopting a common signal.
> >>
> >> Furthermore, while the use of server push might have debatable benefits
> for the web browsing use case. I'm led to believe that it has affirmative
> uses in this streaming model. Again, some evidential data would be really
> interesting.
> >>
> >>
> >> The use of Push in our LL-HLS design eliminates one round trip per
> (partial) media segment downloaded. We’ve got data that shows round trip
> times to media servers can exceed 100 (or even 200) ms, particularly on
> cellular networks, even in the U.S.
> >>
> >> When playing at very low delay-from-live (2s or less), the client can
> only buffer around 1s ahead of the playhead (because that’s all there is).
> New segments must be loaded in a timely fashion to prevent playback from
> stalling. Speeding that up by 10% of the overall budget is a significant
> win.
> >>
> >> In addition, keeping the TCP send pipe full improves lost-packet
> recovery performance of the primary resource that accompanies the push (via
> fast retransmit).
> >>
> >>
> >> Finally, server push and caching is an interesting area that might
> benefit from some more information. Some of the WG might be interested in
> how this gets implemented in your use case.
> >>
> >>
> >> That’s the simplest approach, and it should work pretty well for
> LL-HLS. From a cache point of view it’s effectively the same as the
> non-byterange case, where each partial segment has its own URL.
> >>
> >> There shouldn’t be much of an explosion. The byte ranges pushed are
> determined by the origin, and there won’t be more than about 20 per URL. So
> it hopefully won’t hurt cache search performance too much.
> >>
> >> If you try to combine partial objects into one larger object,  the
> cache code tend to get tricky (we gave up in ATS).
> >>
> >> This is probably something worthwhile discussing to understand the
> implications both on servers and clients. It’s non trivial, but definitely
> interesting!
> >>
> >>
> >> Agreed,
> >>
> >>
> >> Roger.
> >>
> >>
> >> Cheers,
> >>
> >> — Leif
> >>
> >>
> >> If there’s nothing currently defined, what would be the next step? To
> write an Internet-Draft specifying the Link extension?
> >>
> >> (I’m also interested in a way for a server to indicate that pushed
> resources are to be strictly ordered (such as via a dependency tree).
> Today, multiple pushes get multiplexed at the default priority. But that’s
> a different discussion.)
> >>
> >>
> >> Roger.
> >>
> >>
> >> Cheers
> >> Lucas
> >>
> >>
> >
> >
>
>
>

---

From: Roger Pantos <[email-masked]>
Date: Wed, 10 Jul 2019 15:47:44 -0700

> On Jul 10, 2019, at 1:57 PM, Yoav Weiss <[email-masked]> wrote:
> 
> Hey Roger,
> 
> If the goal is to extend preload (e.g. with a new attribute), I believe the best route would be to open an issue on the preload repo <https://github.com/w3c/preload/issues> with your use-case and we can discuss it further there. 

Hi Yoav. That might be a good way to go about it. Although would doing it that way would limit its use to rel=preload? That would work for me, but I wonder if there's a wider interest in defining Range for other Link types. Hopefully anyone who has such interest will chime in here.

> I also believe that such an attribute would be considered an extension attribute <https://tools.ietf.org/html/rfc8288#section-3.4.2> from a WebLinking perspective, but I may be wrong on that front.

I think that you're right.

> 
> Regarding such an attribute, have you considered what would be its impact on the browser itself? Should the browser use that range for the request as well? (assuming the header doesn't get stripped off by the server)

The h2 client implementations that I've surveyed do a fairly straightforward matching between an incoming application request and whatever's in the push cache. So for instance they would find a match if the request has the exact same range as something in the push cache, but not if the request has, say, a sub-range of that. Which is a long way of saying that if you want it to work reliably, the client should probably ask for the same range as the push. It so happens that in the particular application of LL-HLS, that always happens.

Roger.

> 
> Cheers,
> Yoav
> 
> On Wed, Jul 10, 2019 at 6:34 PM Roger Pantos <[email-masked] <mailto:[email-masked]>> wrote:
> 
> 
> > On Jul 10, 2019, at 5:10 AM, Bence Béky <[email-masked] <mailto:[email-masked]>> wrote:
> > 
> > Hi,
> > 
> > On Tue, Jul 9, 2019 at 11:26 PM Roger Pantos <[email-masked] <mailto:[email-masked]>> wrote:
> >> 
> >> 
> >> 
> >> On Jul 9, 2019, at 7:01 PM, Leif Hedstrom <[email-masked] <mailto:[email-masked]>> wrote:
> >> 
> >> 
> >>

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 11 Jul 2019 16:02:10 +1000

Hi Roger,

The philosophy of RFC8288 (which obsoleted 5988) is that individual link relation types are responsible for defining what the appropriate / meaningful set of target attributes is. So, in this case, "preload" would need to define it; as Yoav pointed out, the right place to talk about that is the preload repo and the Web Performance WG in the W3C.

We have previously talked about common parameters that are useful for more than one link relation type, but they still need to be "opted into." A while back I wrote down a starter collection of these, it might be good to dust them off and consider adding something like this. See:
  https://mnot.github.io/I-D/link-hint/

Cheers,

> On 10 Jul 2019, at 2:55 am, Roger Pantos <[email-masked]> wrote:
> 
> Greetings HTTP experts,
> 

--
Mark Nottingham   https://www.mnot.net/

---

From: Roger Pantos <[email-masked]>
Date: Fri, 12 Jul 2019 09:58:31 -0700

Thanks for the guidance, Mark. It sounds like the preload repo is the way to go. I went ahead and created a new issue there: https://github.com/w3c/preload/issues/139

Roger.

> On Jul 10, 2019, at 11:02 PM, Mark Nottingham <[email-masked]> wrote:
> 
> Hi Roger,
> 
>  https://mnot.github.io/I-D/link-hint/ <https://mnot.github.io/I-D/link-hint/>
> 
> Cheers,
> 
> 
> Mark Nottingham   https://www.mnot.net/ <https://www.mnot.net/>

---

From: Julian Reschke <[email-masked]>
Date: Fri, 12 Jul 2019 19:30:13 +0200

On 09.07.2019 18:55, Roger Pantos wrote:
> ...

Nitpicking: if you do this, please consider range units other than
"bytes".  For instance, by embedding the range unit name into the parameter:

Link: </media.mp4>; rel=preload; as=video; type=video/mp4;
range-bytes=1380-14226

Best regards, Julian

---

From: Roger Pantos <[email-masked]>
Date: Fri, 12 Jul 2019 11:51:32 -0700

> On Jul 12, 2019, at 10:30 AM, Julian Reschke <[email-masked]> wrote:
> 

Good point. Thanks Julian.

Roger.