]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tcpcheck: Add support for an option host header value for httpchk option
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 1 Oct 2024 16:40:40 +0000 (18:40 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 2 Oct 2024 08:22:51 +0000 (10:22 +0200)
Support for headers and body hidden in the version for the "option httpchk"
directive was removed. However a Host header is mandatory for HTTP/1.1
requests and some servers may return an error if it is not set. For now, to
add it, an "http-check send" rule must be added. But it is not really handy
to use an extra config line for this purpose.

So now, it is possible to set the host header value, a log-format string, as
extra argument to "option httpchk" directive. It must be the fourth argument:

  option httpchk GET / HTTP/1.1 www.srv.com

While this patch is not a bug fix, it is simple enough to be backported if
necessary. On 2.9 and older, lf_init_expr() does not exist and LIST_INIT() must
be used instead.

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

index 9972ce107aa6e76b563027ea311a840d46e1f65b..0e2836ee0296db7d2aa1f274f78ded36ab6c7eef 100644 (file)
@@ -9858,6 +9858,7 @@ option httpchk
 option httpchk <uri>
 option httpchk <method> <uri>
 option httpchk <method> <uri> <version>
+option httpchk <method> <uri> <version> <host>
   Enables HTTP protocol to check on the servers health
 
   May be used in the following contexts: tcp, http
@@ -9879,7 +9880,10 @@ option httpchk <method> <uri> <version>
     <version> is the optional HTTP version string. It defaults to "HTTP/1.0"
               but some servers might behave incorrectly in HTTP 1.0, so turning
               it to HTTP/1.1 may sometimes help. Note that the Host field is
-              mandatory in HTTP/1.1, use "http-check send" directive to add it.
+              mandatory in HTTP/1.1.
+
+    <host>    is the optional HTTP Host header value. It is not set by default.
+              It is a log-format string.
 
   By default, server health checks only consist in trying to establish a TCP
   connection. When "option httpchk" is specified, a complete HTTP request is
index 0cb6a167c5385e50fe26d7a7e12a53698ff4972e..31ef87abb0a46a15e256b6bb43b9336d89f6d2ff 100644 (file)
@@ -8,6 +8,7 @@ server s1 {
     expect req.method == OPTIONS
     expect req.url == /
     expect req.proto == HTTP/1.0
+    expect req.http.host == <undef>
     txresp
 } -start
 
@@ -16,6 +17,7 @@ server s2 {
     expect req.method == GET
     expect req.url == /status
     expect req.proto == HTTP/1.1
+    expect req.http.host == "www.haproxy.org"
     txresp
 } -start
 
@@ -102,7 +104,7 @@ haproxy h1 -conf {
 
     backend be2
         log ${S1_addr}:${S1_port} len 2048 local0
-        option httpchk GET /status HTTP/1.1
+        option httpchk GET /status HTTP/1.1 www.haproxy.org
         server srv ${s2_addr}:${s2_port} check inter 100ms rise 1 fall 1
 
     backend be3
index d5bd796f35d2e2a7fdd674981d9aca7203e05ea0..10aad1af82fffb62d3bf4e341938b3d95be6ca06 100644 (file)
@@ -5081,7 +5081,7 @@ static struct tcpcheck_rule *proxy_parse_httpchk_req(char **args, int cur_arg, s
 {
        struct tcpcheck_rule *chk = NULL;
        struct tcpcheck_http_hdr *hdr = NULL;
-       char *meth = NULL, *uri = NULL, *vsn = NULL;
+       char *meth = NULL, *uri = NULL, *vsn = NULL, *host = NULL;
        char *hdrs, *body;
 
        hdrs = (*args[cur_arg+2] ? strstr(args[cur_arg+2], "\r\n") : NULL);
@@ -5114,6 +5114,8 @@ static struct tcpcheck_rule *proxy_parse_httpchk_req(char **args, int cur_arg, s
                uri = args[cur_arg+1];
        if (*args[cur_arg+2])
                vsn = args[cur_arg+2];
+       if (*args[cur_arg+3])
+               host = args[cur_arg+3];
 
        if (meth) {
                chk->send.http.meth.meth = find_http_meth(meth, strlen(meth));
@@ -5138,6 +5140,24 @@ static struct tcpcheck_rule *proxy_parse_httpchk_req(char **args, int cur_arg, s
                        goto error;
                }
        }
+       if (host) {
+               hdr = calloc(1, sizeof(*hdr));
+               if (!hdr) {
+                       memprintf(errmsg, "out of memory");
+                       goto error;
+               }
+               lf_expr_init(&hdr->value);
+               hdr->name = istdup(ist("host"));
+               if (!isttest(hdr->name)) {
+                       memprintf(errmsg, "out of memory");
+                       goto error;
+               }
+
+               if (!parse_logformat_string(host, px, &hdr->value, 0, SMP_VAL_BE_CHK_RUL, errmsg))
+                       goto error;
+               LIST_APPEND(&chk->send.http.hdrs, &hdr->list);
+               hdr = NULL;
+       }
 
        return chk;
 
@@ -5160,7 +5180,7 @@ int proxy_parse_httpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
        if (warnifnotcap(curpx, PR_CAP_BE, file, line, args[cur_arg+1], NULL))
                err_code |= ERR_WARN;
 
-       if (alertif_too_many_args_idx(3, 1, file, line, args, &err_code))
+       if (alertif_too_many_args_idx(4, 1, file, line, args, &err_code))
                goto out;
 
        chk = proxy_parse_httpchk_req(args, cur_arg+2, curpx, &errmsg);