]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: emulate "block" rules using "http-request" rules
authorWilly Tarreau <w@1wt.eu>
Mon, 28 Apr 2014 20:06:57 +0000 (22:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 28 Apr 2014 20:06:57 +0000 (22:06 +0200)
The "block" rules are redundant with http-request rules because they
are performed immediately before and do exactly the same thing as
"http-request deny". Moreover, this duplication has led to a few
minor stats accounting issues fixed lately.

Instead of keeping the two rule sets, we now build a list of "block"
rules that we compile as "http-request block" and that we later insert
at the beginning of the "http-request" rules.

The only user-visible change is that in case of a parsing error, the
config parser will now report "http-request block rule" instead of
"blocking condition".

src/cfgparse.c

index 923f2e477a2cacaef9c080f2f20014d69e51f84b..f2afcd0af830539d3d7407c95c2cc00815e9ee17 100644 (file)
@@ -2874,28 +2874,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                curproxy->server_id_hdr_len  = strlen(curproxy->server_id_hdr_name);
        }
        else if (!strcmp(args[0], "block")) {  /* early blocking based on ACLs */
+               struct http_req_rule *rule;
+
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
 
-               if (strcmp(args[1], "if") != 0 && strcmp(args[1], "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 ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
-                       Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
-                             file, linenum, errmsg);
-                       err_code |= ERR_ALERT | ERR_FATAL;
+               /* emulate "block" using "http-request block". Since these rules are supposed to
+                * be processed before all http-request rules, we put them into their own list
+                * and will insert them at the end.
+                */
+               rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
+               if (!rule) {
+                       err_code |= ERR_ALERT | ERR_ABORT;
                        goto out;
                }
-
-               LIST_ADDQ(&curproxy->block_rules, &cond->list);
-               warnif_misplaced_block(curproxy, file, linenum, args[0]);
+               err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
+               err_code |= warnif_cond_conflicts(rule->cond,
+                                                 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
+                                                 file, linenum);
+               LIST_ADDQ(&curproxy->block_rules, &rule->list);
        }
        else if (!strcmp(args[0], "redirect")) {
                struct redirect_rule *rule;
@@ -6189,6 +6189,16 @@ int check_config_validity()
                        }
                }
 
+               /* move any "block" rules at the beginning of the http-request rules */
+               if (!LIST_ISEMPTY(&curproxy->block_rules)) {
+                       /* insert block_rules into http_req_rules at the beginning */
+                       curproxy->block_rules.p->n    = curproxy->http_req_rules.n;
+                       curproxy->http_req_rules.n->p = curproxy->block_rules.p;
+                       curproxy->block_rules.n->p    = &curproxy->http_req_rules;
+                       curproxy->http_req_rules.n    = curproxy->block_rules.n;
+                       LIST_INIT(&curproxy->block_rules);
+               }
+
                if (curproxy->table.peers.name) {
                        struct peers *curpeers = peers;