REORG: config: move the http redirect rule parser to proto_http.c
We'll have to use this elsewhere soon, let's move it to the proper place.
This commit is contained in:
parent
71241abfd3
commit
4baae248fc
|
@ -110,6 +110,8 @@ void http_reset_txn(struct session *s);
|
|||
struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
|
||||
void free_http_req_rules(struct list *r);
|
||||
struct chunk *http_error_message(struct session *s, int msgnum);
|
||||
struct redirect_rule *http_parse_redirect_rule(const char *file, int line, struct proxy *curproxy,
|
||||
const char **args, char **errmsg);
|
||||
|
||||
/* to be used when contents change in an HTTP message */
|
||||
#define http_msg_move_end(msg, bytes) do { \
|
||||
|
|
142
src/cfgparse.c
142
src/cfgparse.c
|
@ -2648,13 +2648,6 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
}
|
||||
else if (!strcmp(args[0], "redirect")) {
|
||||
struct redirect_rule *rule;
|
||||
int cur_arg;
|
||||
int type = REDIRECT_TYPE_NONE;
|
||||
int code = 302;
|
||||
char *destination = NULL;
|
||||
char *cookie = NULL;
|
||||
int cookie_set = 0;
|
||||
unsigned int flags = REDIRECT_FLAG_NONE;
|
||||
|
||||
if (curproxy == &defproxy) {
|
||||
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||
|
@ -2662,142 +2655,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
goto out;
|
||||
}
|
||||
|
||||
cur_arg = 1;
|
||||
while (*(args[cur_arg])) {
|
||||
if (!strcmp(args[cur_arg], "location")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = REDIRECT_TYPE_LOCATION;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "prefix")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = REDIRECT_TYPE_PREFIX;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "scheme")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = REDIRECT_TYPE_SCHEME;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "set-cookie")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 1;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "clear-cookie")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 0;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"code")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
|
||||
file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
cur_arg++;
|
||||
code = atol(args[cur_arg]);
|
||||
if (code < 301 || code > 303) {
|
||||
Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
|
||||
file, linenum, args[0], code);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"drop-query")) {
|
||||
flags |= REDIRECT_FLAG_DROP_QS;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"append-slash")) {
|
||||
flags |= REDIRECT_FLAG_APPEND_SLASH;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "if") == 0 ||
|
||||
strcmp(args[cur_arg], "unless") == 0) {
|
||||
cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
|
||||
if (!cond) {
|
||||
Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
|
||||
file, linenum, args[0], errmsg);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
cur_arg++;
|
||||
}
|
||||
|
||||
if (type == REDIRECT_TYPE_NONE) {
|
||||
Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
|
||||
file, linenum, args[0]);
|
||||
if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
|
||||
Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
|
||||
file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
|
||||
rule->cond = cond;
|
||||
rule->rdr_str = strdup(destination);
|
||||
rule->rdr_len = strlen(destination);
|
||||
if (cookie) {
|
||||
/* depending on cookie_set, either we want to set the cookie, or to clear it.
|
||||
* a clear consists in appending "; path=/; Max-Age=0;" at the end.
|
||||
*/
|
||||
rule->cookie_len = strlen(cookie);
|
||||
if (cookie_set) {
|
||||
rule->cookie_str = malloc(rule->cookie_len + 10);
|
||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
|
||||
rule->cookie_len += 9;
|
||||
} else {
|
||||
rule->cookie_str = malloc(rule->cookie_len + 21);
|
||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
|
||||
rule->cookie_len += 20;
|
||||
}
|
||||
}
|
||||
rule->type = type;
|
||||
rule->code = code;
|
||||
rule->flags = flags;
|
||||
LIST_INIT(&rule->list);
|
||||
LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
|
||||
err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
|
||||
err_code |= warnif_cond_requires_resp(cond, file, linenum);
|
||||
|
|
132
src/proto_http.c
132
src/proto_http.c
|
@ -8104,6 +8104,138 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
|||
return rule;
|
||||
}
|
||||
|
||||
/* Parses a redirect rule. Returns the redirect rule on success or NULL on error,
|
||||
* with <err> filled with the error message.
|
||||
*/
|
||||
struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, struct proxy *curproxy,
|
||||
const char **args, char **errmsg)
|
||||
{
|
||||
struct redirect_rule *rule;
|
||||
int cur_arg;
|
||||
int type = REDIRECT_TYPE_NONE;
|
||||
int code = 302;
|
||||
const char *destination = NULL;
|
||||
const char *cookie = NULL;
|
||||
int cookie_set = 0;
|
||||
unsigned int flags = REDIRECT_FLAG_NONE;
|
||||
struct acl_cond *cond = NULL;
|
||||
|
||||
cur_arg = 0;
|
||||
while (*(args[cur_arg])) {
|
||||
if (strcmp(args[cur_arg], "location") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
type = REDIRECT_TYPE_LOCATION;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "prefix") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
type = REDIRECT_TYPE_PREFIX;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "scheme") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
type = REDIRECT_TYPE_SCHEME;
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "set-cookie") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 1;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "clear-cookie") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 0;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "code") == 0) {
|
||||
if (!*args[cur_arg + 1])
|
||||
goto missing_arg;
|
||||
|
||||
cur_arg++;
|
||||
code = atol(args[cur_arg]);
|
||||
if (code < 301 || code > 303) {
|
||||
memprintf(errmsg,
|
||||
"'%s': unsupported HTTP code '%s' (must be a number between 301 and 303)",
|
||||
args[cur_arg - 1], args[cur_arg]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"drop-query")) {
|
||||
flags |= REDIRECT_FLAG_DROP_QS;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"append-slash")) {
|
||||
flags |= REDIRECT_FLAG_APPEND_SLASH;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "if") == 0 ||
|
||||
strcmp(args[cur_arg], "unless") == 0) {
|
||||
cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, errmsg);
|
||||
if (!cond) {
|
||||
memprintf(errmsg, "error in condition: %s", *errmsg);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
memprintf(errmsg,
|
||||
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s')",
|
||||
args[cur_arg]);
|
||||
return NULL;
|
||||
}
|
||||
cur_arg++;
|
||||
}
|
||||
|
||||
if (type == REDIRECT_TYPE_NONE) {
|
||||
memprintf(errmsg, "redirection type expected ('prefix', 'location', or 'scheme')");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
|
||||
rule->cond = cond;
|
||||
rule->rdr_str = strdup(destination);
|
||||
rule->rdr_len = strlen(destination);
|
||||
if (cookie) {
|
||||
/* depending on cookie_set, either we want to set the cookie, or to clear it.
|
||||
* a clear consists in appending "; path=/; Max-Age=0;" at the end.
|
||||
*/
|
||||
rule->cookie_len = strlen(cookie);
|
||||
if (cookie_set) {
|
||||
rule->cookie_str = malloc(rule->cookie_len + 10);
|
||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
|
||||
rule->cookie_len += 9;
|
||||
} else {
|
||||
rule->cookie_str = malloc(rule->cookie_len + 21);
|
||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
|
||||
rule->cookie_len += 20;
|
||||
}
|
||||
}
|
||||
rule->type = type;
|
||||
rule->code = code;
|
||||
rule->flags = flags;
|
||||
LIST_INIT(&rule->list);
|
||||
return rule;
|
||||
|
||||
missing_arg:
|
||||
memprintf(errmsg, "missing argument for '%s'", args[cur_arg]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* The code below is dedicated to ACL parsing and matching */
|
||||
/************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue