From: Aurelien DARRAGON Date: Thu, 20 Aug 2026 17:49:58 +0000 (+0200) Subject: MEDIUM: filters: implicitly enable "decomp-req" and "decomp-res" when decompression... X-Git-Tag: v3.5-dev6~46 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=6715b5c85d539d4851afc6f99adf99c8e72577f2;p=haproxy.git MEDIUM: filters: implicitly enable "decomp-req" and "decomp-res" when decompression options are used If the "decomp-req" and/or "decomp-res" filters are not declared explicitly but decompression options are set for them, then we detect that the options relevant for one or the other were set and we enable the filter automatically. This eases the configuration for users who forget to declare the relevant decompression filters, as we already do for compression ones. However, when multiple filters are involved on a single proxy, it is highly recommended to declare filters explicitly in order to avoid surprises and this way it is easier to control in which order they are executed. See also "filter-sequence" to help control executing order. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 94e9ae506..ae5f44ccc 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -7404,11 +7404,11 @@ declare capture [ request | response ] len decompression algo-req ... decompression algo-res ... - - Configures the decompression algorithms supported by the proxy. - It does not enable decompression filters ("decomp-req" and "decomp-res") - automatically, relevant decompression filters must be enabled explicitly - on the proxy, else decompression options will simply be ignored. + Configures the decompression algorithms supported by the proxy. It will + implicitly enable decompression filter ("decomp-req" or "decomp-res" whether + the decompression option targets request, response) automatically. However to + prevent misconfiguration, it is recommended to explicitly declare filters + when multiple filters are involved on the proxy. See also "filter-sequence". May be used in the following contexts: http, tcp diff --git a/include/haproxy/flt_decomp.h b/include/haproxy/flt_decomp.h new file mode 100644 index 000000000..800781980 --- /dev/null +++ b/include/haproxy/flt_decomp.h @@ -0,0 +1,28 @@ +/* + * include/haproxy/flt_decomp.h + * This file defines function prototypes for the decompression filters. + * + * Copyright 2026 HAProxy Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, version 2.1 + * exclusively. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _HAPROXY_FLT_DECOMP_H +#define _HAPROXY_FLT_DECOMP_H + +#include + +int check_implicit_decomp_flt(struct proxy *proxy); + +#endif // _HAPROXY_FLT_DECOMP_H diff --git a/src/filters.c b/src/filters.c index bcb311c70..f118fd0cd 100644 --- a/src/filters.c +++ b/src/filters.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -515,6 +516,7 @@ flt_check(struct proxy *proxy) struct flt_conf *fconf; int err = 0; + err += check_implicit_decomp_flt(proxy); err += check_implicit_http_comp_flt(proxy); list_for_each_entry(fconf, &proxy->filter_configs, list) { if (fconf->ops->check) diff --git a/src/flt_decomp.c b/src/flt_decomp.c index 11d02557b..76e3f6bfb 100644 --- a/src/flt_decomp.c +++ b/src/flt_decomp.c @@ -1279,6 +1279,89 @@ parse_decomp_res_flt(char **args, int *cur_arg, struct proxy *px, return 0; } +int +check_implicit_decomp_flt(struct proxy *proxy) +{ + struct flt_conf *fconf; + struct flt_conf *fconf_req = NULL; + struct flt_conf *fconf_res = NULL; + int explicit = 0; + int err = 0; + + if (proxy->decomp == NULL) + goto end; + + if (!LIST_ISEMPTY(&proxy->filter_configs)) { + list_for_each_entry(fconf, &proxy->filter_configs, list) { + if ((proxy->cap & PR_CAP_FE) && fconf->id == decomp_req_flt_id) + fconf_req = fconf; + else if ((proxy->cap & PR_CAP_BE) && fconf->id == decomp_res_flt_id) + fconf_res = fconf; + else if (fconf->id == cache_store_flt_id) { + if (((proxy->cap & PR_CAP_FE) && !fconf_req) || ((proxy->cap & PR_CAP_BE) && !fconf_res)) { + ha_alert("config: %s '%s': cache filter declared before a decompression filter is invalid.\n", + proxy_type_str(proxy), proxy->id); + err++; + goto end; + } + } + else if (fconf->id == http_comp_req_flt_id || fconf->id == http_comp_res_flt_id) + continue; +#if defined(USE_FCGI) + else if (fconf->id == fcgi_flt_id) + continue; +#endif + else + explicit = 1; + } + } + + if ((proxy->cap & PR_CAP_FE) && proxy->decomp->req.algos && !fconf_req) { + if (explicit) { + ha_alert("config: %s '%s': require an explicit 'filter decomp-req' declaration to use " + "decompression.\n", proxy_type_str(proxy), proxy->id); + err++; + goto end; + } + /* Implicit declaration of the decomp-req filter should be at + * the beginning of the filter list. + */ + fconf_req = calloc(1, sizeof(*fconf)); + if (!fconf_req) + goto out_of_memory; + fconf_req->id = decomp_req_flt_id; + fconf_req->conf = &proxy->decomp->req; + fconf_req->ops = &decomp_req_ops; + LIST_INSERT(&proxy->filter_configs, &fconf_req->list); + } + if ((proxy->cap & PR_CAP_BE) && proxy->decomp->res.algos && !fconf_res) { + if (explicit) { + ha_alert("config: %s '%s': require an explicit 'filter decomp-res' declaration to use " + "decompression.\n", proxy_type_str(proxy), proxy->id); + err++; + goto end; + } + /* Implicit declaration of the decomp-res filter should be at + * the beginning of the filter list. + */ + fconf_res = calloc(1, sizeof(*fconf)); + if (!fconf_res) + goto out_of_memory; + fconf_res->id = decomp_res_flt_id; + fconf_res->conf = &proxy->decomp->res; + fconf_res->ops = &decomp_res_ops; + LIST_INSERT(&proxy->filter_configs, &fconf_res->list); + } + end: + return err; + + out_of_memory: + ha_alert("config: %s '%s': out of memory\n", proxy_type_str(proxy), proxy->id); + err++; + goto end; +} + + /* Declare the config parser for "decompression" keyword */ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_LISTEN, "decompression", parse_decompression_options }, diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 42d934816..ed0b83f24 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -1161,6 +1161,8 @@ check_implicit_http_comp_flt(struct proxy *proxy) goto end; } } + else if (fconf->id == decomp_req_flt_id || fconf->id == decomp_res_flt_id) + continue; #if defined(USE_FCGI) else if (fconf->id == fcgi_flt_id) continue;