- From: Lucas Pardue <lucaspardue.24.7@gmail.com>
- Date: Wed, 18 Dec 2024 10:50:35 +0000
- To: Willy Tarreau <w@1wt.eu>
- Cc: HTTP Working Group <ietf-http-wg@w3.org>, Patrick McManus <mcmanus@ducksong.com>
- Message-ID: <CALGR9oYpiOq+Vk_GbdZo_Aooou-fP=Yn_+x1rcFcnrUbtg7Psw@mail.gmail.com>
Hi Willy, Just a brief reply that this sounds like its also related to draft-ietf-httpbis-optimistic-upgrade [1]. Cheers Lucas [1] https://httpwg.org/http-extensions/draft-ietf-httpbis-optimistic-upgrade.html On Wed, 18 Dec 2024, 10:33 Willy Tarreau, <w@1wt.eu> wrote: > Hi! > > RFC8441 ("Bootstrapping WebSockets with HTTP/2") indicates how > to deal with an Upgrade over HTTP/2. To make it short, HTTP/1's > Connection+Upgrade->101 becomes a CONNECT+:protocol->200 in H2. > The RFC specifies a :protocol pseudo-header that allows to use > the mechanism beyond Websocket. > > A while ago, we've implemented the mechanism in haproxy and we > support the upgrade from H1+Upgrade to H2+CONNECT. So far it > works fine for our users. > > A few months ago we got a report of breakage[1] that unveiled > something unexpected: given that CONNECT doesn't support a > request body, we had simplified our support for Upgrade and > completely rejected any request body at the H1 layer (so that > we could fail early when not knowing if the output would be in > H1 or H2). But doing so we accidentally broke support for the > "Docker Engine API" protocol over H1. That's how we discovered > that some protocols were relying on POST + Upgrade! (maybe it's > the only one, I don't know, it was the first report in a few > years of existence). > > Thus, for now we've worked around the problem so that our code > now rejects the upgrade only on the outgoing H2 side when facing > a body, but the problem remains that the mechanism proposed by > RFC8441 doesn't offer provisions for completely transporting H1 > over H2, nor replacing H1 with H2. Indeed, users of this docker > engine protocol will need to limit themselves to H1 when talking > to servers or other proxies. It's a bit sad, and I liked the idea > of using the semantically-close CONNECT for this. > > To me, it looks like the limitations are shared among multiple > causes: > - the docker engine API relies on upgrades after a POST, which are > not much common, and even never mentioned in any of the upgrade > specs (2817, 7230, 9110), though common sense dictates that it's > expected to work fine since the client cannot know whether the > server will accept the upgrade or not. I.e. it's natural to > think that the server is expected to consume the whole request > body before upgrading, or at least drain it after rejecting the > upgrade. > > - RFC8441 that proposes to use the CONNECT method for the tunnel, > while CONNECT itself is defined as "not having content" (9110) > or "not having semantics" (7231), which looked fine for websocket > but not necessarily for others (that were not identified by then). > > - the use of RFC8441 for non-websocket protocols (but if not usable, > what could be the point of ":protocol" ?) > > I really don't know what could reasonably be done at this point to > address that incompatibility. Here are a few ideas: > - we could decide that in the context of RFC8441, CONNECT works a bit > like GET in that by default the request has no message body unless > it is explicitly advertised, and in this case the request cannot > succeed until it's entirely consumed. That sounds quite reasonable > since this would remove exceptions, and not change anything for > existing implementations that don't look for that message body. > That does not solve the situation for request bodies sent using > chunked encoding however. > > - we could imagine a new method that does like CONNECT but also > covers the message body. Same as above, there are still no > provisions in H2+ to transmit a chunked body and delimit the > part that belongs to the request message and the part that > is to be tunnelled. And I'm personally not convinced about the > improved interoperability of a new method. > > - we could explicitly state that POST+Upgrade is strictly forbidden, > but we now know it's already in use and working fine for at least > one implementation. > > - or we could do nothing and consider that some parts of HTTP/1 will > remain HTTP/1 forever and will not be transportable over newer > versions. I'm not fundamentally against it but it would warrant > some extra documentation (especially in the H1 related specs) to > discourage such use so that we make sure no new protocol adopts > them and stay stuck in a corner. > > I'd say that the first approach (tolerating content-length with > CONNECT when :protocol is used) has my preference. It will not > permit chunked requests but should cover the vast majority of use > cases where the server expects a body before deciding to upgrade > (after all not all HTTP/1 servers support chunked requests either). > > But I'm interesting in ideas and opinions others might have. > > Thanks! > Willy > > [1] https://github.com/haproxy/haproxy/issues/2684 > >
Received on Wednesday, 18 December 2024 10:50:52 UTC