Subject: Recursive HTTP/2 Push

From: Simone Bordet <[email-masked]>
Date: Sun, 7 Feb 2016 13:04:26 +0100

Hi,

I would like to ask for a clarification about recursive pushes.

The example: a recursive.html page, which links a recursive.css, which
references a recursive.png image via the url() directive.

recursive.html:
<html>
<head>
    <link rel="stylesheet" href="recursive.css" />
</head>
</html>

recursive.css
body {
    background-image: url("recursive.png");
}

The user agent requests recursive.html (say with stream_id=3) and
Jetty pushes both recursive.css and recursive.png in the following
way:

PUSH_PROMISE (stream_id=3, promised_stream_id=2)
PUSH_PROMISE (stream_id=2, promised_stream_id=4)

Both Chrome and Firefox accepts and use these pushes, but nghttp2
reports a protocol error, citing 7540, section 6.6:

"PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
is in either the "open" or "half-closed (remote)" state."

>From the RFC wording, it really seems that nghttp2 is right and that
Jetty, Chrome and Firefox have a non standard behavior (probably
inherited from their SPDY implementation): the second push is not a
peer-initiated stream (even considering a pushed stream a "fake"
peer-initiated stream, it is not in the "open" or "half-closed
(remote)" state).

Can someone clarify if HTTP/2 really intended to forbid recursive
pushes and why ?

Thanks !

-- 
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz

---

From: Daniel Stenberg <[email-masked]>
Date: Sun, 7 Feb 2016 16:06:10 +0100 (CET)

On Sun, 7 Feb 2016, Simone Bordet wrote:

> The user agent requests recursive.html (say with stream_id=3) and Jetty 
> pushes both recursive.css and recursive.png in the following way:
>

My reading of the spec also says that a server would be wrong sending such 
frames and that a client should reject such frames (as it isn't legal in that 
state) with a PROTOCOL_ERROR.

> Can someone clarify if HTTP/2 really intended to forbid recursive pushes and 
> why ?

I can't remember the exact reasoning, but it seems clear to me that we 
want(ed) servers only to push resources on streams the client has asked for. 
"Pushed responses are always associated with an explicit request from the 
client" (from 8.2.1)

But is there a particular reason to insist on sending the push promise on 
stream_id 2 in the second push and not just make it on stream_id 3?

-- 

  / daniel.haxx.se

---

From: Simone Bordet <[email-masked]>
Date: Sun, 7 Feb 2016 19:12:21 +0100

Hi,

On Sun, Feb 7, 2016 at 4:06 PM, Daniel Stenberg <[email-masked]> wrote:
>> Can someone clarify if HTTP/2 really intended to forbid recursive pushes
>> and why ?
>

The reason is to respect the shape of the resource tree: recursive.png
depends on recursive.css.
If the client directly asks for recursive.css, then it should get
recursive.png pushed.

Sure we can make the pushed resources just one level deep, or flatten
the resource tree like you suggest, but the recursive solution looked
more "natural".

Thanks !

---

From: Mike Bishop <[email-masked]>
Date: Mon, 8 Feb 2016 18:57:28 +0000

Part of the problem is also lifetime.  If I may be pushed streams that chain up to a navigation long after I've finished the navigation, the server gets an almost limitless ability to push resources at me so long as there's one push still in flight that I haven't RST.  Racing RSTs and PUSH_PROMISEs also become even more tricky.

By restricting pushes to streams the client initiated, the client has a well-defined point at which it knows all the streams the server has proposed to push, and can RST any that it doesn't want.

-----Original Message-----
From: Simone Bordet [mailto:[email-masked]] 
Sent: Sunday, February 7, 2016 10:12 AM
To: HTTP Working Group <[email-masked]>
Subject: Re: Recursive HTTP/2 Push

Hi,

On Sun, Feb 7, 2016 at 4:06 PM, Daniel Stenberg <[email-masked]> wrote:
> "Pushed responses are always associated with an explicit request from 
> the client" (from 8.2.1)
>
> But is there a particular reason to insist on sending the push promise 
> on stream_id 2 in the second push and not just make it on stream_id 3?

The reason is to respect the shape of the resource tree: recursive.png depends on recursive.css.
If the client directly asks for recursive.css, then it should get recursive.png pushed.

Sure we can make the pushed resources just one level deep, or flatten the resource tree like you suggest, but the recursive solution looked more "natural".

Thanks !

--
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz