From 54496a6a5b29ca0a5ad0e0a916722d17cb734f2d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 3 Sep 2021 12:00:13 +0200 Subject: [PATCH] MINOR: vars: make the vars() sample fetch function support a default value It is quite common to see in configurations constructions like the following one: http-request set-var(txn.bodylen) 0 http-request set-var(txn.bodylen) req.hdr(content-length) ... http-request set-header orig-len %[var(txn.bodylen)] The set-var() rules are almost always duplicated when manipulating integers or any other value that is mandatory along operations. This is a problem because it makes the configurations complicated to maintain and slower than needed. And it becomes even more complicated when several conditions may set the same variable because the risk of forgetting to initialize it or to accidentally reset it is high. This patch extends the var() sample fetch function to take an optional argument which contains a default value to be returned if the variable was not set. This way it becomes much simpler to use the variable, just set it where needed, and read it with a fall back to the default value: http-request set-var(txn.bodylen) req.hdr(content-length) ... http-request set-header orig-len %[var(txn.bodylen,0)] The default value is always passed as a string, thus it will experience a cast to the output type. It doesn't seem userful to complicate the configuration to pass an explicit type at this point. The vars.vtc regtest was updated accordingly. --- doc/configuration.txt | 7 ++++--- reg-tests/sample_fetches/vars.vtc | 3 ++- src/vars.c | 8 ++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index f6641750d..1a8eb5be7 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -17764,10 +17764,11 @@ uuid([]) : string specified, a UUID version 4 (fully random) is returned. Currently, only version 4 is supported. -var() : undefined +var([,]) : undefined Returns a variable with the stored type. If the variable is not set, the - sample fetch fails. The name of the variable starts with an indication - about its scope. The scopes allowed are: + sample fetch fails, unless a default value is provided, in which case it will + return it as a string. Empty strings are permitted. The name of the variable + starts with an indication about its scope. The scopes allowed are: "proc" : the variable is shared with the whole process "sess" : the variable is shared with the whole session "txn" : the variable is shared with the transaction (request and diff --git a/reg-tests/sample_fetches/vars.vtc b/reg-tests/sample_fetches/vars.vtc index 5dc7b4400..8a04718b4 100644 --- a/reg-tests/sample_fetches/vars.vtc +++ b/reg-tests/sample_fetches/vars.vtc @@ -5,8 +5,9 @@ feature ignore_unknown_macro haproxy h1 -conf { global + # note below, str60 is purposely not defined so that the default is used set-var proc.int12 int(12) - set-var proc.int5 str(60),div(proc.int12) + set-var proc.int5 var(proc.str60,60),div(proc.int12) set-var proc.str1 str("this is") set-var proc.str2 str("a string") set-var proc.str var(proc.str1) diff --git a/src/vars.c b/src/vars.c index df421f71e..1e8e1bd30 100644 --- a/src/vars.c +++ b/src/vars.c @@ -339,8 +339,12 @@ static inline struct var *var_get(struct vars *vars, const char *name) static int smp_fetch_var(const struct arg *args, struct sample *smp, const char *kw, void *private) { const struct var_desc *var_desc = &args[0].data.var; + const struct buffer *def = NULL; - return vars_get_by_desc(var_desc, smp, NULL); + if (args[1].type == ARGT_STR) + def = &args[1].data.str; + + return vars_get_by_desc(var_desc, smp, def); } /* This function search in the a variable with the same @@ -1193,7 +1197,7 @@ REGISTER_POST_DEINIT(vars_deinit); static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { - { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_CONST }, + { "var", smp_fetch_var, ARG2(1,STR,STR), smp_check_var, SMP_T_STR, SMP_USE_CONST }, { /* END */ }, }};