MINOR: cfgparse/http_ext: move post-parsing http_ext steps to http_ext

This is a simple refactor to remove specific http_ext post-parsing treatment from
cfgparse.

Related work is now performed internally through check_http_ext_postconf()
function that is registered via REGISTER_POST_PROXY_CHECK() in http_ext.c.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index c207c6e..85cefb9 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -59,7 +59,6 @@
 #include <haproxy/global.h>
 #include <haproxy/http_ana.h>
 #include <haproxy/http_rules.h>
-#include <haproxy/http_ext.h>
 #include <haproxy/lb_chash.h>
 #include <haproxy/lb_fas.h>
 #include <haproxy/lb_fwlc.h>
@@ -3671,10 +3670,6 @@
 				curproxy->http_needed |= !!(curproxy->lbprm.expr->fetch->use & SMP_USE_HTTP_ANY);
 		}
 
-		/* option "forwarded" may need to compile its expressions */
-		if ((curproxy->mode == PR_MODE_HTTP) && curproxy->http_ext && curproxy->http_ext->fwd)
-			cfgerr += proxy_http_compile_7239(curproxy);
-
 		/* only now we can check if some args remain unresolved.
 		 * This must be done after the users and groups resolution.
 		 */
@@ -3969,28 +3964,6 @@
 				err_code |= ERR_WARN;
 			}
 
-			if (curproxy->http_ext) {
-				/* consistency checks for http_ext */
-				if (curproxy->http_ext->fwd) {
-					ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
-						   "forwarded", proxy_type_str(curproxy), curproxy->id);
-					err_code |= ERR_WARN;
-					http_ext_7239_clean(curproxy);
-				}
-				if (curproxy->http_ext->xff) {
-					ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
-						   "forwardfor", proxy_type_str(curproxy), curproxy->id);
-					err_code |= ERR_WARN;
-					http_ext_xff_clean(curproxy);
-				}
-				if (curproxy->http_ext->xot) {
-					ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
-						   "originalto", proxy_type_str(curproxy), curproxy->id);
-					err_code |= ERR_WARN;
-					http_ext_xot_clean(curproxy);
-				}
-			}
-
 			for (optnum = 0; cfg_opts[optnum].name; optnum++) {
 				if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
 				    (curproxy->cap & cfg_opts[optnum].cap) &&
@@ -4223,8 +4196,6 @@
 				rules->flags = 0;
 			}
 		}
-		/* http_ext post init early cleanup */
-		http_ext_softclean(curproxy);
 	}
 
 	/*
diff --git a/src/http_ext.c b/src/http_ext.c
index 0dcafc5..d3b5764 100644
--- a/src/http_ext.c
+++ b/src/http_ext.c
@@ -1067,13 +1067,14 @@
 	return err_code;
 }
 
-/* returns 0 for success and positive value
- * (equals to number of errors) in case of error
+/* rfc7239 forwarded option needs a postparsing step
+ * to convert parsing hints into runtime usable sample expressions
+ * Returns a composition of ERR_NONE, ERR_FATAL, ERR_ALERT, ERR_WARN
  */
 int proxy_http_compile_7239(struct proxy *curproxy)
 {
 	struct http_ext_7239 *fwd;
-	int cfgerr = 0;
+	int err = ERR_NONE;
 	int loop;
 
 	if (!(curproxy->cap & PR_CAP_BE)) {
@@ -1096,7 +1097,7 @@
 		char **expr_str = NULL;
 		struct sample_expr **expr = NULL;
 		struct sample_expr *cur_expr;
-		char *err = NULL;
+		char *err_str = NULL;
 		int smp = 0;
 		int idx = 0;
 
@@ -1144,7 +1145,7 @@
 				 proxy_type_str(curproxy), curproxy->id,
 				 fwd->c_file, fwd->c_line,
 				 "memory error");
-			cfgerr++;
+			err |= ERR_ALERT | ERR_FATAL;
 			continue;
 		}
 
@@ -1152,15 +1153,15 @@
 			sample_parse_expr((char*[]){*expr_str, NULL}, &idx,
 					  fwd->c_file,
 					  fwd->c_line,
-					  &err, &curproxy->conf.args, NULL);
+					  &err_str, &curproxy->conf.args, NULL);
 
 		if (!cur_expr) {
 			ha_alert("%s '%s' [%s:%d]: failed to parse 'option forwarded' expression '%s' in : %s.\n",
 				 proxy_type_str(curproxy), curproxy->id,
 				 fwd->c_file, fwd->c_line,
-				 *expr_str, err);
-			ha_free(&err);
-			cfgerr++;
+				 *expr_str, err_str);
+			ha_free(&err_str);
+			err |= ERR_ALERT | ERR_FATAL;
 		}
 		else if (!(cur_expr->fetch->val & SMP_VAL_BE_HRQ_HDR)) {
 			/* fetch not available in this context: sample expr is resolved
@@ -1174,6 +1175,7 @@
 				   proxy_type_str(curproxy), curproxy->id,
 				   fwd->c_file, fwd->c_line,
 				   *expr_str, sample_ckp_names(cur_expr->fetch->use));
+			err |= ERR_WARN;
 		}
 		/* post parsing individual expr cleanup */
 		ha_free(expr_str);
@@ -1191,7 +1193,7 @@
 	fwd->c_mode = 1; /* parsing completed */
 
  out:
-	return cfgerr;
+	return err;
 }
 
 /* x-forwarded-for */
@@ -1665,6 +1667,49 @@
 	}
 }
 
+/* Perform some consitency checks on px.http_ext after parsing
+ * is completed.
+ * We make sure to perform a softclean in case some options were
+ * to be disabled in this check. This way we can release some memory.
+ * Returns a composition of ERR_NONE, ERR_ALERT, ERR_FATAL, ERR_WARN
+ */
+static int check_http_ext_postconf(struct proxy *px) {
+	int err = ERR_NONE;
+
+	if (px->http_ext) {
+		/* consistency check for http_ext */
+		if (px->mode != PR_MODE_HTTP && !(px->options & PR_O_HTTP_UPG)) {
+			/* http is disabled on px, yet it is required by http_ext */
+			if (px->http_ext->fwd) {
+				ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
+					   "forwarded", proxy_type_str(px), px->id);
+				err |= ERR_WARN;
+				http_ext_7239_clean(px);
+			}
+			if (px->http_ext->xff) {
+				ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
+					   "forwardfor", proxy_type_str(px), px->id);
+				err |= ERR_WARN;
+				http_ext_xff_clean(px);
+			}
+			if (px->http_ext->xot) {
+				ha_warning("'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
+					   "originalto", proxy_type_str(px), px->id);
+				err |= ERR_WARN;
+				http_ext_xot_clean(px);
+			}
+		} else if (px->http_ext->fwd) {
+			/* option "forwarded" may need to compile its expressions */
+			err |= proxy_http_compile_7239(px);
+		}
+		/* http_ext post init early cleanup */
+		http_ext_softclean(px);
+
+	}
+	return err;
+}
+
+REGISTER_POST_PROXY_CHECK(check_http_ext_postconf);
 /*
  * =========== CONV ===========
  * related converters