Re: On the Upgrade request body limit

2015-12-08 Thread Jacob Champion

On 12/08/2015 12:45 PM, Jim Jagielski wrote:

Well

We are not NGINX. We are also not Microsoft. We don't create HTTP
response codes willy-nilly. We actually try to *honor* the actual
specs.


Yes, I agree 100%. :) Trust me, I've dealt with enough non-standard HTTP 
"extensions"; I'm not suggesting we just start doing stuff willy-nilly.


There are people who have worked on those specs on this mailing list, 
though, who might be interested in making official improvements and 
additions -- or have opinions on why those additions would not actually 
be improvements. This seemed like a nice place to talk about it, since 
we have implementation experts who can weigh in. If that's not on topic, 
I can try to take it somewhere else.


--Jacob


Re: On the Upgrade request body limit

2015-12-08 Thread Jim Jagielski
Well

We are not NGINX. We are also not Microsoft. We don't create HTTP
response codes willy-nilly. We actually try to *honor* the actual
specs.

> On Dec 8, 2015, at 3:22 PM, Jacob Champion  wrote:
> 
> I wrote this in response to Stefan's note on the zero-length request body 
> limit for h2c Upgrades, then realized it would further fragment the (already 
> massive) conversation, so here it is.
> 
> Stefan wrote:
>> It is possible, but difficult to do unless you can read the body and
> > set it aside somewhere. Which again imposes an arbitrary (for the
> > client) limit. Experience shows that this leads to design of clients
> > that work will in developments, but then encounter requests
> > usage/sites/servers that have other limits and break.
> 
> This is true of other things about HTTP/1.1 too -- how does a client figure 
> out what the maximum request size for a server is? -- but it's made harder in 
> this case by the fact that
> 
> 1) 100 Continue is sent whether the request is upgraded or not, which makes 
> it impossible to use a continue handshake to quickly determine upgrade 
> limits, and
> 
> 2) returning 413 during an upgrade would be ambiguous anyway. Is the 413 
> really related to the request target, or is it just because I tried to 
> upgrade and my request was temporarily limited?
> 
> It seems to me that we're missing something in HTTP/1.1 that would make these 
> complex Upgrade scenarios robust. IIUC, the point of allowing request bodies 
> during upgrades was to decrease the number of round trips, but if 
> implementations can't actually make use of it in practice then that's not 
> very useful...
> 
> If it were enough of a problem to fix (and I'm not claiming it is, 
> necessarily), how would we fix it? Would we need a new 1xx response (e.g. 103 
> Upgrade Declined, with headers indicating the related protocol and the reason 
> for the failure)? A new header in OPTIONS? Something else entirely?
> 
> Or is the correct "fix" to rearchitect so the limit during upgrades can be 
> exactly the same as during a normal request?
> 
> --Jacob



Re: On the Upgrade request body limit

2015-12-08 Thread Yann Ylavic
On Tue, Dec 8, 2015 at 11:43 PM, William A Rowe Jr  wrote:
> On Tue, Dec 8, 2015 at 4:17 PM, Yann Ylavic  wrote:
>>
>> Why any HTTP/1 response? If the Upgrade is accepted, ISTM that the
>> response must be Upgraded, no?
>
> The server is always free to accept or ignore the Upgrade: request... and
> once the 101-switching protocols has been sent, the connection must be
> in the offered protocol.
>
> 6.7.  Upgrade

Oh, right, but in this case the Upgrade is aborted, so there should be
no 101 switch from httpd, the whole transaction is HTTP/1 (until
possibly further request).


Re: On the Upgrade request body limit

2015-12-08 Thread Yann Ylavic
On Tue, Dec 8, 2015 at 11:00 PM, William A Rowe Jr  wrote:
>
> Apache httpd server offers limits on the number
> of incoming headers, the number of bytes in those headers, the number of
> bytes in the request line, the length of the URI.  The maximum request body
> length.  This is just one more limit, but not an actual *limitation*,
> because the request will be processed, simply not by changing protocols
> first, per RFC7230.

Agreed.

> On Tue, Dec 8, 2015 at 2:22 PM, Jacob Champion  wrote:
>>
>> 1) 100 Continue is sent whether the request is upgraded or not, which
>> makes it impossible to use a continue handshake to quickly determine upgrade
>> limits, and

100-continue is sent only if the client Expect's it, that's not mandatory.

>
>> 2) returning 413 during an upgrade would be ambiguous anyway. Is the 413
>> really related to the request target, or is it just because I tried to
>> upgrade and my request was temporarily limited?
>
> It never would.  The possible results are the normal response in http/1.1
> protocol, or 426 to tell the client it still must change protocols first.
[]
>
> Our httpd http/1.1 server
> doesn't and cannot care, it can read-ahead the same network bucket it was
> going to read anyways, and let the new protocol handler decide, very early
> or very late in the cycle, whether the upgrade will happen.  If it won't,
> httpd must continue to serve the response sticking to http/1.1.

Agreed, the module/handler can read the (HTTP/1) body if it needs it,
or ignore it, in any case the core must do the right thing for this
body, and if some Protocols was elected, do the 101 switch before any
response bytes.
For empty response (i.e. simple/single 101 response), couldn't the
module/handler simply flush?
If so, an output filter could do the job...

>
> RFC7230 is baked, expect no changes.  The request (including 100-continue +
> body) is read, the protocol is switched if possible, otherwise the response
> is sent in http/1.1.  Those are our constraints.

Agreed (again), and that constraints are not that bad ("normal"
Upgrade handshakes should not have a huge payload anyway), so we
should be able to do an Upgrade in a single round trip.


Re: On the Upgrade request body limit

2015-12-08 Thread William A Rowe Jr
On Tue, Dec 8, 2015 at 4:17 PM, Yann Ylavic  wrote:

> On Tue, Dec 8, 2015 at 11:00 PM, William A Rowe Jr 
> wrote:
> >
> > Define complex, robust.  Request (upgrade: somespec) -> 100 continue ->
> > request body <- [ http/1.1 response | 101 - switching protocols <- new
> > protocol response ].
>
> As I read the RFC, the simple(st) case is:
> Request (upgrade: somespec) -> request body <- 101 (upgrade: somespec)
> <- new protocol response or read
>

Whereas the 100-continue case is:
> Request (upgrade: somespec, expect: 100-continue) [ <- 100-continue ->
> request body ] <- 101 (upgrade: somespec) <- new protocol response or
> read
>

Right, and I didn't color the complexity of using C-L vs. T-E encoding for
the request body, either.  Both may reply in http/1.1 or with a
101-switching
followed by something recognizable (e.g. tls following handshake and filter
insertion) or inscrutable (e.g. websocket, h2c) to the http/1.1 protocol
stack.


> Why any HTTP/1 response? If the Upgrade is accepted, ISTM that the
> response must be Upgraded, no?
>

The server is always free to accept or ignore the Upgrade: request... and
once the 101-switching protocols has been sent, the connection must be
in the offered protocol.

6.7 .  Upgrade

   The "Upgrade" header field is intended to provide a simple mechanism
   for transitioning from HTTP/1.1 to some other protocol on the same
   connection.  A client MAY send a list of protocols in the Upgrade
   header field of a request to invite the server to switch to one or
   more of those protocols, in order of descending preference, before
   sending the final response.  A server MAY ignore a received Upgrade
   header field if it wishes to continue using the current protocol on
   that connection.  Upgrade cannot be used to insist on a protocol
   change.


Re: On the Upgrade request body limit

2015-12-08 Thread Jacob Champion

On 12/08/2015 03:01 PM, Yann Ylavic wrote:

Jacob,

On Tue, Dec 8, 2015 at 11:17 PM, Yann Ylavic  wrote:


As I read the RFC, the simple(st) case is:
Request (upgrade: somespec) -> request body <- 101 (upgrade: somespec)
<- new protocol response or read


Wouldn't that work for the WebSocket case?
If the new protocol wants to read after the Switch I don't think
anything prevents it...
The headers included in the 101 response could be set by a hook.


Sorry I'm responding so slowly; I'm trying to grok all the responses 
before I reply, and they're coming in fast. ;)


Yes, this works fine for the WebSocket case. WebSocket is easier because 
WebSocket upgrades are only allowed for the GET method and there is no 
request body (that I have to worry about, anyway).


The motivation for my original post wasn't WebSocket. I made it with the 
assumption (provided by Stefan) that the h2c upgrade is more limited 
than other protocol upgrades in how big a request body it can handle; 
i.e. that the specs themselves painted mod_http2 into a corner. If that 
assumption is incorrect, and there's a way for it to use the same limit 
as every other request, then I think my discussion point is moot.


--Jacob


Re: On the Upgrade request body limit

2015-12-08 Thread Jacob Champion

On 12/08/2015 02:00 PM, William A Rowe Jr wrote:

Apache httpd server offers limits on the
number of incoming headers, the number of bytes in those headers, the
number of bytes in the request line, the length of the URI.  The maximum
request body length.  This is just one more limit, but not an actual
*limitation*, because the request will be processed, simply not by
changing protocols first, per RFC7230.


I agree with your point -- that's what I was trying to point out with my 
OP -- but I think general-purpose clients that are trying to ensure 
their upgrades succeed as quickly as possible, as often as possible, and 
are thwarted in that by an invisible request body limit, might consider 
it a limitation. That the request succeeds is not necessarily their only 
design goal.



As I'll point out again in closing, h2c isn't defined by RFC7230, and if
it decides to ignore requests with bodies, that's up to mod_http2 and
other implementations.  But RFC7230 has nothing to say to h2c on this,
and rather encourages protocol implementors to accept already-read C-L
or T-E: chunked request bodies in a hand-over into their upgraded protocol.


Agreed. And like I said in my response to Yann, if it turns out that the 
arbitrary upgrade-body-limit for h2c can be done away with entirely, an 
official addition to HTTP would be completely unnecessary.



There is no need for the client to determine the upgrade limit, because
the body of the request is sent.  If the server -arbitrarily- chooses to
satisfy it, there will be a 101 following the body transmission.  But
the spec makes absolutely clear that it is the server's prerogative to
upgrade or not, irrespective of the particular upgrade requested.

If the server demands that the upgrade happen, before a request can be
honored, it must reply with a 426 until the client offers to upgrade.
If the client demands that the upgrade happen, it must perform the
simplest applicable request (e.g. OPTIONS *) with the desired upgrade
semantics and verify that the upgrade occurred.


Stefan is, I think, adding more shades of grey here. OPTIONS * is the 
most likely upgrade to succeed, but also guarantees the addition of an 
"unnecessary" (depending on your point of view) round-trip. Clients may 
be willing to make a trade-off in initial success rate for an average 
increase in performance, but not if the server implementations are so 
different that their success rate plummets.


Whether this is enough of a concern to "fix" is a matter of opinion. But 
it appears that there has already been an agreement of sorts to reject 
h2c response bodies from the major implementors, if I understood Stefan 
correctly, so they at least are concerned. It would be nice to read that 
conversation.



2) returning 413 during an upgrade would be ambiguous anyway. Is the
413 really related to the request target, or is it just because I
tried to upgrade and my request was temporarily limited?


It never would.  The possible results are the normal response in
http/1.1 protocol, or 426 to tell the client it still must change
protocols first.


I'm not sure I understand what you mean. My point was simply that while 
a pure HTTP/1.1 client implementation can try to optimize its "limits 
discovery" through the use of a 100-continue handshake, and immediately 
making adjustments if a 4xx comes back, clients have no way to apply the 
same discovery to an artificial limit on upgrade-requests.


And again, whether such a limit is justified to begin with still remains 
to be seen, I think.



Define complex, robust.  Request (upgrade: somespec) -> 100 continue ->
request body <- [ http/1.1 response | 101 - switching protocols <- new
protocol response ].


Hopefully I've clarified what I mean by this -- not "robust" in terms of 
whether the request breaks or not, but "robust" in terms of a high 
success rate for optimally-performant upgrades to h2c.


--Jacob


Re: On the Upgrade request body limit

2015-12-08 Thread Yann Ylavic
Jacob,

On Tue, Dec 8, 2015 at 11:17 PM, Yann Ylavic  wrote:
>
> As I read the RFC, the simple(st) case is:
> Request (upgrade: somespec) -> request body <- 101 (upgrade: somespec)
> <- new protocol response or read

Wouldn't that work for the WebSocket case?
If the new protocol wants to read after the Switch I don't think
anything prevents it...
The headers included in the 101 response could be set by a hook.


Re: On the Upgrade request body limit

2015-12-08 Thread Yann Ylavic
On Tue, Dec 8, 2015 at 11:00 PM, William A Rowe Jr  wrote:
>
> Define complex, robust.  Request (upgrade: somespec) -> 100 continue ->
> request body <- [ http/1.1 response | 101 - switching protocols <- new
> protocol response ].

As I read the RFC, the simple(st) case is:
Request (upgrade: somespec) -> request body <- 101 (upgrade: somespec)
<- new protocol response or read

Whereas the 100-continue case is:
Request (upgrade: somespec, expect: 100-continue) [ <- 100-continue ->
request body ] <- 101 (upgrade: somespec) <- new protocol response or
read

Why any HTTP/1 response? If the Upgrade is accepted, ISTM that the
response must be Upgraded, no?


Re: On the Upgrade request body limit

2015-12-08 Thread Jim Jagielski

> On Dec 8, 2015, at 4:00 PM, Jacob Champion  wrote:
> 
> On 12/08/2015 12:45 PM, Jim Jagielski wrote:
>> Well
>> 
>> We are not NGINX. We are also not Microsoft. We don't create HTTP
>> response codes willy-nilly. We actually try to *honor* the actual
>> specs.
> 
> Yes, I agree 100%. :) Trust me, I've dealt with enough non-standard HTTP 
> "extensions"; I'm not suggesting we just start doing stuff willy-nilly.
> 
> There are people who have worked on those specs on this mailing list, though, 
> who might be interested in making official improvements and additions -- or 
> have opinions on why those additions would not actually be improvements. This 
> seemed like a nice place to talk about it, since we have implementation 
> experts who can weigh in. If that's not on topic, I can try to take it 
> somewhere else.
> 

I agree that adding in some of the http/2 lists on this thread
would make sense.



Re: On the Upgrade request body limit

2015-12-08 Thread William A Rowe Jr
On Tue, Dec 8, 2015 at 2:22 PM, Jacob Champion  wrote:

> I wrote this in response to Stefan's note on the zero-length request body
> limit for h2c Upgrades, then realized it would further fragment the
> (already massive) conversation, so here it is.
>

And I agree to keep the other thread as clean as possible, so to your
thoughts...


> Stefan wrote:
>
>> It is possible, but difficult to do unless you can read the body and
>>
> > set it aside somewhere. Which again imposes an arbitrary (for the
> > client) limit. Experience shows that this leads to design of clients
> > that work will in developments, but then encounter requests
> > usage/sites/servers that have other limits and break.
>

That's nonsense, of course.  Apache httpd server offers limits on the
number of incoming headers, the number of bytes in those headers, the
number of bytes in the request line, the length of the URI.  The maximum
request body length.  This is just one more limit, but not an actual
*limitation*, because the request will be processed, simply not by changing
protocols first, per RFC7230.

As I'll point out again in closing, h2c isn't defined by RFC7230, and if it
decides to ignore requests with bodies, that's up to mod_http2 and other
implementations.  But RFC7230 has nothing to say to h2c on this, and rather
encourages protocol implementors to accept already-read C-L or T-E: chunked
request bodies in a hand-over into their upgraded protocol.

This is true of other things about HTTP/1.1 too -- how does a client figure
> out what the maximum request size for a server is? -- but it's made harder
> in this case by the fact that
>
> 1) 100 Continue is sent whether the request is upgraded or not, which
> makes it impossible to use a continue handshake to quickly determine
> upgrade limits, and
>

There is no need for the client to determine the upgrade limit, because the
body of the request is sent.  If the server -arbitrarily- chooses to
satisfy it, there will be a 101 following the body transmission.  But the
spec makes absolutely clear that it is the server's prerogative to upgrade
or not, irrespective of the particular upgrade requested.

If the server demands that the upgrade happen, before a request can be
honored, it must reply with a 426 until the client offers to upgrade.  If
the client demands that the upgrade happen, it must perform the simplest
applicable request (e.g. OPTIONS *) with the desired upgrade semantics and
verify that the upgrade occurred.

2) returning 413 during an upgrade would be ambiguous anyway. Is the 413
> really related to the request target, or is it just because I tried to
> upgrade and my request was temporarily limited?
>

It never would.  The possible results are the normal response in http/1.1
protocol, or 426 to tell the client it still must change protocols first.

That new protocol can make whatever demands on the protocol it wants to.
That the only acceptable upgrade to h2c will be an OPTIONS * with no
request body.  Or that POST upgrades will be refused.  Our httpd http/1.1
server doesn't and cannot care, it can read-ahead the same network bucket
it was going to read anyways, and let the new protocol handler decide, very
early or very late in the cycle, whether the upgrade will happen.  If it
won't, httpd must continue to serve the response sticking to http/1.1.

It seems to me that we're missing something in HTTP/1.1 that would make
> these complex Upgrade scenarios robust. IIUC, the point of allowing request
> bodies during upgrades was to decrease the number of round trips, but if
> implementations can't actually make use of it in practice then that's not
> very useful...
>

Define complex, robust.  Request (upgrade: somespec) -> 100 continue ->
request body <- [ http/1.1 response | 101 - switching protocols <- new
protocol response ].

The spec spells it out.  That is as clear as it gets.  One will happen, or
the other.

If it were enough of a problem to fix (and I'm not claiming it is,
> necessarily), how would we fix it? Would we need a new 1xx response (e.g.
> 103 Upgrade Declined, with headers indicating the related protocol and the
> reason for the failure)? A new header in OPTIONS? Something else entirely?
>

I was thinking about this... even within the 100-continue it might be
possible to add some commentary / hint of what might happen next.  Request
and response headers may contain (comments).

Or is the correct "fix" to rearchitect so the limit during upgrades can be
> exactly the same as during a normal request?


RFC7230 is baked, expect no changes.  The request (including 100-continue +
body) is read, the protocol is switched if possible, otherwise the response
is sent in http/1.1.  Those are our constraints.

Is there an advantage to stating no body accepted when we are free to
either upgrade or stay with http/1.1, at our whim? I'd suggest not and will
strongly object to the TLS filter behaving this way. I'll let http/2
protocol gurus argue what