BUG/MEDIUM: stream-int: Disable connection retries on plain HTTP proxy mode
Since the commit 7b69c91e7 ("BUG/MAJOR: stream-int: always detach a faulty
endpoint on connect failure"), the connection is released on connect failure. So
information carried by this connection are lost. Most of time, it is not an
issue, because the destination address is set during the connect [1]. But when
the plain HTTP proxy mode is enabled, via http_proxy option, the destination
address is set during the request analysis. So, if a connect failure happens,
the address is lost and there no way to set it on retry.
There are 2 ways to fix this bug:
* Backport the commit "MAJOR: stream: store the target address into
s->target_addr" from the 2.1. But it depends on others commits and it is
dangerous to backport huge changes in a stable version.
* Add a field to copy the address in the stream on connect failure. But it
will require 128 extra bytes for this only purpose.
At the end, the HTTP proxy mode is not so common. There is no DNS resolution,
only pure IP addresses are supported. It is pretty limited for a forward
proxy. Because it is not a common usage, we decided to simply disable the
connection retries in this case. Releases 2.1 and 2.2 (LTS) don't suffer of this
limitation. If you need to have connection retries with the HTTP proxy mode
enabled, use one of these versions.
[1] This part was fixed by the commit "BUG/MAJOR: stream: Mark the server
address as unset on new outgoing connection".
There is no direct mainline commit ID for this fix, and it must not be
backported as it's solely for 2.0.
diff --git a/src/stream.c b/src/stream.c
index 3f1ee8f..080189e 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -751,6 +751,19 @@
si->conn_retries = 0;
}
}
+ else if (s->be->options & PR_O_HTTP_PROXY) {
+ /*
+ * Disable connection retries on plain HTTP proxy mode, because
+ * on connection failure, the connection is detached from the SI
+ * and released. So the address is definitely lost. It is a 2.0
+ * limitation only. Disabling connection retries is the easiest
+ * way to work around this limitation in this very particular
+ * case (and no so common). Try the 2.2 if it is a problem (or
+ * report a bug).
+ */
+ if (!si->end) /* endpoint already detached */
+ si->conn_retries = 0;
+ }
/* ensure that we have enough retries left */
si->conn_retries--;