From: Christopher Faulet Date: Tue, 1 Oct 2024 16:40:40 +0000 (+0200) Subject: MINOR: tcpcheck: Add support for an option host header value for httpchk option X-Git-Tag: v3.1-dev9~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=27ee2927313aee25f83cf4173ccf2c4e14d58738;p=thirdparty%2Fhaproxy.git MINOR: tcpcheck: Add support for an option host header value for httpchk option 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. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 9972ce107a..0e2836ee02 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9858,6 +9858,7 @@ option httpchk option httpchk option httpchk option httpchk +option httpchk Enables HTTP protocol to check on the servers health May be used in the following contexts: tcp, http @@ -9879,7 +9880,10 @@ option httpchk 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. + + 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 diff --git a/reg-tests/checks/http-check.vtc b/reg-tests/checks/http-check.vtc index 0cb6a167c5..31ef87abb0 100644 --- a/reg-tests/checks/http-check.vtc +++ b/reg-tests/checks/http-check.vtc @@ -8,6 +8,7 @@ server s1 { expect req.method == OPTIONS expect req.url == / expect req.proto == HTTP/1.0 + expect req.http.host == 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 diff --git a/src/tcpcheck.c b/src/tcpcheck.c index d5bd796f35..10aad1af82 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -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);