From: Austin Kauffman Date: Sat, 15 Aug 2026 01:34:39 +0000 (-0700) Subject: BUG/MINOR: fcgi-app: allow explicit filter declaration with non-cache/non-compression... X-Git-Tag: v3.5-dev6~70 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=fa196bc1de290721d8cba67b56d83947e91739a5;p=haproxy.git BUG/MINOR: fcgi-app: allow explicit filter declaration with non-cache/non-compression filters fcgi_flt_check() in src/fcgi-app.c unconditionally rejects any filter that isn't compression, cache, or fcgi-app from coexisting with use-fcgi-app in the same backend section, regardless of whether an explicit `filter fcgi-app ` declaration is present. This contradicts the documentation (section 9.5 of configuration.txt), which states that an explicit `filter fcgi-app` declaration should allow other filters to coexist. The cache filter's equivalent check (cache_store_check in src/cache.c) correctly uses a CACHE_FLT_F_IMPLICIT_DECL flag to only reject implicit declarations when other filters are present. The fcgi-app check was missing this flag, which appears to be an oversight. This patch adds a FCGI_FLT_F_IMPLICIT_DECL flag to fcgi_flt_conf, mirroring the cache filter's pattern: - The flag is set when use-fcgi-app creates an implicit filter (proxy_parse_use_fcgi_app). - The flag is cleared when filter fcgi-app explicitly declares the filter (parse_fcgi_flt), whether reusing an existing implicit config or creating a new one. - fcgi_flt_check only errors when the flag is set (i.e., the filter is implicit), matching cache_store_check's behavior. This allows Lua-based filters (lua.resp_transform, lua.compress for brotli/zstd) and other third-party filters to coexist with FastCGI backends when an explicit `filter fcgi-app` declaration is present, as documented. This should be backported to all versions that have the fcgi-app filter. --- diff --git a/include/haproxy/fcgi-app-t.h b/include/haproxy/fcgi-app-t.h index 56b95091d..aaf218fe3 100644 --- a/include/haproxy/fcgi-app-t.h +++ b/include/haproxy/fcgi-app-t.h @@ -103,6 +103,7 @@ struct fcgi_app { struct fcgi_flt_conf { char *name; /* fcgi-app name used during config parsing */ struct fcgi_app *app; /* configuration of the fcgi application */ + unsigned int flags; /* FCGI_FLT_F_* */ struct list param_rules; /* list of set/unset rules */ struct list hdr_rules; /* list of pass/add rules */ diff --git a/src/fcgi-app.c b/src/fcgi-app.c index efcfd98d8..217594cd0 100644 --- a/src/fcgi-app.c +++ b/src/fcgi-app.c @@ -35,6 +35,11 @@ static struct fcgi_app *fcgi_apps = NULL; struct flt_ops fcgi_flt_ops; const char *fcgi_flt_id = "FCGI filter"; +/* The fcgi-app filter was implicitly declared (ie without the filter keyword, + * via use-fcgi-app). + */ +#define FCGI_FLT_F_IMPLICIT_DECL 0x00000001 + DECLARE_STATIC_TYPED_POOL(pool_head_fcgi_flt_ctx, "fcgi_flt_ctx", struct fcgi_flt_ctx); DECLARE_STATIC_TYPED_POOL(pool_head_fcgi_param_rule, "fcgi_param_rule", struct fcgi_param_rule); DECLARE_STATIC_TYPED_POOL(pool_head_fcgi_hdr_rule, "fcgi_hdr_rule", struct fcgi_hdr_rule); @@ -229,9 +234,9 @@ static int fcgi_flt_check(struct proxy *px, struct flt_conf *fconf) px->id); goto err; } - else if (f->id != fconf->id) { + else if ((f->id != fconf->id) && (fcgi_conf->flags & FCGI_FLT_F_IMPLICIT_DECL)) { /* Implicit declaration is only allowed with the - * compression and cache. For other filters, an implicit + * compression and cache. For other filters, an explicit * declaration is required. */ ha_alert("config: proxy '%s': require an explicit filter declaration " "to use the fcgi-app '%s'.\n", px->id, fcgi_conf->name); @@ -542,6 +547,8 @@ parse_fcgi_flt(char **args, int *cur_arg, struct proxy *px, LIST_INIT(&fcgi_conf->hdr_rules); } + /* Explicit declaration: clear the implicit flag. */ + fcgi_conf->flags &= ~FCGI_FLT_F_IMPLICIT_DECL; fconf->id = fcgi_flt_id; fconf->conf = fcgi_conf; fconf->ops = &fcgi_flt_ops; @@ -596,6 +603,7 @@ static int proxy_parse_use_fcgi_app(char **args, int section, struct proxy *curp goto err; LIST_INIT(&fcgi_conf->param_rules); LIST_INIT(&fcgi_conf->hdr_rules); + fcgi_conf->flags = FCGI_FLT_F_IMPLICIT_DECL; /* implicit declaration */ /* Register the filter */ fconf = calloc(1, sizeof(*fconf));