MEDIUM: streams: Add a new keyword for retry-on, "junk-response"

Add a way to retry requests if we got a junk response from the server, ie
an incomplete response, or something that is not valid HTTP.
To do so, one can use the new "junk-response" keyword for retry-on.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 827c6b0..ee6f81c 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8027,6 +8027,14 @@
                         condition, or a server crash or restart while
                         processing the request.
 
+      junk-response     retry when the server returned something not looking
+                        like a complete HTTP response. This includes partial
+                        responses headers as well as non-HTTP contents. It
+                        usually is a bad idea to retry on such events, which
+                        may be caused a configuration issue (wrong server port)
+                        or by the request being harmful to the server (buffer
+                        overflow attack for example).
+
       response-timeout  the server timeout stroke while waiting for the server
                         to respond to the request. This may be caused by poor
                         network condition, the reuse of an idle connection
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 86fd5e7..dababea 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -222,6 +222,7 @@
  * reserved for eventual future status codes
  */
 #define PR_RE_EARLY_ERROR         0x00010000 /* Retry if we failed at sending early data */
+#define PR_RE_JUNK_REQUEST        0x00020000 /* We received an incomplete or garbage response */
 struct stream;
 
 struct http_snapshot {
diff --git a/src/proto_htx.c b/src/proto_htx.c
index 41012b4..95b81c9 100644
--- a/src/proto_htx.c
+++ b/src/proto_htx.c
@@ -1812,6 +1812,9 @@
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_resp, 1);
 		health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
 	}
+	if ((s->be->retry_type & PR_RE_JUNK_REQUEST) &&
+	    do_l7_retry(s, si_b) == 0)
+		return 0;
 	txn->status = 502;
 	s->si[1].flags |= SI_FL_NOLINGER;
 	htx_reply_and_close(s, txn->status, htx_error_message(s));
diff --git a/src/proxy.c b/src/proxy.c
index e3d59dc..18f016c 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -543,6 +543,8 @@
 			curpx->retry_type |= PR_RE_504;
 		else if (!strcmp(args[i], "0rtt-rejected"))
 			curpx->retry_type |= PR_RE_EARLY_ERROR;
+		else if (!strcmp(args[i], "junk-response"))
+			curpx->retry_type |= PR_RE_JUNK_REQUEST;
 		else if (!strcmp(args[i], "none")) {
 			if (i != 1 || *args[i + 1]) {
 				memprintf(err, "'%s' 'none' keyworld only usable alone", args[0]);