Subject: Re: END_SEGMENT? (#397)

From: Daniel Sommermann <[email-masked]>
Date: Tue, 17 Jun 2014 09:23:11 -0700

Apologies for the (very) late response on this topic. My high level 
question here is if this is strictly needed for interop with 1.1. If 
not, I don't think it warrants the extra complexity and constraints on 
intermediary behavior.

On 04/17/2014 09:25 AM, Jeff Pinner wrote:
>
> On Thu, Apr 17, 2014 at 12:52 AM, <[email-masked] 
> <mailto:[email-masked]>> wrote:
>
>     What is the purpose of END_SEGMENT?
>
> END_SEGMENTS allows the layering of record-based semantics onto the 
> framing layer.
>
> Consider this use case in HTTP/1.1. An API provides a stream of data 
> using HTTP/1.1 chunked encoding. Each chunk contains a single record, 
> and the length of this record is indicated by the chunk length. In 
> HTTP/1.1 the length of these chunks was unconstrained, but when 
> translating into HTTP/2, these chunks must be segmented into multiple 
> data frames to fit within the frame size limit.
>
> If the chunk delineation was meaningful, then END_SEGMENT allows this 
> meaning to be preserved.
>

I'm not exactly sure how END_SEGMENT alone can be used to preserve chunk 
semantics. If you are proxying from 2 to chunked 1.1, you would need 
some other flag to know to add transfer-encoding: chunked and then other 
flags to know the chunk lengths. Roberto implied in an earlier message 
that END_SEGMENT is needed to preserve chunk boundaries.

> The flag is also useful for layering other record-based protocols on 
> top of HTTP.
>

Couldn't such protocols include their own delimiters? If a protocol 
running on HTTP/2 is record based, the record delimiters should be 
incorporated into the contents of the DATA frame. Otherwise, this seems 
like an unnecessary layering violation.

I'm curious who plans to use this feature and why END_SEGMENT is the 
only way to do it. While not exactly a DOS vulnerability for proxies, 
placing requirements on the framing layer limits how proxies can respond 
in low memory situations (e.g. a memory-constrained proxy might need to 
forward a partially received DATA frame as 2 smaller frames). The "MUST 
NOT coalesce" requirement in particular seems out of place. As with any 
feature, the complexity is also a potential source of bugs.

The other point brought up is that many HTTP APIs will not expose this 
segment information, potentially making it difficult to conform to the 
"intermediaries MUST NOT coalesce" requirement.

---

From: Mike Bishop <[email-masked]>
Date: Tue, 17 Jun 2014 20:51:49 +0000

Daniel's latter point applies to several of the "Intermediaries MUST [NOT]" requirements in the spec - since someone could conceivably build intermediaries sitting on top of server and client APIs and tying them together (and people do, with ours), it's not possible for such an intermediary to comply with some of these unless we propagate framing-layer or compressor-layer knowledge all the way up to the app and back down....

From: Daniel Sommermann [mailto:[email-masked]]
Sent: Tuesday, June 17, 2014 9:23 AM
To: Jeff Pinner; [email-masked]
Cc: HTTP Working Group; [email-masked]
Subject: Re: END_SEGMENT? (#397)

Apologies for the (very) late response on this topic. My high level question here is if this is strictly needed for interop with 1.1. If not, I don't think it warrants the extra complexity and constraints on intermediary behavior.
On 04/17/2014 09:25 AM, Jeff Pinner wrote:

On Thu, Apr 17, 2014 at 12:52 AM, <[email-masked]<mailto:[email-masked]>> wrote:

END_SEGMENTS allows the layering of record-based semantics onto the framing layer.

Consider this use case in HTTP/1.1. An API provides a stream of data using HTTP/1.1 chunked encoding. Each chunk contains a single record, and the length of this record is indicated by the chunk length. In HTTP/1.1 the length of these chunks was unconstrained, but when translating into HTTP/2, these chunks must be segmented into multiple data frames to fit within the frame size limit.

If the chunk delineation was meaningful, then END_SEGMENT allows this meaning to be preserved.

I'm not exactly sure how END_SEGMENT alone can be used to preserve chunk semantics. If you are proxying from 2 to chunked 1.1, you would need some other flag to know to add transfer-encoding: chunked and then other flags to know the chunk lengths. Roberto implied in an earlier message that END_SEGMENT is needed to preserve chunk boundaries.

The flag is also useful for layering other record-based protocols on top of HTTP.

Couldn't such protocols include their own delimiters? If a protocol running on HTTP/2 is record based, the record delimiters should be incorporated into the contents of the DATA frame. Otherwise, this seems like an unnecessary layering violation.

I'm curious who plans to use this feature and why END_SEGMENT is the only way to do it. While not exactly a DOS vulnerability for proxies, placing requirements on the framing layer limits how proxies can respond in low memory situations (e.g. a memory-constrained proxy might need to forward a partially received DATA frame as 2 smaller frames). The "MUST NOT coalesce" requirement in particular seems out of place. As with any feature, the complexity is also a potential source of bugs.

The other point brought up is that many HTTP APIs will not expose this segment information, potentially making it difficult to conform to the "intermediaries MUST NOT coalesce" requirement.

---

From: Daniel Sommermann <[email-masked]>
Date: Wed, 18 Jun 2014 09:44:44 -0700

Yes, this is precisely what I was getting at with the layering issue I 
brought up. It seems like a layering violation to expose segments to the 
application. It also doesn't map to HTTP/1.1 concepts (I don't see how 
it maps to chunked encoding since there is no chunk length). This seems 
like an example of a feature in the protocol that is not backwards 
compatible with HTTP/1.1. In this case, the incompatibility is at the 
API level, not the semantic level.

On 06/17/2014 01:51 PM, Mike Bishop wrote:
>
> Daniel's latter point applies to several of the "Intermediaries MUST 
> [NOT]" requirements in the spec -- since someone could conceivably 
> build intermediaries sitting on top of server and client APIs and 
> tying them together (and people do, with ours), it's not possible for 
> such an intermediary to comply with some of these unless we propagate 
> framing-layer or compressor-layer knowledge all the way up to the app 
> and back down....
>
> *From:*Daniel Sommermann [mailto:[email-masked]]
> *Sent:* Tuesday, June 17, 2014 9:23 AM
> *To:* Jeff Pinner; [email-masked]
> *Cc:* HTTP Working Group; [email-masked]
> *Subject:* Re: END_SEGMENT? (#397)
>
>     Consider this use case in HTTP/1.1. An API provides a stream of
>     data using HTTP/1.1 chunked encoding. Each chunk contains a single
>     record, and the length of this record is indicated by the chunk
>     length. In HTTP/1.1 the length of these chunks was unconstrained,
>     but when translating into HTTP/2, these chunks must be segmented
>     into multiple data frames to fit within the frame size limit.
>
> I'm not exactly sure how END_SEGMENT alone can be used to preserve 
> chunk semantics. If you are proxying from 2 to chunked 1.1, you would 
> need some other flag to know to add transfer-encoding: chunked and 
> then other flags to know the chunk lengths. Roberto implied in an 
> earlier message that END_SEGMENT is needed to preserve chunk boundaries.
>
>
> incorporated into the contents of the DATA frame. Otherwise, this 
> seems like an unnecessary layering violation.
>
> placing requirements on the framing layer limits how proxies can 
> respond in low memory situations (e.g. a memory-constrained proxy 
> might need to forward a partially received DATA frame as 2 smaller 
> frames). The "MUST NOT coalesce" requirement in particular seems out 
> of place. As with any feature, the complexity is also a potential 
> source of bugs.
>

---

From: Martin Thomson <[email-masked]>
Date: Wed, 18 Jun 2014 12:19:50 -0700

On 18 June 2014 09:44, Daniel Sommermann <[email-masked]> wrote:
> application. It also doesn't map to HTTP/1.1 concepts (I don't see how it
> maps to chunked encoding since there is no chunk length). This seems like an
> example of a feature in the protocol that is not backwards compatible with
> HTTP/1.1. In this case, the incompatibility is at the API level, not the
> semantic level.

https://github.com/http2/http2-spec/issues/537

---

From: Yutaka Hirano <[email-masked]>
Date: Thu, 19 Jun 2014 09:46:56 +0900

> like an unnecessary layering violation.

I'm interested in WebSocket over HTTP/2 and it uses END_SEGMENT.
The problem of specifying END_SEGMENT in WebSocket over HTTP/2 not in
HTTP/2 is, WebSocket over HTTP/2 can't be used with intermediaries that
merely understand HTTP/2.
I want to avoid such situation if possible.

Thanks,

On Wed, Jun 18, 2014 at 1:23 AM, Daniel Sommermann <[email-masked]> wrote:

> question here is if this is strictly needed for interop with 1.1. If not, I
> don't think it warrants the extra complexity and constraints on
> intermediary behavior.
>
> On Thu, Apr 17, 2014 at 12:52 AM, <[email-masked]> wrote:
>
> using HTTP/1.1 chunked encoding. Each chunk contains a single record, and
> the length of this record is indicated by the chunk length. In HTTP/1.1 the
> length of these chunks was unconstrained, but when translating into HTTP/2,
> these chunks must be segmented into multiple data frames to fit within the
> frame size limit.
>
> semantics. If you are proxying from 2 to chunked 1.1, you would need some
> other flag to know to add transfer-encoding: chunked and then other flags
> to know the chunk lengths. Roberto implied in an earlier message that
> END_SEGMENT is needed to preserve chunk boundaries.
>
> I'm curious who plans to use this feature and why END_SEGMENT is the only
> way to do it. While not exactly a DOS vulnerability for proxies, placing
> requirements on the framing layer limits how proxies can respond in low
> memory situations (e.g. a memory-constrained proxy might need to forward a
> partially received DATA frame as 2 smaller frames). The "MUST NOT coalesce"
> requirement in particular seems out of place. As with any feature, the
> complexity is also a potential source of bugs.
>

---

From: Martin Thomson <[email-masked]>
Date: Wed, 18 Jun 2014 19:21:07 -0700

On 18 June 2014 17:46, Yutaka Hirano <[email-masked]> wrote:
> The problem of specifying END_SEGMENT in WebSocket over HTTP/2 not in HTTP/2
> is, WebSocket over HTTP/2 can't be used with intermediaries that merely
> understand HTTP/2.

I'm less concerned about this particular problem, especially now that
we've effectively opened the door to extension.  Websockets is always
going to be dependent - at least a little - on the next hop
understanding something of the request.  We've talked in the past
about a new ALPN token for that, but it might be as simple now as
SETTINGS_ENABLE_WEBSOCKETS.

It would be relatively easy to port the necessary flags to a
websockets draft if we decided to remove them from HTTP/2.

I do think that we should be looking more seriously at your draft.  In
light of recent changes, but more because we agreed to do this, and I
think that you have the most fully developed proposal that we've
deferred due to increased attention on getting HTTP/2 done.

---

From: Yutaka Hirano <[email-masked]>
Date: Thu, 19 Jun 2014 16:51:41 +0900

> SETTINGS_ENABLE_WEBSOCKETS.

I don't want to require all intermediaries to understand WS over HTTP/2.
With END_SEGMENT, intermediaries only have to transfer the data without
understanding WS over HTTP/2.

If we don't have END_SEGMENT, we have to specify WS_END_SEGMENT in WS_DATA
frame type
which are specific to WS over HTTP/2 and all intermediaries have to
understand WS over HTTP/2.

I have one question:
Suppose we have WS_END_SEGMENT and WS_DATA.
Suppose there is an intermediary that doesn't support WS over HTTP/2.
The intermediary ignores the SETTINGS values specific to WS over HTTP/2, so
the handshake succeeds.
The intermediary discards the frames specific to WS over HTTP/2, so two
endpoints can't communicate
whereas the handshake succeeds.
Is that right?

On Thu, Jun 19, 2014 at 11:21 AM, Martin Thomson <[email-masked]>
wrote:

> HTTP/2

---

From: Martin Thomson <[email-masked]>
Date: Thu, 19 Jun 2014 08:44:09 -0700

> I don't want to require all intermediaries to understand WS over HTTP/2.

If this is the requirement, then you'll need to retain END_SEGMENT.

I'm not convinced that this is right though.  I'd rather have an
explicit acknowledgement that my protocol is understood by the
entities that are participating in it.

Imagine what would happen if an intermediary decided to cache the
response to your websocket request...

---

From: Daniel Sommermann <[email-masked]>
Date: Thu, 19 Jun 2014 09:17:31 -0700

On 06/19/2014 12:51 AM, Yutaka Hirano wrote:
> With END_SEGMENT, intermediaries only have to transfer the data 
> without understanding WS over HTTP/2.

Both options require changes. Even if the intermediary doesn't 
understand WS, normal day-to-day HTTP/1.1 APIs would have to change to 
accommodate segments. In my mind, that is nearly the same as requiring 
the proxy to understand WS.

>
> If we don't have END_SEGMENT, we have to specify WS_END_SEGMENT in 
> WS_DATA frame type
> The intermediary ignores the SETTINGS values specific to WS over 
> HTTP/2, so the handshake succeeds.
> The intermediary discards the frames specific to WS over HTTP/2, so 
> two endpoints can't communicate

I think it would be worth noting in the spec how SETTING negotiation 
works. There's some text in 5.5 already, but perhaps we could be a bit 
more explicit. Here's how I think it can work:

* Extension negotiation happens only during the initial SETTINGS frame 
exchange
* A negotiated extension is active if
     1) A SETTINGS frame with the extension setting enabled has been sent
     2) A SETTINGS frame with the extension setting enabled has been 
received
     3) A SETTINGS frame with the ack flag has been sent

Negotiated settings should take effect for all sent frames after step 
#3. An HTTP/2 endpoint should be prepared to receive extension frames 
after step #2.

This might be more strict than necessary, but it prevents the situation 
of one side believing the extension is ON and the other thinks it is OFF.

---

From: Jeff Pinner <[email-masked]>
Date: Thu, 19 Jun 2014 10:24:19 -0700

> response to your websocket request...

More specifically, the requirement should be that "transparent
intermediaries" not need to understand WS (whether those be captive
portals, load balancers, HTTP routers, etc). And since these proxy devices
may reframe the data stream based on things like window sizes on the
proxied connections, they must at least understand the flag and how to
behave when it comes to reframing.

---

From: Jeff Pinner <[email-masked]>
Date: Thu, 19 Jun 2014 10:26:10 -0700

>
>
> Both options require changes. Even if the intermediary doesn't understand
> WS, normal day-to-day HTTP/1.1 APIs would have to change to accommodate
> segments. In my mind, that is nearly the same as requiring the proxy to
> understand WS.
>
>
The requirements as written were done so that there is no to change normal
day-to-day HTTP/1.1 APIs. It is a requirement on the framing layer, not the
HTTP message layer.

This is in the same sense as HTTP/1.1 APIs do not need to be changed to
understand PING or SETTINGS.

---

From: Daniel Sommermann <[email-masked]>
Date: Thu, 19 Jun 2014 11:53:19 -0700

On 06/19/2014 10:26 AM, Jeff Pinner wrote:
>     understand WS, normal day-to-day HTTP/1.1 APIs would have to
>     change to accommodate segments. In my mind, that is nearly the
>     same as requiring the proxy to understand WS.
>
>
> The requirements as written were done so that there is no to change 
> normal day-to-day HTTP/1.1 APIs. It is a requirement on the framing 
> layer, not the HTTP message layer.
>
> This is in the same sense as HTTP/1.1 APIs do not need to be changed 
> to understand PING or SETTINGS.

Not quite -- since PING and SETTINGS are hop-to-hop they don't need to 
be exposed above the framing layer. Segments are end-to-end, so they 
have to be exposed above the framing layer (ie the HTTP message layer).

---

From: Jeff Pinner <[email-masked]>
Date: Thu, 19 Jun 2014 12:15:30 -0700

>
> Not quite -- since PING and SETTINGS are hop-to-hop they don't need to be
> exposed above the framing layer. Segments are end-to-end, so they have to
> be exposed above the framing layer (ie the HTTP message layer).
>

The intent (and clarification is clearly necessary) is that they are a
property of the stream. If you are forwarding the stream you must maintain
that property.

I agree that once you parse the stream into an HTTP message, if you do so
using an API which does not expose the segments that property will be lost.
But this is true for any push as well (you need to change the APIs to
somehow expose the associated request).

The goal here is that record-based protocols (WS for example) can be
deployed over the HTTP/2 session layer and be reliably transported through
transparent intermediaries (in particular HTTP/2 firmware devices that do
load-balancing) without those intermediaries needing to understand the
protocol.

---

From: Yutaka Hirano <[email-masked]>
Date: Fri, 20 Jun 2014 10:53:32 +0900

> If this is the requirement, then you'll need to retain END_SEGMENT.

What I really need is that an intermediary which don't understand WS over
HTTP/2 don't
do unnecessary "intelligent" things.
Specifically, I don't want an intermediary to drop a WS frame or to buffer
WS frames over
a message boundary without understanding WS over HTTP/2.

If you could state that an intermediary MUST NOT discard or buffer an
unknown or unsupported frames,
it would serve (without END_SEGMENT).
Sorry I didn't follow the "Extending HTTP/2" discussion, so please let me
know if the above statement is pointless.

> entities that are participating in it.

That requires an additional statement on the HTTP/2 spec.
Though I will be happier if WS over HTTP/2 can work with intermediaries
that don't understand WS over HTTP/2,
WS over HTTP/2 can work with the "explicit acknowledgement" mechanism.

Thanks,

---

From: Daniel Sommermann <[email-masked]>
Date: Mon, 30 Jun 2014 09:43:02 -0700

What's the right order to tackle this issue? Can we remove END_SEGMENT 
and then patch the websockets proposal, or do we need to have a story 
for websockets first?

Daniel

---

From: Martin Thomson <[email-masked]>
Date: Mon, 30 Jun 2014 09:49:06 -0700

On 30 June 2014 09:43, Daniel Sommermann <[email-masked]> wrote:
> What's the right order to tackle this issue? Can we remove END_SEGMENT and
> then patch the websockets proposal, or do we need to have a story for
> websockets first?

I think that we have to resolve the issue, either:

a) A new protocol (like websockets) can be layered on top
of/integrated with HTTP/2 without changing the application negotiation
token, as long as the properties of the protocol are compatible.  That
is, intermediaries that support HTTP/2 can carry websockets.

b) A new protocol needs a new application negotiation token.

---

From: David Krauss <[email-masked]>
Date: Tue, 1 Jul 2014 00:54:47 +0800

“Tackle”? It’s an editorial issue, and reviewing GitHub it essentially boils down to specifying what sort of flush should occur.

I don’t think anyone’s talking about removing END_SEGMENT or WebSocket support. It’s essential to interactive applications, including the sort of things that WebSockets often does. This is something all proxies should handle going forward.

On 2014–07–01, at 12:43 AM, Daniel Sommermann <[email-masked]> wrote:

> What's the right order to tackle this issue? Can we remove END_SEGMENT and then patch the websockets proposal, or do we need to have a story for websockets first?
> 
> Daniel
>

---

From: Martin Thomson <[email-masked]>
Date: Mon, 30 Jun 2014 10:01:07 -0700

> I don’t think anyone’s talking about removing END_SEGMENT or WebSocket support. It’s essential to interactive applications, including the sort of things that WebSockets often does. This is somethin…

I think that people are.  From some perspectives, END_SEGMENT is cruft
and WebSocket support isn't present.  From the other perspective,
thewebsocketprotocol can be shoehorned in and that's good enough.

---

From: David Krauss <[email-masked]>
Date: Tue, 1 Jul 2014 01:06:03 +0800

> thewebsocketprotocol can be shoehorned in and that's good enough.

Special-purpose proxies can ignore any part of the protocol that their designer knows will not occur in the local environment. It’s not a normative issue.

Fully conforming proxies should support interactive applications.

---

From: Daniel Sommermann <[email-masked]>
Date: Mon, 30 Jun 2014 10:19:06 -0700

> I don’t think anyone’s talking about removing END_SEGMENT or WebSocket support. It’s essential to interactive applications, including the sort of things that WebSockets often does. This is somethin…

David, we had a discussion on this thread about two weeks ago about the 
layering violations and constraints on intermediaries that are 
introduced by END_SEGMENT and whether END_SEGMENT is needed for the core 
spec.

Also, I brought up the fact that END_SEGMENT's requirements on 
intermediary behavior is not compatible with HTTP/1.1 interfaces. There 
is no concept of segments in HTTP/1.1, so there is no way to transfer 
those semantics through an HTTP/1.1 interface.

I've updated the linked issue in the subject line.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 30 Jun 2014 10:20:30 -0700

> Special-purpose proxies can ignore any part of the protocol that their designer knows will not occur in the local environment. It’s not a normative issue.

That's an argument for the new application negotiation token.

> Fully conforming proxies should support interactive applications.

That's an argument against the new application negotiation token.

---

From: David Krauss <[email-masked]>
Date: Tue, 1 Jul 2014 02:23:15 +0800

Combining replies to Martin and Daniel.

> That's an argument for the new application negotiation token.

Such a proxy should only be put in a place where no negotiation is necessary. Bailing out at any END_SEGMENT would be acceptable then.

> That's an argument against the new application negotiation token.

Yes.

On 2014–07–01, at 1:19 AM, Daniel Sommermann <[email-masked]> wrote:

> David, we had a discussion on this thread about two weeks ago about the layering violations and constraints on intermediaries that are introduced by END_SEGMENT and whether END_SEGMENT is needed for the core spec.

Ah, now I see. Your complaint regarding APIs is similar to mine, raised earlier in other threads (April 16 and 19). Indeed, this is not something applications should be encouraged to fool with.

However, do note that as uncovered by the April 19 thread, END_SEGMENT is only duplicating the intended semantics of mid-stream header blocks, which also act as a fence against DATA coalescing. Reasonable handling of headers likewise would seem to suggest flushing, since they tend to indicate a new request. In effect, END_SEGMENT is only a compressed representation of an empty (non-delta encoded) header block.

> Also, I brought up the fact that END_SEGMENT's requirements on intermediary behavior is not compatible with HTTP/1.1 interfaces. There is no concept of segments in HTTP/1.1, so there is no way to transfer those semantics through an HTTP/1.1 interface.

An HTTP/1.1 intermediary interceding on an HTTP/2 Websockets stream should cause the same degradation as on an HTTP/1.1 Websockets stream. Does translating 2<=>1.1 require knowledge of the original WebSockets protocol? Yes. But that’s unavoidable, and in the long run HTTP/1.1 proxies will go away. That process will start sooner if HTTP/2 normalizes the behavior as opposed to waiting for HTTP/3.

It would perhaps be nice to have an end-to-end SETTINGS indicator that every hop is HTTP/2. Then endpoints could generally moderate their expectations, regarding PRIORITY, etc.

> I've updated the linked issue in the subject line.

Thanks.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 30 Jun 2014 11:40:07 -0700

> Such a proxy should only be put in a place where no negotiation is necessary. Bailing out at any END_SEGMENT would be acceptable then.

There's an obvious counterargument to that one...

That's fine, but if you want to operate sans-standard, then you can
add your own END_SEGMENT.

I really don't care either way here.  I'm just enumerating the
options, and noting that what is currently specified isn't
particularly well-supported.  Our responsibility is to either more
clearly define it, or remove it.

---

From: David Krauss <[email-masked]>
Date: Tue, 1 Jul 2014 02:45:39 +0800

> add your own END_SEGMENT.

Should be explicitly prohibited.

> clearly define it, or remove it.

This I agree with. Actually the same goes for mid-stream headers.

I gave up on the earlier thread, but I still think that END_SEGMENT should be explicitly defined as a compressed representation of an empty header set, to be processed after the current frame.

This puts HTTP/1.1 intermediary support exactly on par. No worries about semantics, no hook for application designers to work their twisted magic.