From 7c95f5f22bcc378a2dc4629ee5dcb1ecb308ed28 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Wed, 6 May 2020 15:06:34 +0200 Subject: [PATCH] MINOR: checks: Support log-format string to set the URI for HTTP send rules For http-check send rules, it is now possible to use a log-format string to set the request URI. the keyword "uri-lf" should be used instead of "uri". If the string eval fails, we fall back on the default uri "/". --- doc/configuration.txt | 17 ++++++++++------ reg-tests/checks/http-check.vtc | 23 +++++++++++++++++++--- src/checks.c | 35 ++++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 80aa83fc7e..da5d05e781 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4681,8 +4681,8 @@ http-check expect [min-recv ] [comment ] and "http-check send". -http-check send [meth ] [uri ] [ver ] [comment ] - [hdr ]* [body ] +http-check send [meth ] [{ uri | uri-lf }>] [ver ] + [hdr ]* [body ] [comment ] Add a possible list of headers and/or a body to the request sent during HTTP health checks. May be used in sections : defaults | frontend | listen | backend @@ -4696,10 +4696,15 @@ http-check send [meth ] [uri ] [ver ] [comment ] logs. Any method may be used, though it is not recommended to invent non-standard ones. - uri is optional and set the URI referenced in the HTTP requests. - it defaults to " / " which is accessible by default on almost - any server, but may be changed to any other URI. Query - strings are permitted. + uri is optional and set the URI referenced in the HTTP requests + to the string . It defaults to "/" which is accessible + by default on almost any server, but may be changed to any + other URI. Query strings are permitted. + + uri-lf is optional and set the URI referenced in the HTTP requests + using the log-format string . It defaults to "/" which + is accessible by default on almost any server, but may be + changed to any other URI. Query strings are permitted. ver is the optional HTTP version string. It defaults to "HTTP/1.0" but some servers might behave incorrectly in HTTP diff --git a/reg-tests/checks/http-check.vtc b/reg-tests/checks/http-check.vtc index 057484f24c..3de3e3f8fe 100644 --- a/reg-tests/checks/http-check.vtc +++ b/reg-tests/checks/http-check.vtc @@ -60,6 +60,16 @@ server s4 { expect req.bodylen == 0 txresp + accept + rxreq + expect req.method == GET + expect req.url == / + expect req.proto == HTTP/1.0 + expect req.http.x-test == + expect req.http.x-haproxy-server-state ~ "UP.+name=be4/srv" + expect req.bodylen == 0 + txresp + } -start syslog S1 -level notice { @@ -113,14 +123,21 @@ haproxy h1 -conf { http-check send-state http-check connect addr ${s4_addr}:${s4_port} http-check set-var(check.server) "str(srv)" - http-check send meth GET uri /req1 ver HTTP/1.1 hdr x-test "server=%[var(check.server)]" + http-check set-var(check.path) "str(/req1)" + http-check send meth GET uri-lf "%[var(check.path)]" ver HTTP/1.1 hdr x-test "server=%[var(check.server)]" http-check expect status 200 http-check connect addr ${s4_addr} port ${s4_port} http-check unset-var(check.server) - http-check send meth GET uri /req2 ver HTTP/1.1 hdr x-test "server=%[var(check.server)]" body "health-check body" + http-check set-var(check.path) "str(/req2)" + http-check send meth GET uri-lf "%[var(check.path)]" ver HTTP/1.1 hdr x-test "server=%[var(check.server)]" body "health-check body" http-check expect rstatus "^2[0-9]{2}" http-check connect addr ${s4_addr} port ${s4_port} - http-check send meth GET uri /req3 + http-check set-var(check.path) "str(/req3)" + http-check send meth GET uri-lf "%[var(check.path)]" + http-check expect rstatus "^2[0-9]{2}" + http-check connect addr ${s4_addr} port ${s4_port} + http-check unset-var(check.path) + http-check send meth GET uri-lf "%[var(check.path)]" # default to "/" ## implicit expect rule server srv ${s1_addr}:${s1_port} check inter 100ms rise 1 fall 1 diff --git a/src/checks.c b/src/checks.c index d5306defe0..0723488a6a 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1964,7 +1964,12 @@ static enum tcpcheck_eval_ret tcpcheck_eval_send(struct check *check, struct tcp meth = ((send->http.meth.meth == HTTP_METH_OTHER) ? ist2(send->http.meth.str.area, send->http.meth.str.data) : http_known_methods[send->http.meth.meth]); - uri = (isttest(send->http.uri) ? send->http.uri : ist("/")); // TODO: handle uri_fmt + if (send->http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) { + tmp->data = sess_build_logline(check->sess, NULL, b_orig(tmp), b_size(tmp), &send->http.uri_fmt); + uri = (b_data(tmp) ? ist2(b_orig(tmp), b_data(tmp)) : ist("/")); + } + else + uri = (isttest(send->http.uri) ? send->http.uri : ist("/")); vsn = (isttest(send->http.vsn) ? send->http.vsn : ist("HTTP/1.0")); if ((istlen(vsn) == 6 && *(vsn.ptr+5) == '2') || @@ -4005,14 +4010,16 @@ static struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, cur_arg++; meth = args[cur_arg]; } - else if (strcmp(args[cur_arg], "uri") == 0) { + else if (strcmp(args[cur_arg], "uri") == 0 || strcmp(args[cur_arg], "uri-lf") == 0) { if (!*(args[cur_arg+1])) { memprintf(errmsg, "'%s' expects a string as argument.", args[cur_arg]); goto error; } + flags &= ~TCPCHK_SND_HTTP_FL_URI_FMT; + if (strcmp(args[cur_arg], "uri-lf") == 0) + flags |= TCPCHK_SND_HTTP_FL_URI_FMT; cur_arg++; uri = args[cur_arg]; - // TODO: log-format uri } else if (strcmp(args[cur_arg], "ver") == 0) { if (!*(args[cur_arg+1])) { @@ -4070,8 +4077,8 @@ static struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, } } else { - memprintf(errmsg, "expects 'comment', 'meth', 'uri', 'ver', 'hdr' and 'body' but got '%s' as argument.", - args[cur_arg]); + memprintf(errmsg, "expects 'comment', 'meth', 'uri', 'uri-lf', 'ver', 'hdr' and 'body'" + " but got '%s' as argument.", args[cur_arg]); goto error; } cur_arg++; @@ -4100,10 +4107,20 @@ static struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, } } if (uri) { - chk->send.http.uri = ist2(strdup(uri), strlen(uri)); - if (!isttest(chk->send.http.uri)) { - memprintf(errmsg, "out of memory"); - goto error; + if (chk->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) { + LIST_INIT(&chk->send.http.uri_fmt); + px->conf.args.ctx = ARGC_SRV; + if (!parse_logformat_string(uri, px, &chk->send.http.uri_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) { + memprintf(errmsg, "'%s' invalid log-format string (%s).\n", uri, *errmsg); + goto error; + } + } + else { + chk->send.http.uri = ist2(strdup(uri), strlen(uri)); + if (!isttest(chk->send.http.uri)) { + memprintf(errmsg, "out of memory"); + goto error; + } } } if (vsn) {