From: Willy Tarreau Date: Mon, 28 Apr 2014 20:06:57 +0000 (+0200) Subject: MEDIUM: http: emulate "block" rules using "http-request" rules X-Git-Tag: v1.5-dev25~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3dc39dfe163ea29819986caa939e4b8c78aae25;p=thirdparty%2Fhaproxy.git MEDIUM: http: emulate "block" rules using "http-request" rules 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". --- diff --git a/src/cfgparse.c b/src/cfgparse.c index 923f2e477a..f2afcd0af8 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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;