]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: filters: Add instance parsers for the built-in classes
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 30 Sep 2026 16:10:22 +0000 (18:10 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 9 Oct 2026 14:17:35 +0000 (16:17 +0200)
Connect built-in classes to parsers that produce a instance's flt_conf
without attaching it to the legacy evaluation list.

Provide a bridge to legacy keyword parsers, translating the stored argument
vector to their empty-string-terminated convention and rejecting leftover
arguments. Use it for trace, bandwidth limitation, SPOE and Lua; restore
curproxy around SPOE parsing and resolve Lua filters by instance id.

Use dedicated parsers for cache, FCGI, compression and decompression so
their legacy implicit/explicit reconciliation does not modify
filter_configs.  Cache and FCGI application names are supplied by the
instance identifier.  The filter-config directive and instance finalization
follow separately.

include/haproxy/filters.h
src/cache.c
src/fcgi-app.c
src/filters.c
src/flt_bwlim.c
src/flt_decomp.c
src/flt_http_comp.c
src/flt_spoe.c
src/flt_trace.c
src/hlua.c

index 69808e271c1e389112a83c29bd0bc82d74715480..707561b9f0e98255a7bb4c2e4755b70fb1bcb7aa 100644 (file)
@@ -67,6 +67,27 @@ extern const char *fcgi_filter_cls_name;
 extern struct filter_class flt_fcgi_cls;
 #endif
 
+/* Parsing functions of the internal filter classes, called to finalize a
+ * filter instance (see "filter-config" directive)
+ */
+int trace_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int cache_store_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int http_comp_req_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int http_comp_res_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int decomp_req_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int decomp_res_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+#if defined(USE_LUA)
+int hlua_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+#endif
+#if defined(USE_SPOE)
+int spoe_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+#endif
+int bwlim_in_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+int bwlim_out_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+#if defined(USE_FCGI)
+int fcgi_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err);
+#endif
+
 #define FLT_ID(flt)   (flt)->config->id
 #define FLT_CONF(flt) (flt)->config->conf
 #define FLT_OPS(flt)  (flt)->config->ops
@@ -273,6 +294,18 @@ flt_update_offsets(struct filter *filter, struct channel *chn, int len)
 
 struct filter_class *filter_find_class(const char *name);
 
+/* Helper function for filter classes: calls the legacy "filter" keyword
+ * parsing function <parse> on the arguments of the filter instance <inst>,
+ * as if the line "filter <kw> <inst args...>" was found in the configuration
+ * of the proxy <px>. <private> is passed as-is to the parsing function.
+ * Returns 0 on success, < 0 on error.
+ */
+int flt_parse_instance_legacy(struct proxy *px, struct filter_instance *inst, char **err,
+                        const char *kw,
+                        int (*parse)(char **args, int *cur_arg, struct proxy *px,
+                                     struct flt_conf *fconf, char **err, void *private),
+                        void *private);
+
 int filter_register_class(struct filter_class *cls, const char *name,
                          int (*parse)(char **args, struct proxy *px,
                                       struct filter_instance *inst, char **err));
index ed8729dcd1ede75ad17172320742954b72c6ab8f..aeb17735f2deb079f7dc87debb8a83c257bc52b4 100644 (file)
@@ -3606,6 +3606,44 @@ parse_cache_flt(char **args, int *cur_arg, struct proxy *px,
        return -1;
 }
 
+/* Parse the arguments of a "cache-store" filter instance. The cache name is the
+ * instance id (the id is mandatory for this class, several instances are
+ * allowed), no argument is expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int cache_store_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct cache_flt_conf *cconf;
+
+       if (!inst->id) {
+               memprintf(err, "'filter-config %s' : missing filter instance id",
+                         cache_store_filter_cls_name);
+               return -1;
+       }
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         cache_store_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       cconf = calloc(1, sizeof(*cconf));
+       if (!cconf) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       cconf->c.name = strdup(inst->id);
+       if (!cconf->c.name) {
+               free(cconf);
+               memprintf(err, "out of memory");
+               return -1;
+       }
+
+       inst->fconf->id   = cache_store_flt_id;
+       inst->fconf->conf = cconf;
+       inst->fconf->ops  = &cache_ops;
+       return 0;
+}
+
 /* It reserves a struct show_cache_ctx for the local variables */
 static int cli_parse_show_cache(char **args, char *payload, struct appctx *appctx, void *private)
 {
index caecc129eddf01f69baabf9170405aab1d99e312..29f355a879f0ff00a7d6aed83553a361dbf6ce03 100644 (file)
@@ -561,6 +561,45 @@ parse_fcgi_flt(char **args, int *cur_arg, struct proxy *px,
        return -1;
 }
 
+/* Parse the arguments of a "fcgi" filter instance. The fcgi-app name is the
+ * instance id, it must be set, and no argument is expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int fcgi_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct fcgi_flt_conf *fcgi_conf;
+
+       if (!inst->id) {
+               memprintf(err, "'filter-config %s' : missing filter instance id, the fcgi-app name is expected",
+                         fcgi_filter_cls_name);
+               return -1;
+       }
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         fcgi_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       fcgi_conf = calloc(1, sizeof(*fcgi_conf));
+       if (!fcgi_conf) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       fcgi_conf->name = strdup(inst->id);
+       if (!fcgi_conf->name) {
+               free(fcgi_conf);
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       LIST_INIT(&fcgi_conf->param_rules);
+       LIST_INIT(&fcgi_conf->hdr_rules);
+
+       inst->fconf->id   = fcgi_flt_id;
+       inst->fconf->conf = fcgi_conf;
+       inst->fconf->ops  = &fcgi_flt_ops;
+       return 0;
+}
+
 /* Parses the "use-fcgi-app" proxy keyword */
 static int proxy_parse_use_fcgi_app(char **args, int section, struct proxy *curpx,
                                    const struct proxy *defpx, const char *file, int line,
index a56c5c0d68e615c8e47a96df34f0ab5bc13783df..1c4da4825f6206d7e14804be7ba5435f2f823cbb 100644 (file)
@@ -1759,6 +1759,42 @@ int flt_init_class_refs(struct proxy *px)
        return -1;
 }
 
+/* Helper function for filter classes: calls the legacy "filter" keyword
+ * parsing function <parse> on the arguments of the filter instance <inst>,
+ * as if the line "filter <kw> <inst args...>" was found in the configuration
+ * of the proxy <px>. <private> is passed as-is to the parsing function.
+ * Returns 0 on success, < 0 on error.
+ */
+int flt_parse_instance_legacy(struct proxy *px, struct filter_instance *inst, char **err,
+                        const char *kw,
+                        int (*parse)(char **args, int *cur_arg, struct proxy *px,
+                                     struct flt_conf *fconf, char **err, void *private),
+                        void *private)
+{
+       char *fargs[MAX_LINE_ARGS+1];
+       int i, ret, cur_arg;
+
+       /* the legacy parsing functions expect the keyword at args[*cur_arg],
+        * followed by the filter arguments. Like for the config parser, the
+        * arguments must be terminated by an empty string, not a NULL pointer.
+        */
+
+       fargs[0] = (char *)kw;
+       for (i = 0; inst->conf.argv[i] && *inst->conf.argv[i]; i++)
+               fargs[i+1] = inst->conf.argv[i];
+       fargs[i+1] = "";
+
+       cur_arg = 0;
+       ret = parse(fargs, &cur_arg, px, inst->fconf, err, private);
+       if (ret == 0 && *fargs[cur_arg]) {
+               /* some arguments were not consumed by the parsing function */
+               memprintf(err, "'filter-config %s' : unknown keyword '%s'",
+                         inst->class->name, fargs[cur_arg]);
+               ret = -1;
+       }
+       return ret;
+}
+
 /* Registers a new filter class, with the parsing function <parse> used to
  * finalize the filter instances of this class (may be NULL if the class does
  * not support the "filter-config" directive). The class is initialized and
@@ -1900,22 +1936,22 @@ int filter_register_class_full(struct filter_class *cls, const char *name,
 static void filter_init_classes(void)
 {
        /* TODO: the filter names must come from the filters (the filter id most probably) */
-       flt_init_class(&flt_trace_cls,         trace_filter_cls_name,         FLT_CLS_FL_MULTI, NULL);
-       flt_init_class(&flt_cache_store_cls,   cache_store_filter_cls_name,   FLT_CLS_FL_MULTI, NULL);
-       flt_init_class(&flt_http_comp_req_cls, http_comp_req_filter_cls_name, 0,                NULL);
-       flt_init_class(&flt_http_comp_res_cls, http_comp_res_filter_cls_name, 0,                NULL);
-       flt_init_class(&flt_decomp_req_cls,    decomp_req_filter_cls_name,    0,                NULL);
-       flt_init_class(&flt_decomp_res_cls,    decomp_res_filter_cls_name,    0,                NULL);
+       flt_init_class(&flt_trace_cls,         trace_filter_cls_name,         FLT_CLS_FL_MULTI, trace_flt_parse_instance);
+       flt_init_class(&flt_cache_store_cls,   cache_store_filter_cls_name,   FLT_CLS_FL_MULTI, cache_store_flt_parse_instance);
+       flt_init_class(&flt_http_comp_req_cls, http_comp_req_filter_cls_name, 0,                http_comp_req_flt_parse_instance);
+       flt_init_class(&flt_http_comp_res_cls, http_comp_res_filter_cls_name, 0,                http_comp_res_flt_parse_instance);
+       flt_init_class(&flt_decomp_req_cls,    decomp_req_filter_cls_name,    0,                decomp_req_flt_parse_instance);
+       flt_init_class(&flt_decomp_res_cls,    decomp_res_filter_cls_name,    0,                decomp_res_flt_parse_instance);
 #if defined(USE_SPOE)
-       flt_init_class(&flt_spoe_cls,          spoe_filter_cls_name,          FLT_CLS_FL_MULTI, NULL);
+       flt_init_class(&flt_spoe_cls,          spoe_filter_cls_name,          FLT_CLS_FL_MULTI, spoe_flt_parse_instance);
 #endif
 #if defined(USE_LUA)
-       flt_init_class(&flt_lua_cls,           hlua_filter_cls_name,          FLT_CLS_FL_MULTI, NULL);
+       flt_init_class(&flt_lua_cls,           hlua_filter_cls_name,          FLT_CLS_FL_MULTI, hlua_flt_parse_instance);
 #endif
-       flt_init_class(&flt_bwlim_in_cls,      bwlim_in_filter_cls_name,      FLT_CLS_FL_MULTI, NULL);
-       flt_init_class(&flt_bwlim_out_cls,     bwlim_out_filter_cls_name,     FLT_CLS_FL_MULTI, NULL);
+       flt_init_class(&flt_bwlim_in_cls,      bwlim_in_filter_cls_name,      FLT_CLS_FL_MULTI, bwlim_in_flt_parse_instance);
+       flt_init_class(&flt_bwlim_out_cls,     bwlim_out_filter_cls_name,     FLT_CLS_FL_MULTI, bwlim_out_flt_parse_instance);
 #if defined(USE_FCGI)
-       flt_init_class(&flt_fcgi_cls,          fcgi_filter_cls_name,          0,                NULL);
+       flt_init_class(&flt_fcgi_cls,          fcgi_filter_cls_name,          0,                fcgi_flt_parse_instance);
 #endif
 
        LIST_APPEND(&filter_classes, &flt_trace_cls.list);
index 6c61c43df8ba7fe7071f7d251a6bd8407e881961..d52b11f3f89714091e892512a43d6d9f5e786fe1 100644 (file)
@@ -967,6 +967,56 @@ static int parse_bwlim_out_flt(char **args, int *cur_arg, struct proxy *px, stru
        return parse_bwlim_flt(args, cur_arg, px, fconf, err, private);
 }
 
+static int bwlim_flt_parse_instance(const char *kw, char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       char *fargs[MAX_LINE_ARGS+1];
+       int i, ret, cur_arg;
+
+       fargs[0] = (char *)kw;
+       fargs[1] = (char *)inst->id;
+       for (i = 0; args[i] && *args[i]; i++)
+               fargs[i+2] = args[i];
+       fargs[i+2] = "";
+
+       cur_arg = 0;
+       ret = parse_bwlim_flt(fargs, &cur_arg, px, inst->fconf, err, NULL);
+       if (ret == 0 && *fargs[cur_arg]) {
+               memprintf(err, "'filter-config %s' : unknown keyword '%s'", inst->class->name, fargs[cur_arg]);
+               ret = -1;
+       }
+       return ret;
+}
+
+/* Parse the arguments of a "bwlim-in" filter instance. the bandwith limitation
+ * name is the instance id. It relies on bwlim_flt_parse_instance().
+ * Returns 0 on success, < 0 on error.
+ */
+int bwlim_in_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       if (flt_find_instance(px, &flt_bwlim_out_cls, inst->id)) {
+               memprintf(err, "bwlim filter '%s' already declared for proxy '%s'\n", inst->id, px->id);
+               return -1;
+       }
+
+       inst->fconf->id = bwlim_in_flt_id;
+       return bwlim_flt_parse_instance("bwlim-in", args, px, inst, err);
+}
+
+/* Parse the arguments of a "bwlim-out" filter instance. the bandwith limitation
+ * name is the instance id. It relies on bwlim_flt_parse_instance().
+ * Returns 0 on success, < 0 on error.
+ */
+int bwlim_out_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       if (flt_find_instance(px, &flt_bwlim_in_cls, inst->id)) {
+               memprintf(err, "bwlim filter '%s' already declared for proxy '%s'\n", inst->id, px->id);
+               return -1;
+       }
+
+       inst->fconf->id = bwlim_out_flt_id;
+       return bwlim_flt_parse_instance("bwlim-out", args, px, inst, err);
+}
+
 /* Declare the filter parser for "trace" keyword */
 static struct flt_kw_list flt_kws = { "BWLIM", { }, {
                { "bwlim-in",  parse_bwlim_in_flt, NULL },
index 72ee1c836082f59ba15b36eed4d0c54777abf5cf..0f0af55e2e774a58c755c0cb54d17642fdbe34bd 100644 (file)
@@ -1254,6 +1254,70 @@ parse_decomp_res_flt(char **args, int *cur_arg, struct proxy *px,
        return 0;
 }
 
+/* Parse the arguments of a "decomp-req" filter instance. No argument is
+ * expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int decomp_req_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct decomp *decomp;
+
+       if (!(px->cap & PR_CAP_FE)) {
+               memprintf(err, "'decomp-req' filter not allowed because %s '%s' has no frontend capability\n",
+                         proxy_type_str(px), px->id);
+               return -1;
+       }
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         decomp_req_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       decomp = proxy_get_decomp(px, 0);
+       if (decomp == NULL) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       decomp->flags |= DECOMP_FL_DIR_REQ;
+
+       inst->fconf->id   = decomp_req_flt_id;
+       inst->fconf->conf = &decomp->req;
+       inst->fconf->ops  = &decomp_req_ops;
+       return 0;
+}
+
+/* Parse the arguments of a "decomp-res" filter instance. No argument is
+ * expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int decomp_res_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct decomp *decomp;
+
+       if (!(px->cap & PR_CAP_BE)) {
+               memprintf(err, "'decomp-res' filter not allowed because %s '%s' has no backend capability\n",
+                         proxy_type_str(px), px->id);
+               return -1;
+       }
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         decomp_res_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       decomp = proxy_get_decomp(px, 0);
+       if (decomp == NULL) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       decomp->flags |= DECOMP_FL_DIR_RES;
+
+       inst->fconf->id   = decomp_res_flt_id;
+       inst->fconf->conf = &decomp->res;
+       inst->fconf->ops  = &decomp_res_ops;
+       return 0;
+}
+
 int
 check_implicit_decomp_flt(struct proxy *proxy)
 {
index e281932226f54ab69995d35cea20af9ec86b3884..299f7ba59f7ef90ee8b9f9bb852566feefd603f4 100644 (file)
@@ -1143,6 +1143,65 @@ parse_http_comp_res_flt(char **args, int *cur_arg, struct proxy *px,
        return 0;
 }
 
+/* Parse the arguments of a "http-comp-req" filter instance. No argument is
+ * expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int http_comp_req_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct comp *comp;
+
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         http_comp_req_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       comp = proxy_get_comp(px, 0);
+       if (comp == NULL) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       /* Implicit instances mirror options; they must not restore a direction
+        * removed by a later option or a local defaults override.
+        */
+       if (!(inst->flags & FLT_INST_F_IMPLICIT))
+               comp->flags |= COMP_FL_DIR_REQ;
+
+       inst->fconf->id   = http_comp_req_flt_id;
+       inst->fconf->conf = px->comp;
+       inst->fconf->ops  = &comp_req_ops;
+       return 0;
+}
+
+/* Parse the arguments of a "http-comp-res" filter instance. No argument is
+ * expected.
+ * Returns 0 on success, < 0 on error.
+ */
+int http_comp_res_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct comp *comp;
+
+       if (*args) {
+               memprintf(err, "'filter-config %s' : unexpected argument '%s'",
+                         http_comp_res_filter_cls_name, args[0]);
+               return -1;
+       }
+
+       comp = proxy_get_comp(px, 0);
+       if (comp == NULL) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       if (!(inst->flags & FLT_INST_F_IMPLICIT))
+               comp->flags |= COMP_FL_DIR_RES;
+
+       inst->fconf->id   = http_comp_res_flt_id;
+       inst->fconf->conf = px->comp;
+       inst->fconf->ops  = &comp_res_ops;
+       return 0;
+}
+
 int
 check_implicit_http_comp_flt(struct proxy *proxy)
 {
index aa5287d50e3cad64cfbbe8db3b32579151bdb2a5..9c475de7984290db31121f71280034122d6bb7ab 100644 (file)
@@ -2678,6 +2678,21 @@ static int parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
        return -1;
 }
 
+/* Parse the arguments of a "spoe" filter instance, relying on the legacy
+ * "filter" keyword parser.
+ * Returns 0 on success, < 0 on error.
+ */
+int spoe_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct proxy *old_curproxy = curproxy;
+       int ret;
+
+       curproxy = px;
+       ret = flt_parse_instance_legacy(px, inst, err, "spoe", parse_spoe_flt, NULL);
+       curproxy = old_curproxy;
+       return ret;
+}
+
 /* Send message of a SPOE group. This is the action_ptr callback of a rule
  * associated to a "send-spoe-group" action.
  *
index 3284f37d18da28619a2a10238c0a335b27a9ce8e..a29cc786ba68c6325da12dfa080638c68328e4e1 100644 (file)
@@ -691,6 +691,31 @@ parse_trace_flt(char **args, int *cur_arg, struct proxy *px,
        return -1;
 }
 
+/* Parse the arguments of a "trace" filter instance (see "filter-config"
+ * directive), relying on the legacy "filter" keyword parser.
+ * Returns 0 on success, < 0 on error.
+ */
+int trace_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       char *fargs[MAX_LINE_ARGS+1];
+       int i, ret, cur_arg;
+
+       fargs[0] = "trace";
+       fargs[1] = "name";
+       fargs[2] = (char *)inst->id;
+       for (i = 0; args[i] && *args[i]; i++)
+               fargs[i+3] = args[i];
+       fargs[i+3] = "";
+
+       cur_arg = 0;
+       ret = parse_trace_flt(fargs, &cur_arg, px, inst->fconf, err, NULL);
+       if (ret == 0 && *fargs[cur_arg]) {
+               memprintf(err, "'filter-config %s' : unknown keyword '%s'", inst->class->name, fargs[cur_arg]);
+               ret = -1;
+       }
+       return ret;
+}
+
 /* Declare the filter parser for "trace" keyword */
 static struct flt_kw_list flt_kws = { "TRACE", { }, {
                { "trace", parse_trace_flt, NULL },
index 3c54791b21ebd2bb7fa8a3b96ca1c3898697856a..66f794c820eca29f4e9807fe45136776eacd37c9 100644 (file)
@@ -12588,6 +12588,42 @@ static int hlua_filter_parse_fct(char **args, int *cur_arg, struct proxy *px,
        return -1;
 }
 
+/* Parse the arguments of a "lua" filter instance. The lua filter name is the
+ * instance id, as declared with core.register_filter() in a lua script (the id
+ * is mandatory for this class, several instances are allowed). The instance
+ * arguments are passed to the lua filter, relying on the legacy "filter"
+ * keyword parser.
+ * Returns 0 on success, < 0 on error.
+ */
+int hlua_flt_parse_instance(char **args, struct proxy *px, struct filter_instance *inst, char **err)
+{
+       struct flt_kw *kw;
+       char *kw_name = NULL;
+       int ret;
+
+       if (!inst->id) {
+               memprintf(err, "'%s' : missing filter instance id", hlua_filter_cls_name);
+               return -1;
+       }
+
+       kw_name = memprintf(&kw_name, "lua.%s", inst->id);
+       if (!kw_name) {
+               memprintf(err, "out of memory");
+               return -1;
+       }
+       kw = flt_find_kw(kw_name);
+       if (!kw || !kw->parse) {
+               memprintf(err, "unknown lua filter '%s'", inst->id);
+               free(kw_name);
+               return -1;
+       }
+
+       ret = flt_parse_instance_legacy(px, inst, err, kw_name, kw->parse, kw->private);
+
+       free(kw_name);
+       return ret;
+}
+
 __LJMP static int hlua_register_data_filter(lua_State *L)
 {
        struct filter *filter;