Subject: RE: Making Implicit C-E work.

From: <[email-masked]>
Date: Thu, 1 May 2014 21:57:43 +0000

In many different e-mails [email-masked] wrote:

> I have a real honest-to-goodness pragmatic deployment problem (myriad pre-existing servers/clients

> whose deployment I do not and cannot control) here that I cannot wish away ...

> Many of my customers will not be writing custom servers, and as such to be deployable,

> we need solutions that will work with what is out there. ...
>

> My problem is dealing with the rest of the world, which is mostly HTTP/1.X and is unlikely to rapidly change.

> In other words, I'm concerned mainly with HTTP/1.X clients and especially servers. ...

I  honestly want to understand your problem, but I don't.  It might be really helpful if you could write down the hypothetical network connections between client and server (including as many potential intermediaries as you know about) and denote either HTTP/1.x or HTTP/2 for every hop.

I've been sitting here trying to understand how implicit C-E gzip helps based on what you've already said and I still don't get it.

You said you are concerned especially about HTTP/1.X servers.  But your proposal can't help because the 1.X servers won't know about the implicit gzip and certainly won't know to add the "uncompressed-*" headers.

In the opposite direction, if the server is HTTP/2 and the client is HTTP/1.X, the body will have to be decompressed anyway so you only benefit for the hops that are HTTP/2.  Is that really that beneficial?

Between an HTTP/2 client and an HTTP/2 server, we can already do something about it without breaking things i.e. some sort of transfer coding.

> The same bytes can't be sent in both [C-E and T-E], unless the we're willing to suffer vastly increased DoS surface area and memory usage [for T-E] ...

I don't buy the "vastly increased DoS surface area" argument. The receivers already have this "DoS surface area" for decompressing C-E gzip entities.  If the receiver of a stream has a gzip decompression context for decompressing a C-E gzip entity OR a T-E gzip message, they still just have one context.  If a receiver has N outstanding streams it has N outstanding gzip contexts, even if they're all C-E gzip.  Sure stupid servers could do both C-E and T-E, but it's near impossible to design a protocol that prevents implementors from doing every stupid thing imaginable.

So, yes the same bytes could be sent in both cases (C-E or T-E) and it's actually probably the right way to do T-E (as opposed to the frame-by-frame).

> I cannot reliably deploy a T-e based compression solution.
> T-e based compression costs too much CPU, especially as compared with c-e where one simply
> compresses any static entity once and decompresses (which is cheap) as necessary at the gateway.

You're comparing apples and oranges. Dynamic gzip has the same cpu cost whether it's called C-E or T-E. For static entities, as I pointed out above, you can pre-compress once and send the same bytes as either C-E or T-E.

> T-e based compression isn't as performant in terms of compression/deflation ratios.

LOL. I assume you could only possibly be talking about frame-by-frame T-E. Ironically, in another thread you said the performance difference for frame-by-frame is negligible (and we sent out data to back that up).

> Many deployed clients/servers wouldn't correctly support it.

I know of no clients/servers that *incorrectly* support T-E.  I assume you just mean wouldn't support it at all?

> T-e would require that any gateway acting as a loadbalancer/reverse proxy would either need to know which
> resources it could compress, or forces us to not use compression. Knowing what resources to compress either
> requires an oracle, or requires content authors to change how they author content (*really* not likely to happen),

How do they solve the same problem with C-E?  The server decides, right?  Same thing for T-E.

> [With implicit C-E gzip] [a]n HTTP/1 client still receives an uncompressed entity if it didn't request it compressed.

What are _HTTP/2_ clients supposed to do to that really want an uncompressed (identity) entity?

Accept-Encoding: identity

Implicit-Accept-Encoding: pretty please don't use gzip

In addition to everything above, I noticed that you still haven't responded to concerns that Matthew & Julian brought up. It would be good for you to update your proposal to address these concerns...

- Matthew wrote: "[What about] last-modified? And, possibly, other fields from Vary? There's more entity-specific metadata than just ETag."

- Matthew also wrote: "Cache-Control:no-transform explicitly forbids the proxy from altering the representation. It's not allowed to decompress it."

- And elsewhere Julian brought up the issue of entity-specific metadata in the body itself. He used the example of WebDav. Do you expect intermediaries to parse through bodies and patch up that metadata too?

This email message is intended only for the use of the named recipient. Information contained in this email message and its attachments may be privileged, confidential and protected from disclosure. If you are not the intended recipient, please do not read, copy, use or disclose this communication to others. Also please notify the sender by replying to this message and then delete it from your system.

---

From: <[email-masked]>
Date: Thu, 1 May 2014 21:58:18 +0000

On 30 April 2014 06:50, Matthew Kerwin wrote:
> ... you end up with my earlier idea of a level of compression somewhere between entity-representation and transport. But because that's just too much work to get right, and even harder to make interoperate with older HTTP, I deferred it until HTTP 3+.

I still think it's a good idea.  We proposed something similar, but as an extension to HTTP so it could be deployed everywhere if desirable.  In fact we just recently wrote out our idea for Message-Encoding into a draft RFC at:
https://github.com/shearl/Internet-Drafts/blob/master/draft-morgan-http-message-encoding/draft-morgan-http-message-encoding.txt

> In fact only yesterday I set up a rough and ready wiki on github to track my thoughts on the matter.
> It's at <https://github.com/phluid61/http3> IIRC.

Is there supposed to be something there already? I only see a README with two sentences.
This email message is intended only for the use of the named recipient. Information contained in this email message and its attachments may be privileged, confidential and protected from disclosure. If you are not the intended recipient, please do not read, copy, use or disclose this communication to others. Also please notify the sender by replying to this message and then delete it from your system.

---

From: Matthew Kerwin <[email-masked]>
Date: Fri, 2 May 2014 08:19:21 +1000

> Is there supposed to be something there already? I only see a README with
two sentences.

https://github.com/phluid61/http3/wiki/Goals

I am currently out of town for a conference, so haven't had a chance to do
anything but get it started with a preliminary brain dump.

I'll look through your draft as soon as I get back to familiar climes.

---

From: Roberto Peon <[email-masked]>
Date: Fri, 2 May 2014 15:31:23 -0700

On Thu, May 1, 2014 at 2:57 PM, <[email-masked]> wrote:

> > My problem is dealing with the rest of the world, which is mostly
> HTTP/1.X and is unlikely to rapidly change.
>
> I  honestly want to understand your problem, but I don't.  It might be
> really helpful if you could write down the hypothetical network connections
> between client and server (including as many potential intermediaries as
> you know about) and denote either HTTP/1.x or HTTP/2 for every hop.
>

  Browser <-h2-> Virus Scanning Software <-h2.> Corporate Proxy <-h2->
 Reverse Proxy/Loadbalancer <-h1-> Reverse Proxy/Loadbalancer(2) <-h1->
Servers
  The fat+short pipe starts after the first 'Reverse Proxy' here.

Other things that definitely happen:

  Browser <-h1-> Virus Scanning Software <-h1.> Corporate Proxy <-h1->
 Reverse Proxy/Loadbalancer <-h2-> Reverse Proxy/Loadbalancer(2) <-h1->
Servers
  The fat+short pipe starts after the *second* 'Reverse Proxy' here.

I'm sure there are myriad other things that happen here, that I'm not
listing.

>
>
> I've been sitting here trying to understand how implicit C-E gzip helps
> based on what you've already said and I still don't get it.
>
>
>
> You said you are concerned especially about HTTP/1.X servers.  But your
> proposal can't help because the 1.X servers won't know about the implicit
> gzip and certainly won't know to add the "uncompressed-*" headers.
>

This is assuming that those parts aren't delegated to the loadbalancer,
which I see often.
The server ultimately always controls if the content could have ever been
compressed (the loadbalancer never compresses).
In other words, there are architectural simplifications that can be made
when the server delegate certain responsibilities to a loadbalancer/proxy.
The choice of whether or not compression is allowed/used is always up to
the server.

Lets ignore that, though.
To support t-e: gzip, one must change the server framework, not simply
business logic.

>
>
>
> In the opposite direction, if the server is HTTP/2 and the client is
> HTTP/1.X, the body will have to be decompressed anyway so you only benefit
> for the hops that are HTTP/2.  Is that really that beneficial?
>
>
huh?

>
>
> Between an HTTP/2 client and an HTTP/2 server, we can already do something
> about it without breaking things i.e. some sort of transfer coding.
>
>
>
Agreed, but that isn't the use-case that I'm worried about. I have myriad
servers which I don't control which I won't be able to make changes to.

>
>
>
> > The same bytes can't be sent in both [C-E and T-E], unless the we're
> willing to suffer vastly increased DoS surface area and memory usage [for
> T-E] ...
>
> I don't buy the "vastly increased DoS surface area" argument. The
> receivers already have this "DoS surface area" for decompressing C-E gzip
> entities.  If the receiver of a stream has a gzip decompression context for
> decompressing a C-E gzip entity OR a T-E gzip message, they still just have
> one context.  If a receiver has N outstanding streams it has N outstanding
> gzip contexts, even if they're all C-E gzip.  Sure stupid servers could do
> both C-E and T-E, but it's near impossible to design a protocol that
> prevents implementors from doing every stupid thing imaginable.
>
> So, yes the same bytes could be sent in both cases (C-E or T-E) and it's
> actually probably the right way to do T-E (as opposed to the
> frame-by-frame).
>
>
This part of the discussion is in the other thread. I'll leave it there :)

> You're comparing apples and oranges. Dynamic gzip has the same cpu cost
> whether it's called C-E or T-E. For static entities, as I pointed out
> above, you can pre-compress once and send the same bytes as either C-E or
> T-E.
>

The issue isn't just the cost, but *where* the cost is born.
The cost should not be born by the http2 gateway in the HTTP1 server ->
client direction.
Additionally, with c-e, remember that for static resources, the compression
cost is incurred only once, not once for every request.

> LOL. I assume you could only possibly be talking about frame-by-frame T-E.
> Ironically, in another thread you said the performance difference for
> frame-by-frame is negligible (and we sent out data to back that up).
>

correct. And it isn't a big difference, but it is there. The difference
gets bigger the smaller the framesize. Note that I prefer frame-based t-e
to segment based t-e, and we're discussing that in another thread.

> just mean wouldn't support it at all?
Correct. Most clients servers that I know of don't support anything other
than t-e: chunked

> > resources it could compress, or forces us to not use compression.
> Knowing what resources to compress either
> > requires an oracle, or requires content authors to change how they
> author content (*really* not likely to happen),
>
>
>

Correct, except that in current deployments servers know about c-e and not
about t-e. Thus, an http2 gateway can be deployed which is able to serve
compressed resources with c-e, but not with t-e thanks to the lack of
server support for t-e.

>
>
>
>
>
> > [With implicit C-E gzip] [a]n HTTP/1 client still receives an
> uncompressed entity if it didn't request it compressed.
>

They're supposed to support  being able to un-gzip.

>
>
>
>
>
> In addition to everything above, I noticed that you still haven't
> responded to concerns that Matthew & Julian brought up. It would be good
> for you to update your proposal to address these concerns...
>
>
>
> - Matthew wrote: "[What about] last-modified? And, possibly, other fields
> from Vary? There's more entity-specific metadata than just ETag."
>
>
>
The rule is simple ":uncomressed-foo" replaces "foo" if decompression is
done.

>
> - Matthew also wrote: "Cache-Control:no-transform explicitly forbids the
> proxy from altering the representation. It's not allowed to decompress it."
>

I've addressed this. It isn't altering the representation if it is
effectively transmitting both.

>
>
>
> - And elsewhere Julian brought up the issue of entity-specific metadata in
> the body itself. He used the example of WebDav. Do you expect
> intermediaries to parse through bodies and patch up that metadata too?
>
>
No. I'd expect the origin to not produce the :uncompressed-foo" fields if
this caused problems.

>
>
>
>
> This email message is intended only for the use of the named recipient.
> Information contained in this email message and its attachments may be
> privileged, confidential and protected from disclosure. If you are not the
> intended recipient, please do not read, copy, use or disclose this
> communication to others. Also please notify the sender by replying to this
> message and then delete it from your system.
>

-=R

---

From: Matthew Kerwin <[email-masked]>
Date: Sat, 3 May 2014 15:57:29 +1000

On May 3, 2014 8:31 AM, "Roberto Peon" <[email-masked]> wrote:
>
>> - Matthew wrote: "[What about] last-modified? And, possibly, other
fields from Vary? There's more entity-specific metadata than just ETag."
done.

Ohh, is this a header pattern? As in, all headers that start with
":uncompressed-" (or whatever) get copied across at the gateway?

So you're effectively sending two complete sets of headers, and optimising
for the overlap.

I can live with this idea, as long as it's made really clear which header
is used by caches and origins for supporting conditionals and ranges in
which situations.

Yeah, I understand this now; you've theoretically transmitted the
uncompressed entity and all its headers, and the compressed one and all of
its. Two tiers of encoding. And because you can detect support for c-e, you
can choose to only use one or the other, if you want.

It's a pretty conceptually rich change; I'd imagine not a great deal of
code would change, but I think it needs a bit more thinking and discussion
to make sure we end up with something that works properly and doesn't hide
other problems.  Are people happy to invest time into something like this?

---

From: Johnny Graettinger <[email-masked]>
Date: Tue, 6 May 2014 17:11:00 -0400

Something that hadn't been clear to me until now (thanks Roberto) is a
significant difference between implicit c-e: gzip and implicit t-e: gzip,
on the upload path from the client. This has been referenced on the list
already, but I benefited from having it explicitly unpacked, and others may
as well:

Assume a gateway inter-mediating a HTTP/2 client and a HTTP/1.1 origin.
When forwarding a POST from the client which uses c-e: gzip, the gateway is
pragmatically able to forward that request wholesale to the origin. While
not universal, many 1.1 servers support c-e: gzip POSTs today (eg, Apache's
mod_deflate). At worst, handling an unexpected Content-Encoding is not a
new problem for 1.1 origins. Thus it's reasonable for the gateway to
forward the request and expect the client to know what it's doing.

Conversely, when forwarding a POST from the client which uses t-e: gzip,
the gateway is *required* to decompress before handing off to the origin
(given the nonexistent HTTP/1.1 support for t-e: gzip), and face the
ensuing DoS attack surface. Either that, or switch to c-e: gzip :)

On Sat, May 3, 2014 at 1:57 AM, Matthew Kerwin <[email-masked]>wrote:

> >> - Matthew also wrote: "Cache-Control:no-transform explicitly forbids
> the proxy from altering the representation. It's not allowed to decompress
> it."
> >

---

From: <[email-masked]>
Date: Wed, 14 May 2014 07:28:08 +0000

On Wednesday,30 April 2014 12:27, Roberto Peon Wrote:

> On Wednesday,30 April 2014 11:35, Roland Zinks wrote:

>> On Wednesday,30 April 2014 08:45, Roberto Peon Wrote:

>>> In fact what we're doing is offering two representations simultaneously.

>> Don't think this will really work. Only one can delivered and translating between them (for example range) seems to be difficult.

> Why is range a problem? If a server wishes to service a range request, it need not compress the output.

> With the proposal, the server will be able to know if the client requested gzip explicitly or not and make

> the correct decision w.r.t. what to output. This is the same as it is today with HTTP/1.

Let's clarify that.  If a server wishes to service a range request it MUST NOT use implicit c-e gzip to compress the output.

range(gzip(content)) != range(identity(content))

This introduces loop-holes for all of those intermediaries you're trying to combat which strip a-e gzip.

For example, an intermediary could...

+ Strip a-e gzip and inject a range request for the entire content:

   "Accept-Encoding: identity"

   "Range: bytes=0-"

+ Or, if the server is too smart for that, strip a-e gzip and inject a multi-part range for the entire content:

   "Accept-Encoding: identity"

  "Range: bytes=0-0,1-"

+ Or, if the server is really smart, strip a-e gzip and split the request into two separate range requests for the entire content:

   "Accept-Encoding: identity"

   "Range: bytes=0-0"

   ...

   "Accept-Encoding: identity"

   "Range: bytes=1-"

Of course the server could simply disable Range requests (i.e. always send the full c-e gzip response - which is legal).  I would argue that this will also degrade the user experience as there are more and more users browsing on spotty networks (e.g. Safari doesn’t use range requests [1] and it drives me crazy every time I’m loading a page and there is a break in network connectivity on the subway, because then it has to start all over).

[1] http://lists.w3.org/Archives/Public/ietf-http-wg/2014AprJun/0112.html

---

From: <[email-masked]>
Date: Wed, 14 May 2014 07:27:11 +0000

Hi Roberto, see my responses in-line below...

On Saturday,03 May 2014 00:31, [email-masked]<mailto:[email-masked]> wrote:

> On Thu, May 1, 2014 at 2:57 PM, <[email-masked]<mailto:[email-masked]>> wrote:

>> You said you are concerned especially about HTTP/1.X servers.  But your proposal can't help because the

>> 1.X servers won't know about the implicit gzip and certainly won't know to add the "uncompressed-*" headers.

> This is assuming that those parts aren't delegated to the loadbalancer, which I see often.

Earlier in this thread you said you have no control over the clients and servers.  Just to be clear, that means you have enough control over the loadbalancer to add the "uncompressed-*" headers??

If you have control over the loadbalancer, I assume you would have enough control to add h2 t-e. Furthermore, _if_ per-segment t-e was used, the c-e gzip entity could be used directly for the t-e gzip entity (with the uncompressed etag, etc. headers of course).  In other words, c-e gzip is-byte-for-byte identical to the per-segment t-e representation. Like I said in the other thread, per-segment and per-frame transfer coding both have their pros and cons – I’m still undecided – but this is a pro in favor of per-segment t-e.

>> In the opposite direction, if the server is HTTP/2 and the client is HTTP/1.X, the body will have to be

>> decompressed anyway so you only benefit for the hops that are HTTP/2.  Is that really that beneficial?

> Browser <-h1-> Virus Scanning Software <-h1.> Corporate Proxy <-h1->  Reverse Proxy/Loadbalancer <-h2-> Reverse Proxy/Loadbalancer(2) <-h1-> Servers

In this example, the response is only compressed from the server back to the last h2 hop (Reverse Proxy/Loadbalancer) and then has to be decompressed, and will be decompressed all the way back to the browser.

I'm just asking if it's really that beneficial to have the entity compressed for a couple of hops, and then decompressed at the h2->h1 gateway - which adds cpu load to the gateway.

> Additionally, with c-e, remember that for static resources, the compression cost is incurred only once, not once for every request.

This would also be true for *per-segment* t-e. Another pro in favor of per-segment t-e.

> They're supposed to support  being able to un-gzip.

In the case of a Range request it doesn't work to get a range of a gzip entity instead of the range of the identity entity you asked for.

In other words... range(gzip(content)) != range(identity(content))

---

From: <[email-masked]>
Date: Wed, 14 May 2014 07:34:43 +0000

On Tuesday,06 May 2014 23:11, Johnny Graettinger wrote:

> Something that hadn't been clear to me until now (thanks Roberto) is a significant difference

> between implicit c-e: gzip and implicit t-e: gzip …

> Assume a gateway inter-mediating a HTTP/2 client and a HTTP/1.1 origin. When forwarding

> a POST from the client which uses c-e: gzip … it's reasonable for the gateway to forward the

> request and expect the client to know what it's doing.

> Conversely, when forwarding a POST from the client which uses t-e: gzip, the gateway is

> required to decompress before handing off to the origin … and face the ensuing DoS attack

> surface.

(This thread is about implicit C-E gzip for responses. C-E gzip on requests is being discussed in the thread “Support for gzip at the server #424”.  No matter though, because your example is true in the other direction as well. Plus, t-e gzip is in both directions.)

Nearly all of the problems brought up w.r.t. t-e gzip are also true for C-E gzip. This one is no exception.

Implicit C-E gzip adds a large DoS attack surface to intermediaries.  An attacker simply sends requests without ‘accept-encoding: gzip’ from a HTTP/1.1. origin through a 1.1<->2 gateway for a resource it knows the server will implicitly C-E gzip. Then (using your own words Johnny) “the gateway is required to decompress before handing off to the origin … and face the ensuing DoS attack surface.”

*I would be thrilled if a request with no ‘accept-encoding’ header implied C-E gzip, but you can opt out by explicitly sending an ‘accept-encoding’ header.*

Just as a point of clarification, I don’t think t-e gzip should be implicit.  (I may have said that in the past, but definitely changed my mind for the very reason you brought up.) I do think frame compression (t-e gzip) and its associated SETTINGS_COMPRESS_DATA setting should be enabled by default, but I think there should always be a way to opt out.

---

From: Johnny Graettinger <[email-masked]>
Date: Wed, 14 May 2014 11:52:47 -0400

> *Implicit C-E gzip adds a large DoS attack surface to intermediaries.*
> An attacker simply sends requests without ‘accept-encoding: gzip’ from a
> HTTP/1.1. origin through a 1.1<->2 gateway for a resource it knows the
> server will implicitly C-E gzip. Then (using your own words Johnny) “the
> gateway is required to decompress before handing off to the origin … and
> face the ensuing DoS attack surface.”
>

This is a problem which already exists today. As Roberto noted, existing h1
intermediaries add a-e: identity on behalf of clients who didn't ask for
it, and existing servers send c-e: gzip anyway, because the observed impact
of not compressing is higher than the interop issues it introduces.

The DOS mitigation which is available today, and continues to be available
for h2/h1 gateways under implicit c-e: gzip, is to pass through what the
server sent without decompression. There's a high likelihood the h1 client
will be able to handle c-e: gzip  (and even prefers it), which is
definitely not true if t-e: gzip were used instead.

---

From: Roland Zink <[email-masked]>
Date: Wed, 14 May 2014 18:21:50 +0200

On 14.05.2014 17:52, Johnny Graettinger wrote:
>
>     Nearly all of the problems brought up w.r.t. t-e gzip are also
>     true for C-E gzip. This one is no exception.
>
>     */Implicit C-E gzip adds a large DoS attack surface to
>     intermediaries./*  An attacker simply sends requests without
>     ‘accept-encoding: gzip’ from a HTTP/1.1. origin through a 1.1<->2
>     gateway for a resource it knows the server will implicitly C-E
>     gzip. Then (using your own words Johnny) “the gateway
>     is required to decompress before handing off to the origin … and
> This is a problem which already exists today. As Roberto noted, 
> existing h1 intermediaries add a-e: identity on behalf of clients who 
> didn't ask for it, and existing servers send c-e: gzip anyway, because 
> the observed impact of not compressing is higher than the interop 
> issues it introduces.
I have seen adding a-e added to a proxy because nobody knowing about the 
interop issue and I have seen it removed after years.

> The DOS mitigation which is available today, and continues to be 
> available for h2/h1 gateways under implicit c-e: gzip, is to pass 
> through what the server sent without decompression. There's a high 
> likelihood the h1 client will be able to handle c-e: gzip  (and even 
> prefers it), which is definitely not true if t-e: gzip were used instead.
>
In h1 the use of compression is negotiated and the server will not send 
compressed content when the client can't handle it. With implicit c-e: 
gzip this is changed and this disables this DOS mitigation or make 
suddenly a number of h1 clients incompatible.

Regards,
Roland

---

From: <[email-masked]>
Date: Wed, 14 May 2014 20:31:27 +0000

On 14 May 2014 17:52, [email-masked] wrote:
> On 14 May 2014, Keith Morgan wrote:
>> Implicit C-E gzip adds a large DoS attack surface to intermediaries.
>> An attacker simply sends requests without ‘accept-encoding: gzip’ from a HTTP/1.1.
>> origin through a 1.1<->2 gateway for a resource it knows the server will
>> implicitly C-E gzip. Then (using your own words Johnny) “the gateway is required
>> to decompress before handing off to the origin … and face the ensuing DoS attack
>> surface.”
>
>
> intermediaries add a-e: identity on behalf of clients who didn't ask for it, and
> existing servers send c-e: gzip anyway, because the observed impact of not
> compressing is higher than the interop issues it introduces.
>
>
> The DOS mitigation which is available today, and continues to be available for
> h2/h1 gateways under implicit c-e: gzip, is to pass through what the server sent
> without decompression. There's a high likelihood the h1 client will be able to
> handle c-e: gzip  (and even prefers it), which is definitely not true if t-e: gzip
> were used instead.

The current -12 spec says "Intermediaries that perform translation from HTTP/2 to
HTTP/1.1 MUST decompress payloads unless the request includes an Accept-Encoding
value that includes 'gzip'." [1].

So implicit gzip either introduces a legitimate DoS at the HTTP/2 to HTTP/1.1 gateway
or you want gateways to ignore this requirement and introduce interop issues. Which
is it?

If it's the latter (forward compressed regardless of the A-E header), then what's the
point of Roberto's "uncompressed-*" headers for the gateways if you don't really want
the gateways to deccompress? And what's the point of this "MUST decompress payloads"
requirement?

If it's the former (decompress at the gateway), and you want to live with the DoS
attack surface, I have to ask again, what's the point of all this - just to have
compression on one or two h2 hops and then force gateways to dynamically decompress??

[1] http://http2.github.io/http2-spec/#Compression
This email message is intended only for the use of the named recipient. Information contained in this email message and its attachments may be privileged, confidential and protected from disclosure. If you are not the intended recipient, please do not read, copy, use or disclose this communication to others. Also please notify the sender by replying to this message and then delete it from your system.

---

From: Martin Thomson <[email-masked]>
Date: Wed, 14 May 2014 14:18:24 -0700

Maybe someone needs to use small words or something, but to me, this DoS
claim is this far poorly supported in fact from my reading.

Assuming that you employ flow control, the only commitment an intermediary
makes when decompressing is the decompression context for each stream. That
is bounded in size too. That might be larger than people might like, but
I'm not all that excited about a new protocol that is more expensive to
operate than an old one in some corner case.
On May 14, 2014 1:37 PM, <[email-masked]> wrote:

> >> Nearly all of the problems brought up w.r.t. t-e gzip are also true for
> C-E
> >> gzip. This one is no exception.
> it, and
> available for

---

From: Johnny Graettinger <[email-masked]>
Date: Wed, 14 May 2014 14:40:57 -0700

> or you want gateways to ignore this requirement and introduce interop

An intermediary MUST decompress payloads, as the specification says.

In the extreme hypothetical case of an intermediary which has lots of
clients which don't send a-e: gzip, and which is facing DoS at current load
levels, then passing through c-e: gzip is a non-conformant but effective
DoS mitigation which is *in-practice* unlikely to break the majority of h1
clients. Yes, this breaks spec, but if decompression DoS is an actual
concern (and with a nod to Martin's point here), it's a reasonable escape
valve.

---

From: Martin Thomson <[email-masked]>
Date: Wed, 14 May 2014 14:58:23 -0700

What Johnny said. I also note the possibility of just dropping things on
the floor, which is the ultimate end state in successful DoS attacks.

I'd be concerned if the commitment were unbounded in some way (other than
time, which is manageable), but I haven't seen any claim to that effect.
On May 14, 2014 2:43 PM, "Johnny Graettinger" <[email-masked]>
wrote:

> DoS mitigation which is *in-practice* unlikely to break the majority of
> h1 clients. Yes, this breaks spec, but if decompression DoS is an actual

---

From: Roberto Peon <[email-masked]>
Date: Wed, 14 May 2014 14:58:33 -0700

inflate size-computation is: (1 << windowBits) + 1440*2*sizeof(int)
windowBits can be as large as 15, thus at least 44k

So, we have each stream potentially allocating and keeping around 44k, and
an unbounded or large number of streams.

The client can largely decide how many streams to create and it can
(guaranteed) leave them idle for as long as it wants (until the proxy
finally closes the stream).
Yes, the server can reduce the max parallelism, but then the protocol is
not doing what it was intended to do.

With 100 streams, we're talking about 4.22 megabytes of uncontrolled buffer.
That is *WAY* more than the typical static-cost for a connection, which the
server can otherwise control to a few bytes, and perhaps two orders of
magnitude larger than typical/desired in-use costs for a connection.

Even better, the proxy may be forced into this scenario because of flow
control, when it is unable to forward bytes onward to the destination.
-=R

On Wed, May 14, 2014 at 2:18 PM, Martin Thomson <[email-masked]>wrote:

>> >> Nearly all of the problems brought up w.r.t. t-e gzip are also true
>> for C-E
>> existing h1

---

From: Matthew Kerwin <[email-masked]>
Date: Thu, 15 May 2014 09:07:22 +1000

I've just had a quick read through P2 and it appears, unless I've missed a
hidden reference somewhere, nothing actually forbids a sender from using an
unsupported content coding, as long as it includes the appropriate
Content-Encoding header.

So why not just change the current text to "SHOULD decompress" and let the
gateway do the best it can?

If the call is, for example, between ignoring a cache-control:no-transform
header and unzipping a payload, making the service unusable with a 40x
Unacceptable response (sorry I forget the code ATM. 406?), or just sending
the content-coded payload as is (which, BTW, sticks it to those extant 1.1
proxies that strip a-e headers), I think the gateway should be able to
choose what it thinks will work best. Especially if that choice can be
reconfigured over time (much easier than revising the spec and rolling out
a new gateway).

---

From: Martin Thomson <[email-masked]>
Date: Wed, 14 May 2014 18:48:05 -0700

Yep, it's several orders of magnitude more memory, worst case, than not
decompressing. Which seems like it might well be the corner case.

But misbehavior, or simple overloading, have relatively straightforward
detection and mitigation techniques.  Well behaved clients, which form the
bulk of everyday requests, should require a minimal commitment to support.
I doubt that you would have much more than 100k open streams requiring
decompression, even with a total pool of 10 million connections. A few
Gbytes is hardly a major capital outlay.

Maybe I'm completely wrong, and you can prove it, but those numbers just
don't scare me that much.

I am down with Matthew's suggestion here to lift the MUST. Though I note
that there are cases where this places an intermediary between a rock and a
hard place in terms of conflicting requirements. Maybe we can note that an
intermediary /could/ decompress and leave the normative text out of it.
On May 14, 2014 3:58 PM, "Roberto Peon" <[email-masked]> wrote:

> That is *WAY* more than the typical static-cost for a connection, which
> the server can otherwise control to a few bytes, and perhaps two orders of
>> Assuming that you employ flow control, the only commitment an
>> intermediary makes when decompressing is the decompression context for each
>> stream. That is bounded in size too. That might be larger than people might
>> like, but I'm not all that excited about a new protocol that is more
>> expensive to operate than an old one in some corner case.

---

From: Roberto Peon <[email-masked]>
Date: Wed, 14 May 2014 19:08:59 -0700

A site can always simply RST every stream that has that bit set, I suppose.
It would have the effect of killing the feature, but that would be a
reasonable compromise to ensure reliability.

-=R

On Wed, May 14, 2014 at 6:48 PM, Martin Thomson <[email-masked]>wrote:

>> So, we have each stream potentially allocating and keeping around 44k,
>> and an unbounded or large number of streams.
>>
>> On Wed, May 14, 2014 at 2:18 PM, Martin Thomson <[email-masked]
>> > wrote:
>>

---

From: Amos Jeffries <[email-masked]>
Date: Thu, 15 May 2014 19:56:22 +1200

> don't scare me that much.

That was with 100 streams. The default/minimum in h2.

A typical Squid intermediary already has to expect between 1k and 10k
clients in any given second of the day. (Squid is not exactly known for
its high levels of client capacity).
 Meaning the RAM requirement just jumped up to 40GB of active state.

> intermediary /could/ decompress and leave the normative text out of it.

I am +1 on relaxing the MUST. Although removing the implicit gzip
entirely and making any encoding stay explicit would be better.

Amos

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 15 May 2014 20:53:16 +1000

On 15 May 2014, at 11:48 am, Martin Thomson <[email-masked]> wrote:

> I am down with Matthew's suggestion here to lift the MUST. Though I note that there are cases where this places an intermediary between a rock and a hard place in terms of conflicting requirements. Maybe we can note that an intermediary /could/ decompress and leave the normative text out of it.

That makes sense to me…

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

---

From: <[email-masked]>
Date: Thu, 15 May 2014 11:42:06 +0000

On Thursday,15 May 2014 12:53, Mark Nottingham wrote:
> On 15 May 2014, at 11:48 am, Martin Thomson <[email-masked]<mailto:[email-masked]>> wrote:

>> I am down with Matthew's suggestion here to lift the MUST. Though I note that there

>> are cases where this places an intermediary between a rock and a hard place in terms

>> of conflicting requirements. Maybe we can note that an intermediary /could/

>> decompress and leave the normative text out of it.

> That makes sense to me...

Let's be more clear.  That only makes sense _if_ you are assuming acceptance of Roberto's proposed "uncompressed-*" headers solution. Otherwise this doesn't solve any of the problems brought up by Matthew, Julian, myself and others with respect to etag, no-transform, metadata within the entity body, etc...

On Tuesday,29 April 2014 22:29, Roberto Peon Wrote:

> [SNIP]

> Servers seeing an implicit gzip a-e and sending a compressed entity MAY include an

> additional header field, ":uncompressed-etag" ...

> [SNIP]

I take issue with the MAY.  IMO, if the server wants to use implicit gzip it MUST include the "uncompressed-*" header fields, if such a header would have been sent with the corresponding entity with c-e: identity. Otherwise it forces the intermediary into a position where it has to either 1) decompress and break the metadata, or, 2) forward the response as-is and possibly cause inter-op issues (on second thought, maybe this a desirable feature for Roberto and others?).

Finally, I also would like to see text added to Roberto's proposal about how servers should deal with range requests with respect to implicit c-e gzip.  As I've pointed out many times, the range n-m of a c-e gzip entity is NOT equal to the range n-m of the entity's c-e identity encoding. Example text:

If a server elects to service a range request, it MUST NOT use implicit gzip content encoding.

<<<

As I pointed out earlier though, this opens up loop-holes for intermediaries to work around implicit gzip...

> Of course the server could simply disable Range requests (i.e. always send the full c-e gzip response - which is legal).

> I would argue that this will also degrade the user experience as there are more and more users browsing on spotty

> networks (e.g. Safari doesn't use range requests [1] and it drives me crazy every time I'm loading a page and there

> is a break in network connectivity on the subway, because then it has to start all over).

---

From: Matthew Kerwin <[email-masked]>
Date: Sat, 17 May 2014 09:38:48 +1000

On May 15, 2014 9:42 PM, <[email-masked]> wrote:
> Let's be more clear.  That only makes sense _if_ you are assuming
acceptance of Roberto's proposed "uncompressed-*" headers solution.
Otherwise this doesn't solve any of the problems brought up by Matthew,
Julian, myself and others with respect to etag, no-transform, metadata
within the entity body, etc...

Nnnno... I think it resolves the issue I had, even without any extra
details. Right now a server is well within its rights to completely ignore
any and all Accept-* headers; it's not the best for interop, but it's legal
within the spec (406 might be better, but also not always great for
interop).

The "MUST decompress" effectively made gateways act as origins for certain
responses, but they didn't have a choice about how to deal with this
interop issue. By not saying anything we grant them the choice of
decompressing, or sending compressed, or 406ing.

If anything I'd probably appreciate something that warns H2 clients not to
rely on implicit a-e:gzip, because servers might treat implicit and
explicit headers differently.

I still definitely prefer not introducing implicit support in the first
place.

> > additional header field, ":uncompressed-etag" …
>
> > [SNIP]
>
>
>
> I take issue with the MAY.  IMO, if the server wants to use implicit gzip
it MUST include the "uncompressed-*" header fields, if such a header would
have been sent with the corresponding entity with c-e: identity. Otherwise
it forces the intermediary into a position where it has to either 1)
decompress and break the metadata, or, 2) forward the response as-is and
possibly cause inter-op issues (on second thought, maybe this a desirable
feature for Roberto and others?).
>
>
>
>
>
> Finally, I also would like to see text added to Roberto's proposal about
how servers should deal with range requests with respect to implicit c-e
gzip.  As I've pointed out many times, the range n-m of a c-e gzip entity
is NOT equal to the range n-m of the entity's c-e identity encoding.
Example text:
> As I pointed out earlier though, this opens up loop-holes for
intermediaries to work around implicit gzip...
> > + Or, if the server is really smart, strip a-e gzip and split the
request into two separate range requests for the entire content:
> > Of course the server could simply disable Range requests (i.e. always
send the full c-e gzip response - which is legal).
>
> > I would argue that this will also degrade the user experience as there
are more and more users browsing on spotty
>
> > networks (e.g. Safari doesn’t use range requests [1] and it drives me
crazy every time I’m loading a page and there
> > [1]
http://lists.w3.org/Archives/Public/ietf-http-wg/2014AprJun/0112.html

---

From: <[email-masked]>
Date: Sat, 17 May 2014 18:10:17 +0000

>> ... [Matthew's suggestion to lift the MUST requirement for intermediaries to decompress]

>> only makes sense _if_ you are assuming acceptance of Roberto's proposed

>> "uncompressed-*" headers solution. Otherwise this doesn't solve any of the problems

>> brought up by Matthew, Julian, myself and others with respect to etag, no-transform,

>> metadata within the entity body, etc...

> ... Right now a server is well within its rights to completely ignore any and all Accept-* headers;

I disagree. According to 'Section 5.3.4 Accept-Encoding' of HTTP-p2 [1], only if a client does not include an Accept-Encoding header, then a server can choose any encoding…

A request without an Accept-Encoding header field implies that the

user agent has no preferences regarding content-codings.  Although

this allows the server to use any content-coding in a response, it

does not imply that the user agent will be able to correctly process

all encodings. [1]

Furthermore, an empty Accept-Encoding field implies identity is the only acceptable coding...

An Accept-Encoding header field with a combined field-value that is

empty implies that the user agent does not want any content-coding in

response.  If an Accept-Encoding header field is present in a request

and none of the available representations for the response have a

content-coding that is listed as acceptable, the origin server SHOULD

send a response without any content-coding. [1]

It says nothing about being able to completely ignore the Accept-Encoding header.

So I still stand behind my statement that lifting the MUST requirement for gateway decompression doesn’t solve any of the problems.

> it's not the best for interop, but it's legal within the spec (406 might be better, but also not always great for interop).

> The "MUST decompress" effectively made gateways act as origins for certain responses,

> but they didn't have a choice about how to deal with this interop issue. By not saying anything we grant them the choice of decompressing, or sending compressed, or 406ing.

> I still definitely prefer not introducing implicit support in the first place.

Agreed.

[1] http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.4

---

From: Matthew Kerwin <[email-masked]>
Date: Mon, 19 May 2014 07:53:56 +1000

On May 18, 2014 4:10 AM, <[email-masked]> wrote:
> I disagree. According to 'Section 5.3.4 Accept-Encoding' of HTTP-p2 [1],
only if a client does not include an Accept-Encoding header, then a server
can choose any encoding…
> send a response without any content-coding. [1]

This. The only normative language in the whole thing, and it's a SHOULD.
"If you can't serve what the client wants, you should serve it uncoded, but
we're cool for you to second-guess the protocol if called for by
circumstances." (Amusingly it doesn't say that you should send an
acceptable representation if you have one.)

At the boundary between 1.1 and 2, the gateway either acts as a proxy (by
not transforming), or an origin. If it acts as an origin it already
inherits the requirements you referenced. Saying "MUST decompress" means
the gateway must act as a second-class origin -- it can't choose to be a
proxy, but it doesn't get the same SHOULD options as any other origin.

> So I still stand behind my statement that lifting the MUST requirement
for gateway decompression doesn’t solve any of the problems.

Except for the MUST decompress/MUST NOT transform issue, which was my big
sticker.

Stepping back to the roots: jerk proxies hurt performance by altering a-e
headers, and capitalist servers hurt interop by ignoring them.

If we keep the "MUST support gzip" directive then new (h2) proxies lose the
motivation to be jerks. Then, if we let gateways do what they like, they
get to choose on a case-by-case basis whether the jerks or the capitalists
win, on the 1.1 side of the gateway. In that case I prefer to let market
forces and/or experience drive the decision, rather than our assumptions
here; and as (I think) I said before, it's much easier to update proxy
config than roll out a new protocol. Thus, non prescriptive language is to
be preferred.

Roberto, you said that interop issues came up as a result of servers
assuming a-e:gzip; can you tell us what they actually were? Would it hurt
the existing (1.1) web if they kept happening? And by extension, would they
hurt the h2 web if they carried over?

---

From: Martin Thomson <[email-masked]>
Date: Sun, 18 May 2014 16:18:42 -0700

Yes, I think that Matthew's analysis is correct. It is probably not ideal,
but th is seems like a case where server (out really intermediary)
discretion wins out. We might speculate that this is intended to provide an
escape hatch for over constrained scenarios. Perhaps we've just created
another such scenario.
On May 18, 2014 5:53 PM, "Matthew Kerwin" <[email-masked]> wrote:

> If we keep the "MUST support gzip" directive then new (h2) proxies lose
> the motivation to be jerks. Then, if we let gateways do what they like,
> they get to choose on a case-by-case basis whether the jerks or the
> capitalists win, on the 1.1 side of the gateway. In that case I prefer to
> let market forces and/or experience drive the decision, rather than our
> assumptions here; and as (I think) I said before, it's much easier to
> update proxy config than roll out a new protocol. Thus, non prescriptive
> language is to be preferred.
>

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 19 May 2014 10:47:33 +1000

Right. We’re not saying that this solves the issue at hand — only that it improves the spec to downgrade this requirement.

Cheers,

On 19 May 2014, at 9:18 am, Martin Thomson <[email-masked]> wrote:

> Yes, I think that Matthew's analysis is correct. It is probably not ideal, but th is seems like a case where server (out really intermediary) discretion wins out. We might speculate that this is intended to provide an escape hatch for over constrained scenarios. Perhaps we've just created another such scenario.
> 
> This. The only normative language in the whole thing, and it's a SHOULD. "If you can't serve what the client wants, you should serve it uncoded, but we're cool for you to second-guess the protocol if called for by circumstances." (Amusingly it doesn't say that you should send an acceptable representation if you have one.)
> 
> At the boundary between 1.1 and 2, the gateway either acts as a proxy (by not transforming), or an origin. If it acts as an origin it already inherits the requirements you referenced. Saying "MUST decompress" means the gateway must act as a second-class origin -- it can't choose to be a proxy, but it doesn't get the same SHOULD options as any other origin.
> 
> Except for the MUST decompress/MUST NOT transform issue, which was my big sticker.
> 
> Stepping back to the roots: jerk proxies hurt performance by altering a-e headers, and capitalist servers hurt interop by ignoring them.
> 
> If we keep the "MUST support gzip" directive then new (h2) proxies lose the motivation to be jerks. Then, if we let gateways do what they like, they get to choose on a case-by-case basis whether the jerks or the capitalists win, on the 1.1 side of the gateway. In that case I prefer to let market forces and/or experience drive the decision, rather than our assumptions here; and as (I think) I said before, it's much easier to update proxy config than roll out a new protocol. Thus, non prescriptive language is to be preferred.
> 
> Roberto, you said that interop issues came up as a result of servers assuming a-e:gzip; can you tell us what they actually were? Would it hurt the existing (1.1) web if they kept happening? And by extension, would they hurt the h2 web if they carried over?
>