]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks: Support log-format string to set the URI for HTTP send rules
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 May 2020 13:06:34 +0000 (15:06 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 May 2020 16:04:05 +0000 (18:04 +0200)
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
reg-tests/checks/http-check.vtc
src/checks.c

index 80aa83fc7eee8c705d1f4597ff9b318f06a8d527..da5d05e78132c809616f7fbed67935b73a165047 100644 (file)
@@ -4681,8 +4681,8 @@ http-check expect [min-recv <int>] [comment <msg>]
              and "http-check send".
 
 
-http-check send [meth <method>] [uri <uri>] [ver <version>] [comment <msg>]
-                [hdr <name> <fmt>]* [body <string>]
+http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
+                [hdr <name> <fmt>]* [body <string>] [comment <msg>]
   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 <method>] [uri <uri>] [ver <version>] [comment <msg>]
                    logs. Any method may be used, though it is not recommended
                    to invent non-standard ones.
 
-    uri <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 <uri>      is optional and set the URI referenced in the HTTP requests
+                   to the string <uri>. 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 <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
                    "HTTP/1.0" but some servers might behave incorrectly in HTTP
index 057484f24c6e346a05f9f52acd43a2fa13ebbf58..3de3e3f8fe98430e5a13b5ac4d4672e0238ebdb5 100644 (file)
@@ -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 == <undef>
+    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 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 send meth GET uri /req3
+        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
 
index d5306defe05f77039562ba30fd1c1fcfec4b8f62..0723488a6a8e71322aac62c1d02442fac0ed7065 100644 (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)
                        ? 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) {