MEDIUM: streams: Add a new http action, disable-l7-retry.
Add a new action for http-request, disable-l7-retry, that can be used to
disable any attempt at retry requests (see retry-on) if it fails for any
reason other than a connection failure.
This is useful for example to make sure POST requests aren't retried.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 31aac44..f88dad8 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -4297,6 +4297,11 @@
those that can be overridden by the "errorfile" directive.
No further "http-request" rules are evaluated.
+http-request disable-l7-retry [ { if | unless } <condition> ]
+ This disables any attempt to retry the request if it fails for any other
+ reason than a connection failure. This can be useful for example to make
+ sure POST requests aren't retried on failure.
+
http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> :
This action performs a DNS resolution of the output of <expr> and stores
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 6b30de5..e11a6c9 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -84,6 +84,7 @@
SI_FL_RXBLK_ANY = 0x001F0000, /* any of the RXBLK flags above */
SI_FL_RX_WAIT_EP = 0x00200000, /* stream-int waits for more data from the end point */
SI_FL_L7_RETRY = 0x01000000, /* The stream interface may attempt L7 retries */
+ SI_FL_D_L7_RETRY = 0x02000000, /* Disable L7 retries on this stream interface, even if configured to do it */
};
/* A stream interface has 3 parts :
diff --git a/src/http_act.c b/src/http_act.c
index c8618ea..c1b94dd 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -217,6 +217,38 @@
return ACT_RET_PRS_OK;
}
+/* This function executes the "disable-l7-retry" HTTP action.
+ * It disables L7 retries (all retry except for a connection failure). This
+ * can be useful for example to avoid retrying on POST requests.
+ * It just removes the L7 retry flag on the stream_interface, and always
+ * return ACT_RET_CONT;
+ */
+static enum act_return http_req_disable_l7_retry(struct act_rule *rule, struct proxy *px,
+ struct session *sess, struct stream *s, int flags)
+{
+ struct stream_interface *si = &s->si[1];
+
+ /* In theory, the SI_FL_L7_RETRY flags isn't set at this point, but
+ * let's be future-proof and remove it anyway.
+ */
+ si->flags &= ~SI_FL_L7_RETRY;
+ si->flags |= SI_FL_D_L7_RETRY;
+ return ACT_RET_CONT;
+}
+
+/* parse the "disable-l7-retry" action:
+ * This action takes no argument and returns ACT_RET_PRS_OK on success,
+ * ACT_RET_PRS_ERR on error.
+ */
+static enum act_parse_ret parse_http_req_disable_l7_retry(const char **args,
+ int *orig_args, struct proxy *px,
+ struct act_rule *rule, char **err)
+{
+ rule->action = ACT_CUSTOM;
+ rule->action_ptr = http_req_disable_l7_retry;
+ return ACT_RET_PRS_OK;
+}
+
/* This function executes the "capture" action. It executes a fetch expression,
* turns the result into a string and puts it in a capture slot. It always
* returns 1. If an error occurs the action is cancelled, but the rule
@@ -575,6 +607,7 @@
.kw = {
{ "capture", parse_http_req_capture },
{ "reject", parse_http_action_reject },
+ { "disable-l7-retry", parse_http_req_disable_l7_retry },
{ "set-method", parse_set_req_line },
{ "set-path", parse_set_req_line },
{ "set-query", parse_set_req_line },
diff --git a/src/stream.c b/src/stream.c
index 58e1cc1..62c5598 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -2341,7 +2341,8 @@
*/
si_b->state = SI_ST_REQ; /* new connection requested */
si_b->conn_retries = s->be->conn_retries;
- if (s->be->retry_type &~ PR_RE_CONN_FAILED)
+ if ((s->be->retry_type &~ PR_RE_CONN_FAILED) &&
+ !(si_b->flags & SI_FL_D_L7_RETRY))
si_b->flags |= SI_FL_L7_RETRY;
}
}