]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks: Simplify matching on HTTP headers in HTTP expect rules
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 5 May 2020 18:23:13 +0000 (20:23 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 6 May 2020 10:42:36 +0000 (12:42 +0200)
Extra parameters on http-check expect rules, for the header matching method, to
use log-format string or to match full header line have been removed. There is
now separate matching methods to match a full header line or to match each
comma-separated values. "http-check expect fhdr" must be used in the first case,
and "http-check expect hdr" in the second one. In addition, to match log-format
header name or value, "-lf" suffix must be added to "name" or "value"
keyword. For intance:

   http-check expect hdr name "set-cookie" value-lf -m beg "sessid=%[var(check.cookie)]"

Thanks to this changes, each parameter may only be interpreted in one way.

doc/configuration.txt
reg-tests/checks/http-check-expect.vtc
src/checks.c

index b183b98e4158ec69b2d6fff3cd4a11277eba46a2..80aa83fc7eee8c705d1f4597ff9b318f06a8d527 100644 (file)
@@ -4560,8 +4560,8 @@ http-check expect [min-recv <int>] [comment <msg>]
                        log-format string.
 
     <match>   is a keyword indicating how to look for a specific pattern in the
-              response. The keyword may be one of "status", "rstatus",
-              "string", or "rstring". The keyword may be preceded by an
+              response. The keyword may be one of "status", "rstatus", "hdr",
+              "fhdr", "string", or "rstring". The keyword may be preceded by an
               exclamation mark ("!") to negate the match. Spaces are allowed
               between the exclamation mark and the keyword. See below for more
               details on the supported keywords.
@@ -4592,8 +4592,8 @@ http-check expect [min-recv <int>] [comment <msg>]
                       will be considered invalid if the status code matches.
                       This is mostly used to check for multiple codes.
 
-    header name [ -m <meth> ] <name> [log-format]
-           [ value [ -m <meth> ] <value> [log-format] [full] ] :
+    hdr  { name | name-lf } [ -m <meth> ] <name>
+         [ { value | value-lf } [ -m <meth> ] <value> :
                       test the specified header pattern on the HTTP response
                       headers. The name pattern is mandatory but the value
                       pattern is optional. If not specified, only the header
@@ -4602,14 +4602,20 @@ http-check expect [min-recv <int>] [comment <msg>]
                       matching methods are "str" (exact match), "beg" (prefix
                       match), "end" (suffix match), "sub" (substring match) or
                       "reg" (regex match). If not specified, exact matching
-                      method is used. If the "log-format" option is used, the
-                      pattern (<name> or <value>) is evaluated as a log-format
-                      string. This option cannot be used with the regex
-                      matching method. Finally, by default, the header value is
-                      considered as comma-separated list. Each part may be
-                      tested. The "full" option may be used to test the full
-                      header line. Note that matchings are case insensitive on
-                      the header names.
+                      method is used. If the "name-lf" parameter is used,
+                      <name> is evaluated as a log-format string. If "value-lf"
+                      parameter is used, <value> is evaluated as a log-format
+                      string. These parameters cannot be used with the regex
+                      matching method. Finally, the header value is considered
+                      as comma-separated list. Note that matchings are case
+                      insensitive on the header names.
+
+    fhdr { name | name-lf } [ -m <meth> ] <name>
+         [ { value | value-lf } [ -m <meth> ] <value> :
+                      test the specified full header pattern on the HTTP
+                      response headers. It does exactly the same than "hdr"
+                      keyword, except the full header value is tested, commas
+                      are not considered as delimiters.
 
     string <string> : test the exact string match in the HTTP response body.
                       A health check response will be considered valid if the
index 9cbe2bd7be9f7604f9396ac17248bc4d1f00db7a..ab629db8e51d34348b450652ab142717324cc509 100644 (file)
@@ -39,26 +39,26 @@ haproxy h1 -conf {
         option httpchk
        http-check expect status 200-399
 
-       http-check expect header name "x-test1"
-       http-check expect header name -m str "X-Test2"
-       http-check expect header name -m beg "X-Begin-"
-       http-check expect header name -m end "-End"
-       http-check expect header name -m sub "-Sub-"
-       http-check expect header name -m reg "^[a-z]+-Reg-[a-z]+[0-9]\$"
+       http-check expect hdr name "x-test1"
+       http-check expect hdr name -m str "X-Test2"
+       http-check expect hdr name -m beg "X-Begin-"
+       http-check expect hdr name -m end "-End"
+       http-check expect hdr name -m sub "-Sub-"
+       http-check expect hdr name -m reg "^[a-z]+-Reg-[a-z]+[0-9]\$"
        http-check set-var(check.hdr_name) res.fhdr(x-hdr-name)
-       http-check expect header name -m str "%[var(check.hdr_name)]" log-format
-       http-check expect header name -m str "%[res.fhdr(x-hdr-name)]" log-format
+       http-check expect hdr name-lf -m str "%[var(check.hdr_name)]"
+       http-check expect hdr name-lf -m str "%[res.fhdr(x-hdr-name)]"
 
-       http-check expect header name "x-test1" value "true, next value" full
-       http-check expect header name "x-test2" value -m str "true"
-       http-check expect header name -m beg "x-test" value -m beg "begin-"
-       http-check expect header name -m beg "x-test" value -m end "-end"
-       http-check expect header name -m beg "x-test" value -m sub "-sub-"
-       http-check expect header name -m beg "x-test" value -m reg "^value-reg-[A-Z0-9]+\$"
-       http-check expect header name -m beg "x-test" value -m reg "value-reg-[A-Z0-9]+" full
+       http-check expect fhdr name "x-test1" value "true, next value"
+       http-check expect hdr name "x-test2" value -m str "true"
+       http-check expect hdr name -m beg "x-test" value -m beg "begin-"
+       http-check expect hdr name -m beg "x-test" value -m end "-end"
+       http-check expect hdr name -m beg "x-test" value -m sub "-sub-"
+       http-check expect hdr name -m beg "x-test" value -m reg "^value-reg-[A-Z0-9]+\$"
+       http-check expect fhdr name -m beg "x-test" value -m reg "value-reg-[A-Z0-9]+"
        http-check set-var(check.hdr_value) str(x-test1)
-       http-check expect header name -m beg "x-" value -m str "%[var(check.hdr_value)]" log-format
-       http-check expect header name -m beg "x-" value -m str "%[res.fhdr(x-hdr-name)]" log-format full
+       http-check expect hdr name -m beg "x-" value-lf -m str "%[var(check.hdr_value)]"
+       http-check expect fhdr name -m beg "x-" value-lf -m str "%[res.fhdr(x-hdr-name)]"
 
         server srv ${s1_addr}:${s1_port} check inter 100ms rise 1 fall 1
 } -start
index 172cdd6082ab692eb9e2a5fd3997759d373fe98f..d5306defe05f77039562ba30fd1c1fcfec4b8f62 100644 (file)
@@ -4319,7 +4319,7 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                        }
                        type = TCPCHK_EXPECT_CUSTOM;
                }
-               else if (strcmp(args[cur_arg], "header") == 0) {
+               else if (strcmp(args[cur_arg], "hdr") == 0 || strcmp(args[cur_arg], "fhdr") == 0) {
                        int orig_arg = cur_arg;
 
                        if (proto != TCPCHK_RULES_HTTP_CHK)
@@ -4330,12 +4330,20 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                        }
                        type = TCPCHK_EXPECT_HTTP_HEADER;
 
+                       if (strcmp(args[cur_arg], "fhdr") == 0)
+                               flags |= TCPCHK_EXPT_FL_HTTP_HVAL_FULL;
+
                        /* Parse the name pattern, mandatory */
-                       if (!*(args[cur_arg+1]) || !*(args[cur_arg+2]) || strcmp(args[cur_arg+1], "name") != 0) {
-                               memprintf(errmsg, "'%s' expects at the keyword name as first argument followed by a pattern",
+                       if (!*(args[cur_arg+1]) || !*(args[cur_arg+2]) ||
+                           (strcmp(args[cur_arg+1], "name") != 0 && strcmp(args[cur_arg+1], "name-lf") != 0)) {
+                               memprintf(errmsg, "'%s' expects at the name keyword as first argument followed by a pattern",
                                          args[orig_arg]);
                                goto error;
                        }
+
+                       if (strcmp(args[cur_arg+1], "name-lf") == 0)
+                               flags |= TCPCHK_EXPT_FL_HTTP_HNAME_FMT;
+
                        cur_arg += 2;
                        if (strcmp(args[cur_arg], "-m") == 0) {
                                if  (!*(args[cur_arg+1])) {
@@ -4351,8 +4359,14 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                                        flags |= TCPCHK_EXPT_FL_HTTP_HNAME_END;
                                else if (strcmp(args[cur_arg+1], "sub") == 0)
                                        flags |= TCPCHK_EXPT_FL_HTTP_HNAME_SUB;
-                               else if (strcmp(args[cur_arg+1], "reg") == 0)
+                               else if (strcmp(args[cur_arg+1], "reg") == 0) {
+                                       if (flags & TCPCHK_EXPT_FL_HTTP_HNAME_FMT) {
+                                               memprintf(errmsg, "'%s': log-format string is not supported with a regex matching method",
+                                                         args[orig_arg]);
+                                               goto error;
+                                       }
                                        flags |= TCPCHK_EXPT_FL_HTTP_HNAME_REG;
+                               }
                                else {
                                        memprintf(errmsg, "'%s' : '%s' only supports 'str', 'beg', 'end', 'sub' or 'reg' (got '%s')",
                                                  args[orig_arg], args[cur_arg], args[cur_arg+1]);
@@ -4364,29 +4378,17 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                                flags |= TCPCHK_EXPT_FL_HTTP_HNAME_STR;
                        npat = args[cur_arg];
 
-                       if (!(*args[cur_arg+1])) {
-                               flags |= TCPCHK_EXPT_FL_HTTP_HVAL_NONE;
-                               goto next;
-                       }
-
-                       if (strcmp(args[cur_arg+1], "log-format") == 0) {
-                               if (flags & TCPCHK_EXPT_FL_HTTP_HNAME_REG) {
-                                       memprintf(errmsg, "'%s': '%s' cannot be used with a regex matching pattern",
-                                                 args[orig_arg], args[cur_arg+1]);
-                                       goto error;
-                               }
-                               flags |= TCPCHK_EXPT_FL_HTTP_HNAME_FMT;
-                               cur_arg++;
-                       }
-
-                       if (!(*args[cur_arg+1]) || strcmp(args[cur_arg+1], "value") != 0) {
+                       if (!*(args[cur_arg+1]) ||
+                           (strcmp(args[cur_arg+1], "value") != 0 && strcmp(args[cur_arg+1], "value-lf") != 0)) {
                                flags |= TCPCHK_EXPT_FL_HTTP_HVAL_NONE;
                                goto next;
                        }
+                       if (strcmp(args[cur_arg+1], "value-lf") == 0)
+                               flags |= TCPCHK_EXPT_FL_HTTP_HVAL_FMT;
 
                        /* Parse the value pattern, optionnal */
-                       cur_arg += 2;
-                       if (strcmp(args[cur_arg], "-m") == 0) {
+                       if (strcmp(args[cur_arg+2], "-m") == 0) {
+                               cur_arg += 2;
                                if  (!*(args[cur_arg+1])) {
                                        memprintf(errmsg, "'%s' : '%s' expects at a matching pattern ('str', 'beg', 'end', 'sub' or 'reg')",
                                                  args[orig_arg], args[cur_arg]);
@@ -4400,34 +4402,29 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                                        flags |= TCPCHK_EXPT_FL_HTTP_HVAL_END;
                                else if (strcmp(args[cur_arg+1], "sub") == 0)
                                        flags |= TCPCHK_EXPT_FL_HTTP_HVAL_SUB;
-                               else if (strcmp(args[cur_arg+1], "reg") == 0)
+                               else if (strcmp(args[cur_arg+1], "reg") == 0) {
+                                       if (flags & TCPCHK_EXPT_FL_HTTP_HVAL_FMT) {
+                                               memprintf(errmsg, "'%s': log-format string is not supported with a regex matching method",
+                                                         args[orig_arg]);
+                                               goto error;
+                                       }
                                        flags |= TCPCHK_EXPT_FL_HTTP_HVAL_REG;
+                               }
                                else {
                                        memprintf(errmsg, "'%s' : '%s' only supports 'str', 'beg', 'end', 'sub' or 'reg' (got '%s')",
                                                  args[orig_arg], args[cur_arg], args[cur_arg+1]);
                                        goto error;
                                }
-                               cur_arg += 2;
                        }
                        else
                                flags |= TCPCHK_EXPT_FL_HTTP_HVAL_STR;
-                       vpat = args[cur_arg];
 
-                       while (*args[cur_arg+1]) {
-                               if (strcmp(args[cur_arg+1], "log-format") == 0) {
-                                       if (flags & TCPCHK_EXPT_FL_HTTP_HVAL_REG) {
-                                               memprintf(errmsg, "'%s': '%s' cannot be used with a regex matching pattern",
-                                                         args[orig_arg], args[cur_arg+1]);
-                                               goto error;
-                                       }
-                                       flags |= TCPCHK_EXPT_FL_HTTP_HVAL_FMT;
-                               }
-                               else if (strcmp(args[cur_arg+1], "full") == 0)
-                                       flags |= TCPCHK_EXPT_FL_HTTP_HVAL_FULL;
-                               else
-                                       break;
-                               cur_arg++;
+                       if (!*(args[cur_arg+2])) {
+                               memprintf(errmsg, "'%s' expect a pattern with the value keyword", args[orig_arg]);
+                               goto error;
                        }
+                       vpat = args[cur_arg+2];
+                       cur_arg += 2;
                }
                else if (strcmp(args[cur_arg], "comment") == 0) {
                        if (in_pattern) {
@@ -4574,7 +4571,7 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                        if (proto == TCPCHK_RULES_HTTP_CHK) {
                          bad_http_kw:
                                memprintf(errmsg, "'only supports min-recv, [!]string', '[!]rstring', '[!]string-lf', '[!]status', "
-                                         "'[!]rstatus', [!]header or comment but got '%s' as argument.", args[cur_arg]);
+                                         "'[!]rstatus', [!]hdr, [!]fhdr or comment but got '%s' as argument.", args[cur_arg]);
                        }
                        else {
                          bad_tcp_kw: