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.
This commit is contained in:
Christopher Faulet 2020-04-09 15:54:18 +02:00
parent 430e480510
commit 51b129fd0f
2 changed files with 171 additions and 173 deletions

View File

@ -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 <string> 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 <string> 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 <regex> 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 <regex> 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]);

View File

@ -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 <string> 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 <string> 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 <regex> 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 <regex> 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 },
}};