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 "/".
This commit is contained in:
Christopher Faulet 2020-05-06 15:06:34 +02:00
parent a655ba4a94
commit 7c95f5f22b
3 changed files with 57 additions and 18 deletions

View File

@ -4681,8 +4681,8 @@ http-check expect [min-recv <int>] [comment <msg>]
and "http-check send". and "http-check send".
http-check send [meth <method>] [uri <uri>] [ver <version>] [comment <msg>] http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
[hdr <name> <fmt>]* [body <string>] [hdr <name> <fmt>]* [body <string>] [comment <msg>]
Add a possible list of headers and/or a body to the request sent during HTTP Add a possible list of headers and/or a body to the request sent during HTTP
health checks. health checks.
May be used in sections : defaults | frontend | listen | backend May be used in sections : defaults | frontend | listen | backend
@ -4696,10 +4696,15 @@ http-check send [meth <method>] [uri <uri>] [ver <version>] [comment <msg>]
logs. Any method may be used, though it is not recommended logs. Any method may be used, though it is not recommended
to invent non-standard ones. to invent non-standard ones.
uri <uri> is optional and set the URI referenced in the HTTP requests. uri <uri> is optional and set the URI referenced in the HTTP requests
it defaults to " / " which is accessible by default on almost to the string <uri>. It defaults to "/" which is accessible
any server, but may be changed to any other URI. Query by default on almost any server, but may be changed to any
strings are permitted. other URI. Query strings are permitted.
uri-lf <fmt> is optional and set the URI referenced in the HTTP requests
using the log-format string <fmt>. 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 <version> is the optional HTTP version string. It defaults to ver <version> is the optional HTTP version string. It defaults to
"HTTP/1.0" but some servers might behave incorrectly in HTTP "HTTP/1.0" but some servers might behave incorrectly in HTTP

View File

@ -60,6 +60,16 @@ server s4 {
expect req.bodylen == 0 expect req.bodylen == 0
txresp txresp
accept
rxreq
expect req.method == GET
expect req.url == /
expect req.proto == HTTP/1.0
expect req.http.x-test == <undef>
expect req.http.x-haproxy-server-state ~ "UP.+name=be4/srv"
expect req.bodylen == 0
txresp
} -start } -start
syslog S1 -level notice { syslog S1 -level notice {
@ -113,14 +123,21 @@ haproxy h1 -conf {
http-check send-state http-check send-state
http-check connect addr ${s4_addr}:${s4_port} http-check connect addr ${s4_addr}:${s4_port}
http-check set-var(check.server) "str(srv)" 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 expect status 200
http-check connect addr ${s4_addr} port ${s4_port} http-check connect addr ${s4_addr} port ${s4_port}
http-check unset-var(check.server) 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 expect rstatus "^2[0-9]{2}"
http-check connect addr ${s4_addr} port ${s4_port} 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 ## implicit expect rule
server srv ${s1_addr}:${s1_port} check inter 100ms rise 1 fall 1 server srv ${s1_addr}:${s1_port} check inter 100ms rise 1 fall 1

View File

@ -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) meth = ((send->http.meth.meth == HTTP_METH_OTHER)
? ist2(send->http.meth.str.area, send->http.meth.str.data) ? ist2(send->http.meth.str.area, send->http.meth.str.data)
: http_known_methods[send->http.meth.meth]); : 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")); vsn = (isttest(send->http.vsn) ? send->http.vsn : ist("HTTP/1.0"));
if ((istlen(vsn) == 6 && *(vsn.ptr+5) == '2') || 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++; cur_arg++;
meth = args[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])) { if (!*(args[cur_arg+1])) {
memprintf(errmsg, "'%s' expects a string as argument.", args[cur_arg]); memprintf(errmsg, "'%s' expects a string as argument.", args[cur_arg]);
goto error; 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++; cur_arg++;
uri = args[cur_arg]; uri = args[cur_arg];
// TODO: log-format uri
} }
else if (strcmp(args[cur_arg], "ver") == 0) { else if (strcmp(args[cur_arg], "ver") == 0) {
if (!*(args[cur_arg+1])) { if (!*(args[cur_arg+1])) {
@ -4070,8 +4077,8 @@ static struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg,
} }
} }
else { else {
memprintf(errmsg, "expects 'comment', 'meth', 'uri', 'ver', 'hdr' and 'body' but got '%s' as argument.", memprintf(errmsg, "expects 'comment', 'meth', 'uri', 'uri-lf', 'ver', 'hdr' and 'body'"
args[cur_arg]); " but got '%s' as argument.", args[cur_arg]);
goto error; goto error;
} }
cur_arg++; cur_arg++;
@ -4100,12 +4107,22 @@ static struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg,
} }
} }
if (uri) { if (uri) {
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)); chk->send.http.uri = ist2(strdup(uri), strlen(uri));
if (!isttest(chk->send.http.uri)) { if (!isttest(chk->send.http.uri)) {
memprintf(errmsg, "out of memory"); memprintf(errmsg, "out of memory");
goto error; goto error;
} }
} }
}
if (vsn) { if (vsn) {
chk->send.http.vsn = ist2(strdup(vsn), strlen(vsn)); chk->send.http.vsn = ist2(strdup(vsn), strlen(vsn));
if (!isttest(chk->send.http.vsn)) { if (!isttest(chk->send.http.vsn)) {