]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http_htx: split check/init of http_errors
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 18 Mar 2026 15:21:37 +0000 (16:21 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 23 Mar 2026 09:51:33 +0000 (10:51 +0100)
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
src/http_htx.c
src/proxy.c

index 3d01a061f1c8e8646965687c89902b0f3a4eedc2..784596dd1da41003b309400f48e2586e5702d6e0 100644 (file)
@@ -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);
 
index 296cde2ce5524a976c775a1bc90205025f658d37..61e5683e60586cada187b0b36fdd95f84a191aa2 100644 (file)
@@ -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 <conf_errors> initialized during config parsing for <px> proxy.
+ * Each one of them is transfromed in a http_reply type, stored in proxy
+ * replies array member. The original <conf_errors> 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 <px> 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);
index 1b6c8e4dbba77a442829cb5988251661ffc3fea4..a72370aa438068629f20693fb7963433b1fcc8ee 100644 (file)
@@ -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;