Subject: Re: #158: Proxy-Connection and Keep-alive

From: Mark Nottingham <[email-masked]>
Date: Sat, 3 Dec 2011 11:21:17 +1100

On 29/11/2011, at 5:01 PM, Amos Jeffries wrote:

> How about is for prose:
> "
> Proxy-Connection is now obsolete. Clients must not produce it on HTTP/1.1 requests or responses.

Yes, with editorial niggles. I think this is roughly what we have now.

> NP: existing software still uses a mixture of HTTP/1.0 and obsolete Proxy-Connection keep-alive mechanisms which differ in behaviour from HTTP/1.1. Clients should always explicitly send Connection: keep-alive or Connection: close when contacting servers having HTTP/1.0 or unknown HTTP version numbers.

That's too strong; we shouldn't require use of HTTP/1.0 mechanisms, as some implementations might make reasonable decisions to not use pconns with 1.0 servers. Besides, connection: close is the default with 1.0 anyway, so there's not reason to mention it here.

I'd really rather not get into specifying the keep-alive mechanism in HTTP/1.1, because it's deprecated, and difficult to correctly specify. Mentioning it is fine, but putting requirements around it is too much.

Cheers,

--
Mark Nottingham   http://www.mnot.net/

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 3 Dec 2011 08:22:17 +0100

Hi Mark,

> I'd really rather not get into specifying the keep-alive mechanism in HTTP/1.1, because it's deprecated, and difficult to correctly specify. Mentioning it is fine, but putting requirements around i…

But if we want Proxy-Connection to disappear, we need to indicate what else
to do, as simply removing it *will* lead to persistent connections being
disabled at many workplaces where proxies still apply 1.0 semantics. And
this is not only a performance issue but a connectivity issue, since these
workplaces sometimes make use of NTLM auth, which authenticates the connection
instead of the request, and does not work without persistent conns.

That's why I agree with Amos that we need to state something for clients
which currently make use of Proxy-Connection. In fact, a number of them
already emit both "Connection: keep-alive" and "Proxy-Connection: keep-alive"
but I'm not certain at all this is the case for all of them, and helping
them not getting trapped will save them from reverting their change when
they get breakage reports.

Maybe instead we should suggest the following :

  The Proxy-Connection header was completely obsoleted by the Connection
  header. Therefore, clients must not emit it and must use the Connection
  header instead, even with proxies running an unknown HTTP version.

I'm insisting on this point because it's not necessarily obvious that a
"Connection: keep-alive" header must be sent in an HTTP/1.1 request when
the proxy's version is unknown or 1.0.

Regards,
Willy

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 5 Dec 2011 12:01:16 +1100

> the proxy's version is unknown or 1.0.

Willy,

There are a number of problems with this.

* Your text effectively requires clients to send Connection: keep-alive under certain conditions. This is a new requirement that will very likely break existing implementations, and one that makes HTTP more complex.

* Furthermore, we don't define Keep-Alive, as it's not part of HTTP/1.1 (and therefore out of scope). It was previously abandoned as too problematic. Requiring use of a deprecated mechanism doesn't make sense.

* The primary motivation for doing so is compatibility with NTLM authentication, which is also not part of HTTP, and very clearly breaks HTTP. While we can attempt to improve interoperability for this broken extension, it cannot be at the cost of making HTTP itself more complex.

Clients choose whether to use persistent connections or not; it's up to them. If you want to make NTLM authentication more interoperable, I'd suggest you create a new I-D describing how to do so.

As a reminder, the current proposal text is:

> replace p1 A.1.2 with:
> 
> Most HTTP/1.0 implementations use a separate connection for each request. However, some implement persistent connections using the Keep-Alive negotiation mechanism described in Section 19.7.1 of [RFC2068].
> 
> In contrast, persistent connections are the default for HTTP/1.1; they do not need to be explicitly negotiated, as in HTTP/1.0. This is because there were various interoperability problems in the implementations of HTTP/1.0 persistent connections, especially when a proxy is involved.
> 
> For example, some existing HTTP/1.0 clients might send Keep-Alive to a proxy server that doesn't understand Connection, which would then erroneously forward it to the next inbound server, which would establish the Keep-Alive connection and result in a hung HTTP/1.0 proxy waiting for the close on the response. The result is that HTTP/1.0 clients must be prevented from using Keep-Alive when talking to proxies.
> 
> However, talking to proxies is the most important use of persistent connections, so that prohibition is clearly unacceptable. Some early attempts to correct this was to use the Proxy-Connection request header, but this approach was also unworkable, for similar reasons.
> 
> Therefore, some other mechanism for indicating a persistent connection was needed -- one that is safe to use even when talking to an old proxy that ignores Connection. Persistent connections are the default for HTTP/1.1 messages; we introduce a new keyword (Connection: close) for declaring non-persistence. See Section 8.1.
> 
> As a result, HTTP/1.1 clients ought not to send the Proxy-Connection or Keep-Alive header; at best, they will waste bytes in requests, and at worst they can cause interoperability problems.

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 5 Dec 2011 07:36:30 +0100

Hi Mark,

> * Your text effectively requires clients to send Connection: keep-alive under certain conditions. This is a new requirement that will very likely break existing implementations, and one that makes…

It should not as it is what they're doing *right now*. Look at a
proxy request, you'll see both "Proxy-Connection: keep-alive" and
"Connection: keep-alive".

> * Furthermore, we don't define Keep-Alive, as it's not part of HTTP/1.1 (and therefore out of scope). It was previously abandoned as too problematic. Requiring use of a deprecated mechanism doesn't…

I'm not asking to emit the Keep-alive header, rather just to suggest
clients to continue to emit "Connection: keep-alive" when they suspect
the proxy could be 1.0, as they're doing right now.

> * The primary motivation for doing so is compatibility with NTLM authentication, which is also not part of HTTP, and very clearly breaks HTTP. While we can attempt to improve interoperability for t…

In fact there are two degrees in these motivations :
  - the first one is to maintain a reasonable performance level, but it
    could be argued that if some browsers are slowed down after an upgrade
    due to loss of persistent connections, it's not dramatic, except maybe
    in the mobile world but explicit proxies are not common there ;

  - the second one is to ensure that browser vendors are not pressured by
    their users to revert the upgrade because it totally breaks what used
    to work for 10 years. And this one seems much more important to me,
    because if Proxy-Connection is still in use after so long a time, it
    precisely is because browser vendors did not find a non-breaking upgrade
    path.

In fact I don't care a dime about NTLM, I hate this broken and insecure
scheme. What I care about is that the spec can *really* be applied. If we
force developers to introduce big regressions, we all know they will revert
the spec, and what we write there is pointless.

A few years ago, I had checked a number of different proxies' behaviour,
and unfortunately I lost the traces since. What I recall is that most of
them mimicked squid's behaviour, which by then was 2.x (I didn't find
this surprizing considering that squid is the de-facto standard proxy).
Among the important points was that an 1.1 request sent without a Connection
or Proxy-Connection header was not considered a persistent connection, which
is normal for an 1.0 proxy and not expected for an 1.1 client. Clients are
already aware of this because they currently send an explicit
"Connection: keep-alive" header.

> Clients choose whether to use persistent connections or not; it's up to them.

That's precisely my point ! If they want to have persistent connections
on an 1.x proxy (where x is unknown), they need to send an explicit
"Connection: keep-alive" header. Without this, they can't chose, not
because of the protocol, but because of currently deployed products'
behaviour which apply 1.0 semantics.

> If you want to make NTLM authentication more interoperable, I'd suggest you create a new I-D describing how to do so.

Oh no, I'm really not interested in this at all, thanks ;-)

Alternatively, maybe this tip could be placed in the section on interoperabilty
with 1.0, because after all it's needed to talk to 1.0 proxies.

Best regards,
Willy

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 5 Dec 2011 18:20:30 +1100

> the proxy could be 1.0, as they're doing right now.

Browsers != all clients

> with 1.0, because after all it's needed to talk to 1.0 proxies.

That may be. My objecting is to introducing new requirements -- not advice.

Cheers,

--
Mark Nottingham
http://www.mnot.net/

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 5 Dec 2011 08:52:15 +0100

>From the beginning, I'm not suggestiong a requirement, just an advice. I
know that browser vendors will be smart enough to try various suggestions
not to get trapped. We just need to save them from causing important
regressions making their users complain.

Best regards,
Willy

---

From: Mark Nottingham <[email-masked]>
Date: Fri, 9 Dec 2011 16:27:22 +1100

OK, one more go at this.

> the proxy could be 1.0, as they're doing right now.

Understand that using Connection: keep-alive with 1.0 proxies is *precisely* the cause of the interoperability problems that led to the design of persistent connections in 1.1; because 1.0 proxies aren't required to remove the Connection: header (or what it refers to), this can result in hanging connections. 

While *most* proxies have upgraded to implement this, you cannot count on it; they aren't required to implement it in 1.0, and IME there are still some that don't. I know that the proxies that you (Willy and Amos) are implementing now don't have this problem currently, but we're concerned with the entire installed base of proxies, not just current products.

So, suggesting that they do it is too strong; there are legitimate reasons to be concerned about interoperability in this use case, and we're all about the interoperability.

See below for another go at a proposal. Personally, I think this is as far as we can go; others may feel differently (in either direction), and are encouraged to say so (I'd like to get this one nailed down).

Replace p1 A.1.2 with:

> In HTTP/1.0, each connection is established by the client prior to the request and closed by the server after sending the response. However, some implementations implement the explicitly negotiated ("Keep-Alive") version of persistent connections described in Section 19.7.1 of [RFC2068].
> 
> Some clients and servers might wish to be compatible with these previous approaches to persistent connections, by explicitly negotiating for them with a "Connection: keep-alive" request header field. However, some experimental implementations of HTTP/1.0 persistent connections are faulty; for example, if a HTTP/1.0 proxy server doesn't understand Connection, it will erroneously forward that header to the next inbound server, which would result in a hung connection.
> 
> One attempted solution was the introduction of a Proxy-Connection header, targeted specifically at proxies. In practice, this was also unworkable, because proxies are often deployed in multiple layers, bringing about the same problem discussed above.
> 
> As a result, clients are encouraged not to send the Proxy-Connection header in any requests.
> 
> Clients are also encouraged to consider the use of Connection: keep-alive in requests carefully; while they can enable persistent connections with HTTP/1.0 servers, clients using them need will need to monitor the connection for "hung" requests (which indicate that the client ought stop sending the header), and this mechanism ought not be used by clients at all when a proxy is being used.

Cheers,

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 9 Dec 2011 08:14:36 +0100

Hi Mark,

> While *most* proxies have upgraded to implement this, you cannot count on it; they aren't required to implement it in 1.0, and IME there are still some that don't. I know that the proxies that you…

That's my point too. I think that both Amos and I are willing to change our
codes to satisfy the spec if some interoperability problems are spotted. Here
I was really talking about what I'm observing in field with deployed clients.

> See below for another go at a proposal. Personally, I think this is as far as we can go; others may feel differently (in either direction), and are encouraged to say so (I'd like to get this one na…
(...)

I'm fine with this one. What's important to me is that we give at least a
clue to implementers about what issue they might face, so that they consider
some real-world tests and possibly some fallbacks for embarrassing situations.
Your version also suggests that it's better to avoid doing this when not
necessary, which is good if we want to achieve a global cleanup. Works for me.

Thanks,
Willy

---

From: Mark Nottingham <[email-masked]>
Date: Wed, 14 Dec 2011 14:12:49 +1100

OK, incorporating.

Thanks,