]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: filters: Add helpers to iterate and find filter configurations
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 2 Oct 2026 16:05:29 +0000 (18:05 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 9 Oct 2026 14:17:36 +0000 (16:17 +0200)
Add flt_foreach_conf() to walk the filter configurations of a proxy in
the evaluation order of a given side, and flt_find_conf() to look up the
first configuration matching an id and an optional callback.

Both helpers select the legacy filter configurations (px->filter_configs)
when the proxy is in legacy mode, and the finalized filter instances
otherwise, following the global, request or response order. They will let
the filter callbacks and the action parsers work in both modes without
duplicating the list selection.

The helpers are not used yet.

include/haproxy/filters.h
src/filters.c

index 4f87aeb53c3f6af9fda6d3806e71de36db1caf4e..ea68a6bec0dc3ead29c402edef5ddb3e3a0b435c 100644 (file)
@@ -158,6 +158,11 @@ int  flt_add_implicit_instance(struct proxy *px, struct filter_class *cls, const
                                 char **args, const char *file, int line);
 struct filter_instance *flt_find_instance(struct proxy *px, struct filter_class *cls, const char *id);
 
+int flt_foreach_conf(struct proxy *px, unsigned int side,
+                    int (*fct)(struct flt_conf *fconf, void *data), void *data);
+struct flt_conf *flt_find_conf(struct proxy *px, const char *flt_id, unsigned int side,
+                              int (*match)(struct flt_conf *fconf, void *data), void *data);
+
 int  flt_stream_start(struct stream *s);
 void flt_stream_stop(struct stream *s);
 int  flt_set_stream_backend(struct stream *s, struct proxy *be);
index 722ec7a409b65068b3364c5a7091ef25ca516063..482a2bae58d58efeb30765f5ecd0102906012dd1 100644 (file)
@@ -1705,6 +1705,97 @@ struct filter_instance *flt_find_instance(struct proxy *px, struct filter_class
        return flt_find_instance_count(px, cls, id, NULL);
 }
 
+/* Calls <fct> for each filter configuration of the proxy <px> in the evaluation
+ * order of side <side> (FLT_SIDE_GLOBAL, FLT_SIDE_REQ or FLT_SIDE_RES). if the
+ * proxy is in legacy mode (PR_FL_FILTER_LEGACY) the filter_configs list is used.
+ * <fct> must return 0 to continue, any other value to stop immediately; that
+ * value is then returned.
+ */
+int flt_foreach_conf(struct proxy *px, unsigned int side,
+                    int (*fct)(struct flt_conf *fconf, void *data), void *data)
+{
+       struct filter_instance *inst;
+       struct flt_conf *fconf;
+       int ret = 0;
+
+       if (flt_use_legacy_filter(px)) {
+               list_for_each_entry(fconf, &px->filter_configs, list) {
+                       ret = fct(fconf, data);
+                       if (ret)
+                               break;
+               }
+               return ret;
+       }
+
+       if (side == FLT_SIDE_GLOBAL) {
+               list_for_each_entry(inst, &px->filter_instances, global.list) {
+                       if (!inst->fconf)
+                               continue;
+                       ret = fct(inst->fconf, data);
+                       if (ret)
+                               break;
+               }
+       }
+       else if (side == FLT_SIDE_REQ) {
+               list_for_each_entry(inst, &px->filter_req_instances, req.list) {
+                       if (!inst->fconf)
+                               continue;
+                       ret = fct(inst->fconf, data);
+                       if (ret)
+                               break;
+               }
+       }
+       else {
+               list_for_each_entry(inst, &px->filter_res_instances, res.list) {
+                       if (!inst->fconf)
+                               continue;
+                       ret = fct(inst->fconf, data);
+                       if (ret)
+                               break;
+               }
+       }
+       return ret;
+}
+
+/* Context for flt_find_conf_cb() */
+struct flt_find_conf_ctx {
+       const char *flt_id;                          /* the filter id to match, NULL for any id */
+       int (*match)(struct flt_conf *fconf, void *data); /* optional extra match */
+       void *data;                                  /* data for the match callback */
+       struct flt_conf *found;                      /* the first matching configuration */
+};
+
+/* Callback matching the filter configurations with the id ctx->flt_id (any
+ * id if NULL) and the ctx->match callback if set. The first match is
+ * recorded in ctx->found and the iteration stops.
+ */
+static int flt_find_conf_cb(struct flt_conf *fconf, void *data)
+{
+       struct flt_find_conf_ctx *ctx = data;
+
+       if (ctx->flt_id && fconf->id != ctx->flt_id)
+               return 0;
+       if (ctx->match && !ctx->match(fconf, ctx->data))
+               return 0;
+       ctx->found = fconf;
+       return 1;
+}
+
+/* Finds a filter configuration of the proxy <px> with the id <flt_id> (any
+ * id if NULL), from the filter instances by default or from the legacy
+ * filters if the proxy is in legacy mode (see flt_foreach_conf()). If
+ * <match> is not NULL, it is called with each candidate and <data> and must
+ * return non-zero to accept it. Returns the first match, or NULL if none.
+ */
+struct flt_conf *flt_find_conf(struct proxy *px, const char *flt_id, unsigned int side,
+                              int (*match)(struct flt_conf *fconf, void *data), void *data)
+{
+       struct flt_find_conf_ctx ctx = { .flt_id = flt_id, .match = match, .data = data, .found = NULL };
+
+       flt_foreach_conf(px, side, flt_find_conf_cb, &ctx);
+       return ctx.found;
+}
+
 
 /* Links <inst> in the global class references of <px> and on each side its
  * class is placed on. All links were initialized on allocation.