MEDIUM: http: move Connection header processing earlier

Till now the Connection header was processed in the middle of the http-request
rules and some reqadd rules. It used to force some http-request actions to be
cut in two parts.

Now with keep-alive, not only that doesn't make any sense anymore, but it's
becoming a total mess, especially since we need to know the headers contents
before proceeding with most actions.

The real reason it was not moved earlier is that the "block" or "http-request"
rules can see a different version if some fields are changed there. But that
is already not reliable anymore since the values observed by the frontend
differ from those in the backend.

This patch is the equivalent of commit f118d9f ("REORG: http: move HTTP
Connection response header parsing earlier") but for the request side. It
has been tagged MEDIUM as it could theorically slightly affect some setups
relying on corner cases or invalid setups, though this does not make real
sense and is highly unlikely.
diff --git a/src/proto_http.c b/src/proto_http.c
index 241dc52..e797e00 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2916,6 +2916,70 @@
 	if (!use_close_only)
 		msg->flags |= HTTP_MSGF_XFER_LEN;
 
+	/* Until set to anything else, the connection mode is set as Keep-Alive. It will
+	 * only change if both the request and the config reference something else.
+	 * Option httpclose by itself sets tunnel mode where headers are mangled.
+	 * However, if another mode is set, it will affect it (eg: server-close/
+	 * keep-alive + httpclose = close). Note that we avoid to redo the same work
+	 * if FE and BE have the same settings (common). The method consists in
+	 * checking if options changed between the two calls (implying that either
+	 * one is non-null, or one of them is non-null and we are there for the first
+	 * time.
+	 */
+	if (!(txn->flags & TX_HDR_CONN_PRS) ||
+	    ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) {
+		int tmp = TX_CON_WANT_KAL;
+
+		if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
+			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
+			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
+				tmp = TX_CON_WANT_TUN;
+
+			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
+			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
+				tmp = TX_CON_WANT_TUN;
+		}
+
+		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
+		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
+			/* option httpclose + server_close => forceclose */
+			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
+			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
+				tmp = TX_CON_WANT_CLO;
+			else
+				tmp = TX_CON_WANT_SCL;
+		}
+
+		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
+		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
+			tmp = TX_CON_WANT_CLO;
+
+		if ((txn->flags & TX_CON_WANT_MSK) < tmp)
+			txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
+
+		if (!(txn->flags & TX_HDR_CONN_PRS) &&
+		    (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
+			/* parse the Connection header and possibly clean it */
+			int to_del = 0;
+			if ((msg->flags & HTTP_MSGF_VER_11) ||
+			    ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
+			     !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
+				to_del |= 2; /* remove "keep-alive" */
+			if (!(msg->flags & HTTP_MSGF_VER_11))
+				to_del |= 1; /* remove "close" */
+			http_parse_connection_header(txn, msg, to_del);
+		}
+
+		/* check if client or config asks for explicit close in KAL/SCL */
+		if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
+		     (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
+		    ((txn->flags & TX_HDR_CONN_CLO) ||                         /* "connection: close" */
+		     (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
+		     !(msg->flags & HTTP_MSGF_XFER_LEN) ||                     /* no length known => close */
+		     s->fe->state == PR_STSTOPPED))                            /* frontend is stopping */
+		    txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
+	}
+
 	/* end of job, return OK */
 	req->analysers &= ~an_bit;
 	req->analyse_exp = TICK_ETERNITY;
@@ -3829,70 +3893,6 @@
 			goto tarpit;
 	}
 
-	/* Until set to anything else, the connection mode is set as Keep-Alive. It will
-	 * only change if both the request and the config reference something else.
-	 * Option httpclose by itself sets tunnel mode where headers are mangled.
-	 * However, if another mode is set, it will affect it (eg: server-close/
-	 * keep-alive + httpclose = close). Note that we avoid to redo the same work
-	 * if FE and BE have the same settings (common). The method consists in
-	 * checking if options changed between the two calls (implying that either
-	 * one is non-null, or one of them is non-null and we are there for the first
-	 * time.
-	 */
-	if (!(txn->flags & TX_HDR_CONN_PRS) ||
-	    ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) {
-		int tmp = TX_CON_WANT_KAL;
-
-		if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
-				tmp = TX_CON_WANT_TUN;
-
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
-				tmp = TX_CON_WANT_TUN;
-		}
-
-		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
-		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
-			/* option httpclose + server_close => forceclose */
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
-				tmp = TX_CON_WANT_CLO;
-			else
-				tmp = TX_CON_WANT_SCL;
-		}
-
-		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
-		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
-			tmp = TX_CON_WANT_CLO;
-
-		if ((txn->flags & TX_CON_WANT_MSK) < tmp)
-			txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
-
-		if (!(txn->flags & TX_HDR_CONN_PRS) &&
-		    (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
-			/* parse the Connection header and possibly clean it */
-			int to_del = 0;
-			if ((msg->flags & HTTP_MSGF_VER_11) ||
-			    ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
-			     !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
-				to_del |= 2; /* remove "keep-alive" */
-			if (!(msg->flags & HTTP_MSGF_VER_11))
-				to_del |= 1; /* remove "close" */
-			http_parse_connection_header(txn, msg, to_del);
-		}
-
-		/* check if client or config asks for explicit close in KAL/SCL */
-		if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
-		     (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
-		    ((txn->flags & TX_HDR_CONN_CLO) ||                         /* "connection: close" */
-		     (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
-		     !(msg->flags & HTTP_MSGF_XFER_LEN) ||                     /* no length known => close */
-		     s->fe->state == PR_STSTOPPED))                            /* frontend is stopping */
-		    txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
-	}
-
 	/* we can be blocked here because the request needs to be authenticated,
 	 * either to pass or to access stats.
 	 */