Re: Ambiguity on HTTP/3 HEADERS and QUIC STREAM FIN requirement

Willy Tarreau <> Fri, 17 June 2022 04:57 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 7D427C157B59 for <>; Thu, 16 Jun 2022 21:57:06 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.661
X-Spam-Status: No, score=-2.661 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, MAILING_LIST_MULTI=-1, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id p6B12psxHQ-W for <>; Thu, 16 Jun 2022 21:57:04 -0700 (PDT)
Received: from ( []) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by (Postfix) with ESMTPS id 42E81C14F75F for <>; Thu, 16 Jun 2022 21:57:03 -0700 (PDT)
Received: from lists by with local (Exim 4.92) (envelope-from <>) id 1o23zm-0001fT-QZ for; Fri, 17 Jun 2022 04:54:10 +0000
Resent-Date: Fri, 17 Jun 2022 04:54:10 +0000
Resent-Message-Id: <>
Received: from ([]) by with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from <>) id 1o23zi-0001ea-VG for; Fri, 17 Jun 2022 04:54:06 +0000
Received: from ([] by with esmtp (Exim 4.92) (envelope-from <>) id 1o23zh-0001y3-DN for; Fri, 17 Jun 2022 04:54:06 +0000
Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 25H4rUJc030373; Fri, 17 Jun 2022 06:53:30 +0200
Date: Fri, 17 Jun 2022 06:53:30 +0200
From: Willy Tarreau <>
To: Martin Thomson <>
Cc:, Amaury Denoyelle <>
Message-ID: <>
References: <YqsBZ0M4lDXGRQTo@miskatonic> <> <> <> <>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <>
User-Agent: Mutt/1.10.1 (2018-07-13)
Received-SPF: pass client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-4.9
X-W3C-Hub-Spam-Report: BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, W3C_AA=-1, W3C_IRA=-1, W3C_WL=-1
X-W3C-Scan-Sig: 1o23zh-0001y3-DN 88853a327fca3610b817545ad7798c99
Subject: Re: Ambiguity on HTTP/3 HEADERS and QUIC STREAM FIN requirement
Archived-At: <>
X-Mailing-List: <> archive/latest/40141
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>

Hi Martin!

On Fri, Jun 17, 2022 at 10:00:50AM +1000, Martin Thomson wrote:
> David's approach is the ideal one, but there are others that trade some
> downsides for performance.

Probably, but I'm still seeing it as a workaround. I mean, since HTTP/1.0
we've been used to know when receiving a full headers block the entire
list of the header fields. And it looks like with H3 the headers block
is uncertain at the end of a HEADERS frame. I'm a bit concerned about
long-term impacts, especially when the ambiguity affects the presence
or absence of a body. The risk that we start to see intermediaries pass
the header block as-is to HTTP/1, followed by the contents of subsequent
DATA frames is non-negligible, and that would create new request smuggling

Conversely, requiring to wait (even a bit) risks to encourage bad behaviors
such as clients sending the FIN very late, which brings slowloris back.

I think that this situation is not good at all for interoperability and
that we should at least pass the word about it to encourage implementations
to signal that they know there is no data following the HEADERS frame.
I suspect we should really file an errata proposing to add something
like the following, at least to make sure implementations are aware of
this problem:

   A sender which knows that no data follows the headers block SHOULD
   signal the end of the message by setting the FIN bit along with the
   HEADERS frame. A receiver that processes a HEADERS frame without
   seeing a FIN bit MAY expect more data to follow regardless of the
   HTTP method used.

From what Amaury told me, in the interop tests, all client implementations
but two already proceed like this, which is not surprising since content
producers normally know whether or not they're willing to pass a body,
and gateways from other HTTP versions already have the information
available. Thus I think it would still be better to limit the risk of
proliferation of an ambiguous behavior.

> It is also possible to generate a response to an incomplete request if you
> are confident that anything that might follow won't change the response.
> (That's generally true for any HTTP request.)  In this case, you have a
> complete header block and it is a GET request.  Though you might get content,
> you probably won't.  Deciding to serve the answer isn't likely to cause
> problems.  It's a tiny gamble, but one with modest costs: if you do get
> content, then you committed to ignoring it rather than generating an error.
> You might be able to use RESET_STREAM if you care about signaling an error
> and the response hasn't already been delivered.  The real loss there is that
> you can't signal at the HTTP layer.

Sure but while you can often do this when you're a server, you practically
can't when you're a gateway, because that would require to adjust the
behavior per-URI. Not only it's a real problem in terms of deployments
(think about an edge load-balancer deployed in front of a massive hosting
infrastructure with tens of thousands of hosted clients who would find it
surprising that the hosting company requires them to declare all of their
content-aware URIs), but sometimes it will not even be applicable due a
chicken-and-egg problem by which you need a complete headers block to
start to process HTTP and apply processing rules, and you'll need to do
that to decide that the headers block is complete.