[MINOR] redirect: add support for unconditional rules

Sometimes it's useful to be able to specify an unconditional redirect
rule without adding "if TRUE".
This commit is contained in:
Willy Tarreau 2010-01-03 20:03:03 +01:00
parent 963abc33a2
commit f285f54311
4 changed files with 22 additions and 21 deletions

View File

@ -3296,14 +3296,14 @@ rate-limit sessions <rate>
See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion. See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion.
redirect location <to> [code <code>] <option> {if | unless} <condition> redirect location <to> [code <code>] <option> [{if | unless} <condition>]
redirect prefix <to> [code <code>] <option> {if | unless} <condition> redirect prefix <to> [code <code>] <option> [{if | unless} <condition>]
Return an HTTP redirection if/unless a condition is matched Return an HTTP redirection if/unless a condition is matched
May be used in sections : defaults | frontend | listen | backend May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes no | yes | yes | yes
If/unless the condition is matched, the HTTP request will lead to a redirect If/unless the condition is matched, the HTTP request will lead to a redirect
response. response. If no condition is specified, the redirect applies unconditionally.
Arguments : Arguments :
<to> With "redirect location", the exact value in <to> is placed into <to> With "redirect location", the exact value in <to> is placed into

View File

@ -1754,7 +1754,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
} }
else if (!strcmp(args[0], "redirect")) { else if (!strcmp(args[0], "redirect")) {
int pol = ACL_COND_NONE; int pol = ACL_COND_NONE;
struct acl_cond *cond; struct acl_cond *cond = NULL;
struct redirect_rule *rule; struct redirect_rule *rule;
int cur_arg; int cur_arg;
int type = REDIRECT_TYPE_NONE; int type = REDIRECT_TYPE_NONE;
@ -1859,23 +1859,19 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
goto out; goto out;
} }
if (pol == ACL_COND_NONE) { if (pol != ACL_COND_NONE &&
Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n", (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n", Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
file, linenum, args[0]); file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto out; goto out;
} }
cond->file = file; if (cond) {
cond->line = linenum; cond->file = file;
curproxy->acl_requires |= cond->requires; cond->line = linenum;
curproxy->acl_requires |= cond->requires;
}
rule = (struct redirect_rule *)calloc(1, sizeof(*rule)); rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
rule->cond = cond; rule->cond = cond;
rule->rdr_str = strdup(destination); rule->rdr_str = strdup(destination);

View File

@ -797,8 +797,10 @@ void deinit(void)
list_for_each_entry_safe(rdr, rdrb, &p->redirect_rules, list) { list_for_each_entry_safe(rdr, rdrb, &p->redirect_rules, list) {
LIST_DEL(&rdr->list); LIST_DEL(&rdr->list);
prune_acl_cond(rdr->cond); if (rdr->cond) {
free(rdr->cond); prune_acl_cond(rdr->cond);
free(rdr->cond);
}
free(rdr->rdr_str); free(rdr->rdr_str);
free(rdr); free(rdr);
} }

View File

@ -2697,11 +2697,14 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
/* check whether we have some ACLs set to redirect this request */ /* check whether we have some ACLs set to redirect this request */
list_for_each_entry(rule, &px->redirect_rules, list) { list_for_each_entry(rule, &px->redirect_rules, list) {
int ret = acl_exec_cond(rule->cond, px, s, txn, ACL_DIR_REQ); int ret = ACL_PAT_PASS;
ret = acl_pass(ret); if (rule->cond) {
if (rule->cond->pol == ACL_COND_UNLESS) ret = acl_exec_cond(rule->cond, px, s, txn, ACL_DIR_REQ);
ret = !ret; ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS)
ret = !ret;
}
if (ret) { if (ret) {
struct chunk rdr = { .str = trash, .size = sizeof(trash), .len = 0 }; struct chunk rdr = { .str = trash, .size = sizeof(trash), .len = 0 };