From e3249a98e2eaa5292b428cdb2b88b2bb9010ce43 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Fri, 3 May 2019 23:01:47 +0200 Subject: [PATCH] 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. --- doc/configuration.txt | 8 ++++++++ include/types/proxy.h | 1 + src/proto_htx.c | 3 +++ src/proxy.c | 2 ++ 4 files changed, 14 insertions(+) diff --git a/doc/configuration.txt b/doc/configuration.txt index 827c6b0b2..ee6f81c1d 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -8027,6 +8027,14 @@ retry-on [list of keywords] 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 86fd5e7fb..dababea34 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -222,6 +222,7 @@ enum PR_SRV_STATE_FILE { * 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 41012b472..95b81c9e5 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -1812,6 +1812,9 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit) _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 e3d59dc2c..18f016c83 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -543,6 +543,8 @@ proxy_parse_retry_on(char **args, int section, struct proxy *curpx, 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]);