Subject: Re: [Technical Errata Reported] RFC7540 (5249)

From: Loïc Hoguin <[email-masked]>
Date: Fri, 2 Feb 2018 10:43:38 +0100

On 02/01/2018 07:32 AM, Willy Tarreau wrote:
> On Thu, Feb 01, 2018 at 12:43:53PM +1100, Martin Thomson wrote:
>> The observation is correct.  However, I'm not sure that this is the
>> solution I would choose.  I'm not sure, but I think that an empty
>> header field would cause problems.
> 
> Some intermediaries risk to drop it, considering that empty is equivalent
> to absent.

I'm curious about this as I don't recall reading this in the RFCs. What 
is related to this is:

4.3  TE

    If the TE field-value is empty or if no TE field is present, the only
    acceptable transfer coding is chunked.  A message with no transfer
    coding is always acceptable.

This matches what you're saying.

5.4  Host

    If the authority component is missing or
    undefined for the target URI, then a client MUST send a Host header
    field with an empty field-value.

This seems contrary to what you're saying since the Host header is 
mandatory and dropping it would lead to errors further on.

RFC 7231 talks about empty Accept-Encoding and Allow headers where the 
value being empty has a different meaning than the header not being there.

RFC 7540 has no mention of empty headers except saying that :path must 
not be empty.

So my understanding is that intermediaries dropping empty header fields 
would be an error. Maybe dropping the empty TE header field would make 
sense but this isn't true of all headers.

Considering this I don't see why the HTTP2-Settings header can't be 
empty. Been working for me, at least.

-- 
Loïc Hoguin
https://ninenines.eu

---

From: Amos Jeffries <[email-masked]>
Date: Fri, 2 Feb 2018 23:38:01 +1300

> Some intermediaries risk to drop it, considering that empty is equivalent

Ah, HTTP2-Settings is a connection specific header anyway.
Intermediaries are *required* to remove it when forwarding, by section
3.2.1 paragraph 4.

So removal seems to be a non-problem.

>> Maybe the right conclusion to draw
>> here is that you have to include at least one setting if you use this
>> header field.
> 
> I just tried to see if "====" would be possible as an encoding for an
> empty string, but at least the base64 utility I have here considers
> that it's an invalid input, so I suspect that it's not widely accepted
> to have an end tag at the beginning of a base64 string. Thus most
> likely as you suggest, something needs to be sent. Maybe we should
> recommend to pass one of the default settings in this case.
> 
> Willy
> 

IMO, empty field-value should be valid even if it technically is not
now. It is semantically (and literally) equivalent to a SETTINGS frame
with 0-byte payload.

On the plus side it should be a no-brainer for implementations not to
even attempt decoding a 0-byte string.

(That said the Squid tools for now send a pre-computed blob with the
default SETTINGS from the spec. Have not tried sending empty payload.)

Amos

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 2 Feb 2018 15:07:59 +0100

On Fri, Feb 02, 2018 at 10:43:38AM +0100, Loïc Hoguin wrote:
> I'm curious about this as I don't recall reading this in the RFCs. What is
> related to this is:
(...)
> This seems contrary to what you're saying since the Host header is mandatory
> and dropping it would lead to errors further on.
(...)

I know and that's what I'm doing as well when typing a request over
telnet and I don't know the host name (often you get a redirect with
the proper one by the way :-)).

I'm just saying that despite what is standard, I have already observed
a few intermediaries (abusively) dropping empty fields, so we must be
cautious about them. I've even seen this once with a CGI gateway which
would simply not pass empty fields as variables.

(...)
> would be an error.

I totally agree with you on this. I'm just warning you about some risks
in field based on some observations of this rare corner case which very
likely is not the most commonly tested.

> Maybe dropping the empty TE header field would make sense
> but this isn't true of all headers.
> 
> Considering this I don't see why the HTTP2-Settings header can't be empty.
> Been working for me, at least.

I would tend to think that H2 implementations being more modern, you take
less risks there than on older ones, but you're speaking here about an
upgrade where the header field passes over possibly old intermediaries.
That said, given that 101/Upgrade used not to work well before WebSocket
was specified, that could be another filter to ensure that you're limiting
yourself to reasonably modern devices anyway.

Cheers,
Willy

---

From: "Roy T. Fielding" <[email-masked]>
Date: Fri, 2 Feb 2018 09:09:39 -0800

> On Feb 2, 2018, at 1:43 AM, Loïc Hoguin <[email-masked]> wrote:
> I'm curious about this as I don't recall reading this in the RFCs. [...]

FTR, an empty HTTP/1 field value is definitely not equivalent to absent.  In some cases
it is an error; in other cases it has a distinct meaning (like in Accept). An intermediary
that absent-mindedly removed empty fields is just broken, but that doesn't apply to
CGI (which is not HTTP) nor HTTP2-Settings (which should be listed in Connection to
prevent it from being forwarded).

Cheers,

....Roy