Subject: httpbis-p2 : 1xx messages may not always be treated as 100

From: Willy Tarreau <[email-masked]>
Date: Tue, 6 Jul 2010 23:29:22 +0200

Hello,

since at least RFC1945 and up to at least httpbis-p2-9, it is stated in
"4. Status Code and Reason Phrase" :

   HTTP applications are not required
   to understand the meaning of all registered status codes, though such
   understanding is obviously desirable.  However, applications MUST
   understand the class of any status code, as indicated by the first
   digit, and treat any unrecognized response as being equivalent to the
   x00 status code of that class, with the exception that an
   unrecognized response MUST NOT be cached.  For example, if an
   unrecognized status code of 431 is received by the client, it can
   safely assume that there was something wrong with its request and
   treat the response as if it had received a 400 status code.

I followed that advice about a year ago when adding support for 1xx
responses in HAProxy, and that broke status 101 which till then was
working without doing anything special. The reason is that 100 is a
very special state in that it implies that a second response message
follows (possibly a 100 too BTW). 101 is a final message.

So by considering that 1xx could all be treated as 100, I broke support
for 101 because when a server replied with 101, I would wait for a
second message to come.

I think that it would be reasonable to add an exception for 1xx messages
in the statement above so that other people don't get trapped as I did
for the same reasons ("it's enough and I don't need special processing
of this one"). This is particularly true on intermediates. I rememeber
having noticed that some products don't support 101 (Pound was one of
them last year, Alteon used to be too), and it is possible that for
some of them, it is due to the same simplification.

Any opinions ?

Regards,
Willy

---

From: Yves Lafon <[email-masked]>
Date: Fri, 9 Jul 2010 12:21:23 -0400 (EDT)

> follows (possibly a 100 too BTW). 101 is a final message.

In fact, it's not that 100 is a special state, it is more because 101 is 
special.
<<
       - 1xx: Informational - Request received, continuing process
<<
    A client MUST be prepared to accept one or more 1xx status responses
    prior to a regular response, even if the client does not expect a 100
    (Continue) status message. Unexpected 1xx status responses MAY be
    ignored by a user agent.

    Proxies MUST forward 1xx responses, unless the connection between the
    proxy and its client has been closed, or unless the proxy itself
    requested the generation of the 1xx response. (For example, if a
    proxy adds a "Expect: 100-continue" field when it forwards a request,
    then it need not forward the corresponding 100 (Continue)
    response(s).)
The "prior to a regular response" show that 101 is the culprit, and not 
100.

However, 101 definition says:
<<
    The server understands and is willing to comply with the client's
    request, via the Upgrade message header field (section 14.42), for a
    change in the application protocol being used on this connection.
but Upgrade is a hop-by-hop header
<<
    The Upgrade header field only applies to the immediate connection.
    Therefore, the upgrade keyword MUST be supplied within a Connection
    header field (section 14.10) whenever Upgrade is present in an
    HTTP/1.1 message.
Meaning that Upgrade request should not be transmitted by a proxy, unless 
the proxy knows how to deal with 101 and re-add the Upgrade header (and 
act accordingly afterwards).

If the client is sending a Upgrade: header to a proxy not knowing how to 
cope with it, it should be removed, and no 101 can flow back, so the 
general rules of 1xx are still correct.

> for 101 because when a server replied with 101, I would wait for a

In your case, you are just not supporting 101 and it is fine, unless you 
forward the Upgrade headers.

-- 
Baroula que barouleras, au tiéu toujou t'entourneras.

         ~~Yves

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 9 Jul 2010 20:13:05 +0200

Hello Yves,

On Fri, Jul 09, 2010 at 12:21:23PM -0400, Yves Lafon wrote:
(...)
> In fact, it's not that 100 is a special state, it is more because 101
> is special.
> <<
> The "prior to a regular response" show that 101 is the culprit, and
> not 100.

Indeed, I agree with your analysis. The 101 could have been a 2xx, just
like a 200 in response to a CONNECT means a tunnel is established.

> Meaning that Upgrade request should not be transmitted by a proxy,
> unless the proxy knows how to deal with 101 and re-add the Upgrade
> header (and act accordingly afterwards).
> 
> If the client is sending a Upgrade: header to a proxy not knowing how
> to cope with it, it should be removed, and no 101 can flow back, so
> the general rules of 1xx are still correct.

I now see your point, except that the 101 will flow back, without the
Upgrade header, which results in the client being able to identify the
failure. This is what I've observed on my (quite old) squid here, as
well as on another commercial proxy (bluecoat I believe though not
certain).

> In your case, you are just not supporting 101 and it is fine, unless
> you forward the Upgrade headers.

Yes, indeed, that seems OK to me now. Anyway, I'm wondering if we would
not need a clear statement for this 101 case. I'm concerned about reverse
proxies and load balancers which generally don't modify the stream that
passes through them, and which will not remove the Upgrade header but
will still forward 101, processing it as 1xx. As you say this is the only
corner case, maybe we should explain the proper failure method to adopt
when 101 is not implemented (which could very well be something like
"if an intermediate receives a 101 which it cannot handle, and it is not
able to remove the Upgrade header, it must ensure by any means that the
server's response will not be forwarded back intact to the client, so
that the client does not believe the connection is upgraded. Closing the
connection is one possible solution".

Thanks for your explanations.
Willy