From 19a69b3740702ce5503a063e9dfbcea5b9187d27 Mon Sep 17 00:00:00 2001 From: Baptiste Assmann Date: Thu, 16 Jan 2020 14:34:22 +0100 Subject: [PATCH] BUG/MINOR: http_act: don't check capture id in backend A wrong behavior was introduced by e9544935e86278dfa3d49fb4b97b860774730625, leading to preventing loading any configuration where a capture slot id is used in a backend. IE, the configuration below does not parse: frontend f bind *:80 declare capture request len 32 default_backend webserver backend webserver http-request capture req.hdr(Host) id 1 The point is that such type of configuration is valid and should run. This patch enforces the check of capture slot id only if the action rule is configured in a frontend. The point is that at configuration parsing time, it is impossible to check which frontend could point to this backend (furthermore if we use dynamic backend name resolution at runtime). The documentation has been updated to warn the user to ensure that relevant frontends have required declaration when such rule has to be used in a backend. If no capture slot can be found, then the action will just not be executed and HAProxy will process the next one in the list, as expected. This should be backported to all supported branches (bug created as part of a bug fix introduced into 1.7 and backported to 1.6). --- doc/configuration.txt | 16 +++++++++++----- src/http_act.c | 5 ++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 0e69b206c2..ba7cb960e4 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4391,9 +4391,12 @@ http-request capture [ len | id ] If the keyword "id" is used instead of "len", the action tries to store the captured string in a previously declared capture slot. This is useful to run captures in backends. The slot id can be declared by a previous directive - "http-request capture" or with the "declare capture" keyword. If the slot - doesn't exist, then HAProxy fails parsing the configuration to prevent - unexpected behavior at run time. + "http-request capture" or with the "declare capture" keyword. + + When using this action in a backend, double check that the relevant + frontend(s) have the required capture slots otherwise, this rule will be + ignored at run time. This can't be detected at configuration parsing time + due to HAProxy's ability to dynamically resolve backend name at runtime. http-request del-acl() [ { if | unless } ] @@ -5097,8 +5100,11 @@ http-response capture id [ { if | unless } ] This is useful to run captures in backends. The slot id can be declared by a previous directive "http-response capture" or with the "declare capture" keyword. - If the slot doesn't exist, then HAProxy fails parsing the configuration - to prevent unexpected behavior at run time. + + When using this action in a backend, double check that the relevant + frontend(s) have the required capture slots otherwise, this rule will be + ignored at run time. This can't be detected at configuration parsing time + due to HAProxy's ability to dynamically resolve backend name at runtime. http-response del-acl() [ { if | unless } ] diff --git a/src/http_act.c b/src/http_act.c index 774df140ad..a7f9e119dc 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -494,7 +494,10 @@ static int check_http_req_capture(struct act_rule *rule, struct proxy *px, char if (rule->action_ptr != http_action_req_capture_by_id) return 1; - if (rule->arg.capid.idx >= px->nb_req_cap) { + /* capture slots can only be declared in frontends, so we can't check their + * existence in backends at configuration parsing step + */ + if (px->cap & PR_CAP_FE && rule->arg.capid.idx >= px->nb_req_cap) { memprintf(err, "unable to find capture id '%d' referenced by http-request capture rule", rule->arg.capid.idx); return 0;