]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: streams: Add a new http action, disable-l7-retry.
authorOlivier Houchard <ohouchard@haproxy.com>
Fri, 10 May 2019 11:59:15 +0000 (13:59 +0200)
committerOlivier Houchard <cognet@ci0.org>
Fri, 10 May 2019 15:49:09 +0000 (17:49 +0200)
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.

doc/configuration.txt
include/types/stream_interface.h
src/http_act.c
src/stream.c

index 31aac447aa68b0358af668c3ea154a0e94d0f0e8..f88dad876e24a8ed879a034970b73eaf2982f70d 100644 (file)
@@ -4297,6 +4297,11 @@ http-request deny [deny_status <status>] [ { if | unless } <condition> ]
   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
index 6b30de58ad355da12bd34c17fafd6a8514e2e47d..e11a6c903772edd8b67bd2c4c039f6802fb341c0 100644 (file)
@@ -84,6 +84,7 @@ enum {
        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 :
index c8618eac589429c0e391c89ac611f576936d254d..c1b94dd0924223fa3ac0c08070e40b2b1bffb681 100644 (file)
@@ -217,6 +217,38 @@ static enum act_parse_ret parse_http_action_reject(const char **args, int *orig_
        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 @@ static struct action_kw_list http_req_actions = {
        .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 },
index 58e1cc11b8110db47f809d8c01305808ceaef094..62c559847d378ef6a5538e577deedeaa3fe9cad7 100644 (file)
@@ -2341,7 +2341,8 @@ redo:
                                 */
                                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;
                        }
                }