From d250b381dca2a53e4ec8c17c4fca28ecef4c4c83 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 18 Mar 2026 16:21:37 +0100 Subject: [PATCH] MINOR: http_htx: split check/init of http_errors Function proxy_check_errors() is used when configuration parsing is over. This patch splits it in two newly named ones. The first function is named proxy_check_http_errors(). It is responsible to check for the validity of any "errorfiles" directive which could reference non-existent http-errors section or code not defined in such section. This function is now called via proxy_finalize(). The second function is named proxy_finalize_http_errors(). It converts each conf_errors type used during parsing in a proper http_reply type for runtime usage. This function is still called via post-proxy-check, after proxy_finalize(). This patch does not bring any functional change. However, it will become necessary to ensure http-errors can be used as expected with dynamic backends. --- include/haproxy/http_htx.h | 1 + src/http_htx.c | 88 +++++++++++++++++++++++++++----------- src/proxy.c | 2 + 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/include/haproxy/http_htx.h b/include/haproxy/http_htx.h index 3d01a061f..784596dd1 100644 --- a/include/haproxy/http_htx.h +++ b/include/haproxy/http_htx.h @@ -78,6 +78,7 @@ struct buffer *http_load_errorfile(const char *file, char **errmsg); struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg); struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg); struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg); +int proxy_check_http_errors(struct proxy *px); int proxy_dup_default_conf_errors(struct proxy *curpx, const struct proxy *defpx, char **errmsg); void proxy_release_conf_errors(struct proxy *px); diff --git a/src/http_htx.c b/src/http_htx.c index 296cde2ce..61e5683e6 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -2260,12 +2260,17 @@ static int proxy_parse_http_error(char **args, int section, struct proxy *curpx, } -/* Check "errorfiles" proxy keyword */ -static int proxy_check_errors(struct proxy *px) +/* Converts initialized during config parsing for proxy. + * Each one of them is transfromed in a http_reply type, stored in proxy + * replies array member. The original becomes unneeded and is + * thus removed and freed. + */ +static int proxy_finalize_http_errors(struct proxy *px) { struct conf_errors *conf_err, *conf_err_back; struct http_errors *http_errs; - int rc, err = ERR_NONE; + int section_found; + int rc; list_for_each_entry_safe(conf_err, conf_err_back, &px->conf.errors, list) { switch (conf_err->directive) { @@ -2279,41 +2284,31 @@ static int proxy_check_errors(struct proxy *px) break; case HTTP_ERR_DIRECTIVE_SECTION: + section_found = 0; list_for_each_entry(http_errs, &http_errors_list, list) { - if (strcmp(http_errs->id, conf_err->type.section.name) == 0) + if (strcmp(http_errs->id, conf_err->type.section.name) == 0) { + section_found = 1; break; - } - - /* unknown http-errors section */ - if (&http_errs->list == &http_errors_list) { - ha_alert("proxy '%s': unknown http-errors section '%s' (at %s:%d).\n", - px->id, conf_err->type.section.name, conf_err->file, conf_err->line); - err |= ERR_ALERT | ERR_FATAL; - free(conf_err->type.section.name); - goto next; + } } free(conf_err->type.section.name); - for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { - if (conf_err->type.section.status[rc] > HTTP_ERR_IMPORT_NO) { + if (section_found) { + for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { + if (conf_err->type.section.status[rc] == HTTP_ERR_IMPORT_NO) + continue; if (http_errs->replies[rc]) px->replies[rc] = http_errs->replies[rc]; - else if (conf_err->type.section.status[rc] == HTTP_ERR_IMPORT_EXPLICIT) - ha_warning("config: proxy '%s' : status '%d' not declared in" - " http-errors section '%s' (at %s:%d).\n", - px->id, http_err_codes[rc], http_errs->id, - conf_err->file, conf_err->line); } } } - next: + LIST_DELETE(&conf_err->list); free(conf_err->file); free(conf_err); } - out: - return err; + return ERR_NONE; } static int post_check_errors() @@ -2343,6 +2338,51 @@ static int post_check_errors() return err_code; } +/* Checks the validity of conf_errors stored in proxy after the + * configuration is completely parsed. + * + * Returns ERR_NONE on success and a combination of ERR_CODE on failure. + */ +int proxy_check_http_errors(struct proxy *px) +{ + struct http_errors *http_errs; + struct conf_errors *conf_err; + int section_found; + int rc, err = ERR_NONE; + + list_for_each_entry(conf_err, &px->conf.errors, list) { + if (conf_err->directive == HTTP_ERR_DIRECTIVE_SECTION) { + section_found = 0; + list_for_each_entry(http_errs, &http_errors_list, list) { + if (strcmp(http_errs->id, conf_err->type.section.name) == 0) { + section_found = 1; + break; + } + } + + if (!section_found) { + ha_alert("proxy '%s': unknown http-errors section '%s' (at %s:%d).\n", + px->id, conf_err->type.section.name, conf_err->file, conf_err->line); + err |= ERR_ALERT | ERR_FATAL; + continue; + } + + for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { + if (conf_err->type.section.status[rc] == HTTP_ERR_IMPORT_EXPLICIT && + !http_errs->replies[rc]) { + ha_warning("config: proxy '%s' : status '%d' not declared in" + " http-errors section '%s' (at %s:%d).\n", + px->id, http_err_codes[rc], http_errs->id, + conf_err->file, conf_err->line); + err |= ERR_WARN; + } + } + } + } + + return err; +} + int proxy_dup_default_conf_errors(struct proxy *curpx, const struct proxy *defpx, char **errmsg) { struct conf_errors *conf_err, *new_conf_err = NULL; @@ -2508,7 +2548,7 @@ static struct cfg_kw_list cfg_kws = {ILH, { }}; INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); -REGISTER_POST_PROXY_CHECK(proxy_check_errors); +REGISTER_POST_PROXY_CHECK(proxy_finalize_http_errors); REGISTER_POST_CHECK(post_check_errors); REGISTER_CONFIG_SECTION("http-errors", cfg_parse_http_errors, NULL); diff --git a/src/proxy.c b/src/proxy.c index 1b6c8e4db..a72370aa4 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -2672,6 +2672,8 @@ int proxy_finalize(struct proxy *px, int *err_code) *err_code |= ERR_WARN; } + *err_code |= proxy_check_http_errors(px); + if (px->mode != PR_MODE_HTTP && !(px->options & PR_O_HTTP_UPG)) { int optnum;