Re: Call for Adoption: Bootstrapping WebSockets with HTTP/2

On 11/24/2017 05:52 PM, Loïc Hoguin wrote:
> Hello,
> 
> On 11/22/2017 08:35 AM, Mark Nottingham wrote:
>> As discussed in Singapore, this is a Call for Adoption of 
>> Bootstrapping WebSockets with HTTP/2:
>>    https://tools.ietf.org/html/draft-mcmanus-httpbis-h2-websockets-02
>>
>> So far there seems to be strong interest in this draft; please forward 
>> any further thoughts (both for or against) on list in the next week, 
>> when we'll make a decision.
> 
> I've been putting some thoughts into implementing this and there's one 
> difference betwwen h1-websocket and h2-websocket that I'm uneasy about: 
> in h1 the server could receive a Websocket upgrade request, ignore it 
> and send a normal 200 response with a representation of the resource. In 
> h2 it can only error out.
> 
> I feel that this difference in behavior ought to be pointed out in the 
> RFC because depending on how the server is implemented you need to be 
> careful about this.
> 
> For example my server currently receives a Websocket upgrade request and 
> starts processing it like any normal request (h1 or h2): by passing it 
> to user code and letting the user decide what to do: upgrade or not. The 
> user could very well send a 200 response here.

libwebsockets generally has the same approach to pass things to a 
user-provided callback to decide what to do.  But eg, we have different 
callback reasons coming according to the connection upgrade state; HTTP 
connections send different callback reasons for established / rx / 
writable / close than do connections in the ws state for example.

> Now with h2 I would like to keep this same interface however I cannot 
> allow sending a 200 response anymore because a 200 response to CONNECT 
> means we accept the Websocket connection. If I see the user try to 
> handle the request as a normal HTTP request I have to fail the CONNECT, 
> otherwise proceed with the upgrade. This is in contrast with h1 where 
> the user can do what they want without such restrictions.

To implement the CONNECT processing for this, lws parses it internally 
and filters on the upgrades it understands, so lws will fail it out if 
it's not exactly upgrading to "websocket" and lws will send the 200 if 
it likes it, and adapt the connection state to ws-over-h2.

> To summarize:

Step zero: this implementation that doesn't actually understand and 
handle CONNECT upgrades wrongly sent the nondefault SETTING that says 
that it does understand them.

> - h1 ws upgrade: OK to either upgrade or ignore the upgrade and send 200
> - h2 ws upgrade: upgrade is via a 200 response, can't ignore the upgrade 
> request and respond with a representation of the resource, be careful!

It can do that... but the connection won't work because it's not 
upgraded to ws... it's not half-working either, it's not sending ws 
framing.  So the guy writing the user code will very quickly notice no 
ws packets are passing.

IIUI he can't accidentally fall into this because he has to send the 
non-default SETTING enabling it.  So we are just saying "implementations 
may be broken" I think...  (no doubt mine amongst them until it can be 
tested on a compliant client).

-Andy

> ***
> 
> I also have a nitpick:
> 
>     [RFC6455] requires the use of Connection and Upgrade headers that are
>     not part of HTTP/2.  They MUST not be included in the CONNECT request
>     defined here.
> 
> Probably should be a "MUST NOT".
> 
> Thanks,
> 

Received on Friday, 24 November 2017 10:59:55 UTC