From 51b129fd0fcd60178a91297f0cce197d48b9e185 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 9 Apr 2020 15:54:18 +0200 Subject: [PATCH] MINOR: proxy/checks: Register a keyword to parse http-check rules The keyword 'http-check' is now parsed in a dedicated callback function. Thus the code to parse these rules is now located in checks.c. --- src/cfgparse-listen.c | 172 ------------------------------------------ src/checks.c | 172 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 173 deletions(-) diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index eb175a1c5..7b33eb06f 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -2547,178 +2547,6 @@ stats_error_parsing: goto out; } } - else if (!strcmp(args[0], "http-check")) { - if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) - err_code |= ERR_WARN; - - if (strcmp(args[1], "disable-on-404") == 0) { - /* enable a graceful server shutdown on an HTTP 404 response */ - curproxy->options |= PR_O_DISABLE404; - if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code)) - goto out; - } - else if (strcmp(args[1], "send-state") == 0) { - /* enable emission of the apparent state of a server in HTTP checks */ - curproxy->options2 |= PR_O2_CHK_SNDST; - if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code)) - goto out; - } - else if (strcmp(args[1], "send") == 0) { - int cur_arg = 2; - - free(curproxy->check_hdrs); - free(curproxy->check_body); - curproxy->check_hdrs = curproxy->check_body = NULL; - curproxy->check_hdrs_len = curproxy->check_body_len = 0; - while (*(args[cur_arg])) { - if (strcmp(args[cur_arg], "hdr") == 0) { - int hdr_len; - if (!*(args[cur_arg+1]) || !*(args[cur_arg+2])) { - ha_alert("parsing [%s:%d] : '%s %s' : %s expects a name and a value as parameter.\n", - file, linenum, args[0], args[1], args[cur_arg]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - cur_arg++; - hdr_len = strlen(args[cur_arg]) + strlen(args[cur_arg+1]) + 4; - curproxy->check_hdrs = my_realloc2(curproxy->check_hdrs, curproxy->check_hdrs_len+hdr_len+1); - if (curproxy->check_hdrs == NULL) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - snprintf(curproxy->check_hdrs + curproxy->check_hdrs_len, hdr_len+1, "%s: %s\r\n", args[cur_arg], args[cur_arg+1]); - curproxy->check_hdrs_len += hdr_len; - - cur_arg++; - } - else if (strcmp(args[cur_arg], "body") == 0) { - if (!*(args[cur_arg+1])) { - ha_alert("parsing [%s:%d] : '%s %s' : %s expects a string as parameter.\n", - file, linenum, args[0], args[1], args[cur_arg]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - cur_arg++; - free(curproxy->check_body); - curproxy->check_body = strdup(args[cur_arg]); - curproxy->check_body_len = strlen(args[cur_arg]); - if (curproxy->check_body == NULL) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' only supports 'hdr' and 'body', found '%s'.\n", - file, linenum, args[0], args[1], args[cur_arg]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - cur_arg++; - } - - } - else if (strcmp(args[1], "expect") == 0) { - const char *ptr_arg; - int cur_arg; - - if (curproxy->options2 & PR_O2_EXP_TYPE) { - ha_alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - cur_arg = 2; - /* consider exclamation marks, sole or at the beginning of a word */ - while (*(ptr_arg = args[cur_arg])) { - while (*ptr_arg == '!') { - curproxy->options2 ^= PR_O2_EXP_INV; - ptr_arg++; - } - if (*ptr_arg) - break; - cur_arg++; - } - /* now ptr_arg points to the beginning of a word past any possible - * exclamation mark, and cur_arg is the argument which holds this word. - */ - if (strcmp(ptr_arg, "status") == 0) { - if (!*(args[cur_arg + 1])) { - ha_alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", - file, linenum, args[0], args[1], ptr_arg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->options2 |= PR_O2_EXP_STS; - free(curproxy->expect_str); - curproxy->expect_str = strdup(args[cur_arg + 1]); - } - else if (strcmp(ptr_arg, "string") == 0) { - if (!*(args[cur_arg + 1])) { - ha_alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", - file, linenum, args[0], args[1], ptr_arg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->options2 |= PR_O2_EXP_STR; - free(curproxy->expect_str); - curproxy->expect_str = strdup(args[cur_arg + 1]); - } - else if (strcmp(ptr_arg, "rstatus") == 0) { - if (!*(args[cur_arg + 1])) { - ha_alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", - file, linenum, args[0], args[1], ptr_arg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->options2 |= PR_O2_EXP_RSTS; - free(curproxy->expect_str); - regex_free(curproxy->expect_regex); - curproxy->expect_str = strdup(args[cur_arg + 1]); - error = NULL; - if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) { - ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n", - file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error); - free(error); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - } - else if (strcmp(ptr_arg, "rstring") == 0) { - if (!*(args[cur_arg + 1])) { - ha_alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", - file, linenum, args[0], args[1], ptr_arg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->options2 |= PR_O2_EXP_RSTR; - free(curproxy->expect_str); - regex_free(curproxy->expect_regex); - curproxy->expect_str = strdup(args[cur_arg + 1]); - error = NULL; - if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) { - ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n", - file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error); - free(error); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n", - file, linenum, args[0], args[1], ptr_arg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - } - else { - ha_alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - } else if (!strcmp(args[0], "monitor")) { if (curproxy == &defproxy) { ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); diff --git a/src/checks.c b/src/checks.c index 240201b10..ad72e08af 100644 --- a/src/checks.c +++ b/src/checks.c @@ -5096,6 +5096,175 @@ static int proxy_parse_tcpcheck(char **args, int section, struct proxy *curpx, return -1; } +/* Parses the "http-check" proxy keyword */ +static int proxy_parse_httpcheck(char **args, int section, struct proxy *curpx, + struct proxy *defpx, const char *file, int line, + char **errmsg) +{ + int cur_arg, ret = 0; + + if (warnifnotcap(curpx, PR_CAP_BE, file, line, args[0], NULL)) + ret = 1; + + cur_arg = 1; + if (strcmp(args[cur_arg], "disable-on-404") == 0) { + /* enable a graceful server shutdown on an HTTP 404 response */ + curpx->options |= PR_O_DISABLE404; + if (too_many_args(1, args, errmsg, NULL)) + goto error; + } + else if (strcmp(args[cur_arg], "send-state") == 0) { + /* enable emission of the apparent state of a server in HTTP checks */ + curpx->options2 |= PR_O2_CHK_SNDST; + if (too_many_args(1, args, errmsg, NULL)) + goto error; + } + else if (strcmp(args[cur_arg], "send") == 0) { + free(curpx->check_hdrs); + free(curpx->check_body); + curpx->check_hdrs = curpx->check_body = NULL; + curpx->check_hdrs_len = curpx->check_body_len = 0; + + cur_arg++; + while (*(args[cur_arg])) { + if (strcmp(args[cur_arg], "hdr") == 0) { + int hdr_len; + if (!*(args[cur_arg+1]) || !*(args[cur_arg+2])) { + memprintf(errmsg, "'%s %s' : %s expects a name and a value as parameter.", + args[0], args[1], args[cur_arg]); + goto error; + } + + cur_arg++; + hdr_len = strlen(args[cur_arg]) + strlen(args[cur_arg+1]) + 4; + curpx->check_hdrs = my_realloc2(curpx->check_hdrs, curpx->check_hdrs_len+hdr_len+1); + if (curpx->check_hdrs == NULL) { + memprintf(errmsg, "out of memory."); + goto error; + } + snprintf(curpx->check_hdrs + curpx->check_hdrs_len, hdr_len+1, "%s: %s\r\n", args[cur_arg], args[cur_arg+1]); + curpx->check_hdrs_len += hdr_len; + + cur_arg++; + } + else if (strcmp(args[cur_arg], "body") == 0) { + if (!*(args[cur_arg+1])) { + memprintf(errmsg, "'%s %s' : %s expects a string as parameter.", + args[0], args[1], args[cur_arg]); + goto error; + } + cur_arg++; + free(curpx->check_body); + curpx->check_body = strdup(args[cur_arg]); + curpx->check_body_len = strlen(args[cur_arg]); + if (curpx->check_body == NULL) { + memprintf(errmsg, "out of memory."); + goto error; + } + } + else { + memprintf(errmsg, "'%s %s' only supports 'hdr' and 'body', found '%s'.", + args[0], args[1], args[cur_arg]); + goto error; + } + cur_arg++; + } + } + else if (strcmp(args[cur_arg], "expect") == 0) { + const char *ptr_arg; + + if (curpx->options2 & PR_O2_EXP_TYPE) { + memprintf(errmsg, "'%s %s' already specified.", args[0], args[1]); + goto error; + } + + cur_arg++; + + /* consider exclamation marks, sole or at the beginning of a word */ + while (*(ptr_arg = args[cur_arg])) { + while (*ptr_arg == '!') { + curpx->options2 ^= PR_O2_EXP_INV; + ptr_arg++; + } + if (*ptr_arg) + break; + cur_arg++; + } + + /* now ptr_arg points to the beginning of a word past any possible + * exclamation mark, and cur_arg is the argument which holds this word. + */ + if (strcmp(ptr_arg, "status") == 0) { + if (!*(args[cur_arg+1])) { + memprintf(errmsg, "'%s %s %s' expects as an argument.", + args[0], args[1], ptr_arg); + goto error; + } + curpx->options2 |= PR_O2_EXP_STS; + free(curpx->expect_str); + curpx->expect_str = strdup(args[cur_arg+1]); + } + else if (strcmp(ptr_arg, "string") == 0) { + if (!*(args[cur_arg+1])) { + memprintf(errmsg, "'%s %s %s' expects as an argument.", + args[0], args[1], ptr_arg); + goto error; + } + curpx->options2 |= PR_O2_EXP_STR; + free(curpx->expect_str); + curpx->expect_str = strdup(args[cur_arg+1]); + } + else if (strcmp(ptr_arg, "rstatus") == 0) { + if (!*(args[cur_arg+1])) { + memprintf(errmsg, "'%s %s %s' expects as an argument.", + args[0], args[1], ptr_arg); + goto error; + } + curpx->options2 |= PR_O2_EXP_RSTS; + free(curpx->expect_str); + regex_free(curpx->expect_regex); + curpx->expect_str = strdup(args[cur_arg+1]); + if (!(curpx->expect_regex = regex_comp(args[cur_arg+1], 1, 1, errmsg))) { + memprintf(errmsg, "'%s %s %s' : regular expression '%s': %s.", + args[0], args[1], ptr_arg, args[cur_arg+1], *errmsg); + goto error; + } + } + else if (strcmp(ptr_arg, "rstring") == 0) { + if (!*(args[cur_arg+1])) { + memprintf(errmsg, "'%s %s %s' expects as an argument.", + args[0], args[1], ptr_arg); + goto error; + } + curpx->options2 |= PR_O2_EXP_RSTR; + free(curpx->expect_str); + regex_free(curpx->expect_regex); + curpx->expect_str = strdup(args[cur_arg+1]); + if (!(curpx->expect_regex = regex_comp(args[cur_arg+1], 1, 1, errmsg))) { + memprintf(errmsg, "'%s %s %s' : regular expression '%s': %s.", + args[0], args[1], ptr_arg, args[cur_arg + 1], *errmsg); + goto error; + } + } + else { + memprintf(errmsg, "'%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.", + args[0], args[1], ptr_arg); + goto error; + } + } + else { + memprintf(errmsg, "'%s' only supports 'disable-on-404', 'send', 'send-state' and 'expect'. but got '%s'.", + args[0], args[1]); + goto error; + } + + ret = (*errmsg != NULL); /* Handle warning */ + return ret; + + error: + return -1; +} + static struct tcpcheck_ruleset *tcpcheck_ruleset_lookup(const char *name) { @@ -6701,7 +6870,8 @@ static int srv_parse_check_port(char **args, int *cur_arg, struct proxy *curpx, } static struct cfg_kw_list cfg_kws = {ILH, { - { CFG_LISTEN, "tcp-check", proxy_parse_tcpcheck }, + { CFG_LISTEN, "tcp-check", proxy_parse_tcpcheck }, + { CFG_LISTEN, "http-check", proxy_parse_httpcheck }, { 0, NULL, NULL }, }};