From: Christopher Faulet Date: Fri, 2 Oct 2026 16:05:29 +0000 (+0200) Subject: MINOR: filters: Add helpers to iterate and find filter configurations X-Git-Tag: v3.5-dev9~75 X-Git-Url: https://git.kaiwu.me/$%7BISSUES%7D/static/gitweb.js?a=commitdiff_plain;h=bf32f28b2cce96cc45a6f8b9b96821115eccb9df;p=haproxy.git MINOR: filters: Add helpers to iterate and find filter configurations 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. --- diff --git a/include/haproxy/filters.h b/include/haproxy/filters.h index 4f87aeb53..ea68a6bec 100644 --- a/include/haproxy/filters.h +++ b/include/haproxy/filters.h @@ -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); diff --git a/src/filters.c b/src/filters.c index 722ec7a40..482a2bae5 100644 --- a/src/filters.c +++ b/src/filters.c @@ -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 for each filter configuration of the proxy in the evaluation + * order of 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. + * 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 with the 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 + * is not NULL, it is called with each candidate and 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 in the global class references of and on each side its * class is placed on. All links were initialized on allocation.