]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: vars: make vars_get_by_* support an optional default value
authorWilly Tarreau <w@1wt.eu>
Fri, 3 Sep 2021 09:52:38 +0000 (11:52 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 3 Sep 2021 10:08:54 +0000 (12:08 +0200)
In preparation for support default values when fetching variables, we
need to update the internal API to pass an extra argument to functions
vars_get_by_{name,desc} to provide an optional default value. This
patch does this and always passes NULL in this argument. var_to_smp()
was extended to fall back to this value when available.

include/haproxy/vars.h
src/hlua.c
src/sample.c
src/vars.c

index f809c62d5bf066300342fad510eb1aa36aa3b4b3..0647cf346142bc0fc9d8f01dbd4a760c7f7ca695 100644 (file)
@@ -34,11 +34,11 @@ void var_accounting_diff(struct vars *vars, struct session *sess, struct stream
 unsigned int var_clear(struct var *var);
 void vars_prune(struct vars *vars, struct session *sess, struct stream *strm);
 void vars_prune_per_sess(struct vars *vars);
-int vars_get_by_name(const char *name, size_t len, struct sample *smp);
+int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def);
 int vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp);
 int vars_set_by_name(const char *name, size_t len, struct sample *smp);
 int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp);
-int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp);
+int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def);
 int vars_check_arg(struct arg *arg, char **err);
 
 #endif
index 039ebeca7741610ba787e415d2f2467eefaa5059..72d232491a2478ea35f0fc22f4c8085ca64351e3 100644 (file)
@@ -4382,7 +4382,7 @@ __LJMP static int hlua_applet_tcp_get_var(lua_State *L)
        s = luactx->htxn.s;
 
        smp_set_owner(&smp, s->be, s->sess, s, 0);
-       if (!vars_get_by_name(name, len, &smp)) {
+       if (!vars_get_by_name(name, len, &smp, NULL)) {
                lua_pushnil(L);
                return 1;
        }
@@ -4869,7 +4869,7 @@ __LJMP static int hlua_applet_http_get_var(lua_State *L)
        s = luactx->htxn.s;
 
        smp_set_owner(&smp, s->be, s->sess, s, 0);
-       if (!vars_get_by_name(name, len, &smp)) {
+       if (!vars_get_by_name(name, len, &smp, NULL)) {
                lua_pushnil(L);
                return 1;
        }
@@ -6966,7 +6966,7 @@ __LJMP static int hlua_get_var(lua_State *L)
        name = MAY_LJMP(luaL_checklstring(L, 2, &len));
 
        smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
-       if (!vars_get_by_name(name, len, &smp)) {
+       if (!vars_get_by_name(name, len, &smp, NULL)) {
                lua_pushnil(L);
                return 1;
        }
index a0727d236059fc0cddaeed12989abf5c9acdc76d..e4bb3182a6248de1638d8dfa9a04be192b2e7959 100644 (file)
@@ -1747,7 +1747,7 @@ static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *
                smp->flags = SMP_F_CONST;
                return 1;
        case ARGT_VAR:
-               if (!vars_get_by_desc(&arg->data.var, smp))
+               if (!vars_get_by_desc(&arg->data.var, smp, NULL))
                                return 0;
                if (!sample_casts[smp->data.type][SMP_T_STR])
                                return 0;
@@ -2990,7 +2990,7 @@ static inline int sample_conv_var2smp(const struct arg *arg, struct sample *smp)
                smp->data.u.sint = arg->data.sint;
                return 1;
        case ARGT_VAR:
-               if (!vars_get_by_desc(&arg->data.var, smp))
+               if (!vars_get_by_desc(&arg->data.var, smp, NULL))
                        return 0;
                if (!sample_casts[smp->data.type][SMP_T_SINT])
                        return 0;
@@ -3317,7 +3317,7 @@ static int sample_conv_concat(const struct arg *arg_p, struct sample *smp, void
         * into a string.
         */
        smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
-       if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp) &&
+       if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp, NULL) &&
            (sample_casts[tmp.data.type][SMP_T_STR] == c_none ||
             sample_casts[tmp.data.type][SMP_T_STR](&tmp))) {
 
@@ -3377,7 +3377,7 @@ static int sample_conv_strcmp(const struct arg *arg_p, struct sample *smp, void
        smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
        if (arg_p[0].type != ARGT_VAR)
                return 0;
-       if (!vars_get_by_desc(&arg_p[0].data.var, &tmp))
+       if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL))
                return 0;
        if (!sample_casts[tmp.data.type][SMP_T_STR](&tmp))
                return 0;
@@ -3415,7 +3415,7 @@ static int sample_conv_secure_memcmp(const struct arg *arg_p, struct sample *smp
        smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
        if (arg_p[0].type != ARGT_VAR)
                return 0;
-       if (!vars_get_by_desc(&arg_p[0].data.var, &tmp))
+       if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL))
                return 0;
        if (!sample_casts[tmp.data.type][SMP_T_BIN](&tmp))
                return 0;
index 236466b217994af0499ca7fcb314676511c1f547..df421f71ed1d212a78473e036cca8c11d13c58af 100644 (file)
@@ -340,7 +340,7 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char
 {
        const struct var_desc *var_desc = &args[0].data.var;
 
-       return vars_get_by_desc(var_desc, smp);
+       return vars_get_by_desc(var_desc, smp, NULL);
 }
 
 /* This function search in the <head> a variable with the same
@@ -574,10 +574,11 @@ int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
  * release the variables lock ASAP (so a pre-allocated chunk is obtained
  * via get_trash_shunk()). The variables' lock is used for reads.
  *
- * The function returns 0 if the variable was not found, otherwise 1
- * with the sample filled.
+ * The function returns 0 if the variable was not found and no default
+ * value was provided in <def>, otherwise 1 with the sample filled.
+ * Default values are always returned as strings.
  */
-static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
+static int var_to_smp(struct vars *vars, const char *name, struct sample *smp, const struct buffer *def)
 {
        struct var *var;
 
@@ -585,12 +586,19 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
        HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock);
        var = var_get(vars, name);
        if (!var) {
-               HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
-               return 0;
+               if (!def) {
+                       HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
+                       return 0;
+               }
+
+               /* not found but we have a default value */
+               smp->data.type = SMP_T_STR;
+               smp->data.u.str = *def;
        }
+       else
+               smp->data = var->data;
 
        /* Copy sample. */
-       smp->data = var->data;
        smp_dup(smp);
 
        HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
@@ -603,9 +611,13 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
  * and it therefore uses a pre-allocated trash chunk as returned by
  * get_trash_chunk().
  *
+ * If the variable is not valid in this scope, 0 is always returned.
+ * If the variable is valid but not found, either the default value
+ * <def> is returned if not NULL, or zero is returned.
+ *
  * Returns 1 if the sample is filled, otherwise it returns 0.
  */
-int vars_get_by_name(const char *name, size_t len, struct sample *smp)
+int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def)
 {
        struct vars *vars;
        enum vars_scope scope;
@@ -620,7 +632,8 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp)
        if (!vars || vars->scope != scope)
                return 0;
 
-       return var_to_smp(vars, name, smp);
+
+       return var_to_smp(vars, name, smp, def);
 }
 
 /* This function fills a sample with the content of the variable described
@@ -630,9 +643,13 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp)
  * and it therefore uses a pre-allocated trash chunk as returned by
  * get_trash_chunk().
  *
+ * If the variable is not valid in this scope, 0 is always returned.
+ * If the variable is valid but not found, either the default value
+ * <def> is returned if not NULL, or zero is returned.
+ *
  * Returns 1 if the sample is filled, otherwise it returns 0.
  */
-int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
+int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def)
 {
        struct vars *vars;
 
@@ -643,7 +660,7 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
        if (!vars || vars->scope != var_desc->scope)
                return 0;
 
-       return var_to_smp(vars, var_desc->name, smp);
+       return var_to_smp(vars, var_desc->name, smp, def);
 }
 
 /* Always returns ACT_RET_CONT even if an error occurs. */
@@ -739,7 +756,7 @@ static void release_store_rule(struct act_rule *rule)
 /* This two function checks the variable name and replace the
  * configuration string name by the global string name. its
  * the same string, but the global pointer can be easy to
- * compare.
+ * compare. They return non-zero on success, zero on failure.
  *
  * The first function checks a sample-fetch and the second
  * checks a converter.
@@ -989,7 +1006,7 @@ static int vars_parse_cli_get_var(char **args, char *payload, struct appctx *app
        if (!vars || vars->scope != SCOPE_PROC)
                return 0;
 
-       if (!vars_get_by_name(args[2], strlen(args[2]), &smp))
+       if (!vars_get_by_name(args[2], strlen(args[2]), &smp, NULL))
                return cli_err(appctx, "Variable not found.\n");
 
        /* the sample returned by vars_get_by_name() is allocated into a trash