MEDIUM: config: relax use_backend check to make the condition optional
Since it became possible to use log-format expressions in use_backend,
having a mandatory condition becomes annoying because configurations
are full of "if TRUE". Let's relax the check to accept no condition
like many other keywords (eg: redirect).
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 113818f..37321e3 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -7705,8 +7705,7 @@
See also: "unique-id-format"
-use_backend <backend> if <condition>
-use_backend <backend> unless <condition>
+use_backend <backend> [{if | unless} <condition>]
Switch to a specific backend if/unless an ACL-based condition is matched.
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | no
@@ -7714,7 +7713,8 @@
<backend> is the name of a valid backend or "listen" section, or a
"log-format" string resolving to a backend name.
- <condition> is a condition composed of ACLs, as described in section 7.
+ <condition> is a condition composed of ACLs, as described in section 7. If
+ it is omitted, the rule is unconditionally applied.
When doing content-switching, connections arrive on a frontend and are then
dispatched to various backends depending on a number of conditions. The
diff --git a/src/cfgparse.c b/src/cfgparse.c
index d4893a1..53b136a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2866,22 +2866,17 @@
goto out;
}
- if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
- Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
+ if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
+ file, linenum, errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
- file, linenum, errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
+ err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
}
- err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
-
rule = (struct switching_rule *)calloc(1, sizeof(*rule));
rule->cond = cond;
rule->be.name = strdup(args[1]);
diff --git a/src/haproxy.c b/src/haproxy.c
index 67798b4..ed2ff21 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1085,8 +1085,10 @@
list_for_each_entry_safe(rule, ruleb, &p->switching_rules, list) {
LIST_DEL(&rule->list);
- prune_acl_cond(rule->cond);
- free(rule->cond);
+ if (rule->cond) {
+ prune_acl_cond(rule->cond);
+ free(rule->cond);
+ }
free(rule);
}
diff --git a/src/session.c b/src/session.c
index b373489..dc72ba5 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1238,12 +1238,14 @@
struct switching_rule *rule;
list_for_each_entry(rule, &s->fe->switching_rules, list) {
- int ret;
+ int ret = 1;
- ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
- ret = acl_pass(ret);
- if (rule->cond->pol == ACL_COND_UNLESS)
- ret = !ret;
+ if (rule->cond) {
+ ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+ ret = acl_pass(ret);
+ if (rule->cond->pol == ACL_COND_UNLESS)
+ ret = !ret;
+ }
if (ret) {
/* If the backend name is dynamic, try to resolve the name.