[MEDIUM] http: add support for conditional request header addition
Now the reqadd rules also support ACLs. All req* rules are converted
now.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index e3d38f1..e6cffa9 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3578,7 +3578,7 @@
See also : "option redispatch"
-reqadd <string>
+reqadd <string> [{if | unless} <cond>]
Add a header at the end of the HTTP request
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
@@ -3587,6 +3587,9 @@
must be escaped using a backslash ('\'). Please refer to section
6 about HTTP header manipulation for more information.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
A new line consisting in <string> followed by a line feed will be added after
the last header of an HTTP request.
@@ -3594,7 +3597,12 @@
and not to traffic generated by HAProxy, such as health-checks or error
responses.
- See also: "rspadd" and section 6 about HTTP header manipulation
+ Example : add "X-Proto: SSL" to requests coming via port 81
+ acl is-ssl dst_port 81
+ reqadd X-Proto:\ SSL if is-ssl
+
+ See also: "rspadd", section 6 about HTTP header manipulation, and section 7
+ about ACLs.
reqallow <search> [{if | unless} <cond>]
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4e724b2..c7f549d 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3738,7 +3738,24 @@
goto out;
}
+ if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ err_code |= warnif_cond_requires_resp(cond, file, linenum);
+ }
+ else if (*args[2]) {
+ Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
+ file, linenum, args[0], args[2]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
wl = calloc(1, sizeof(*wl));
+ wl->cond = cond;
wl->s = strdup(args[1]);
LIST_ADDQ(&curproxy->req_add, &wl->list);
warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
diff --git a/src/proto_http.c b/src/proto_http.c
index 9759635..1ee2307 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2851,6 +2851,15 @@
/* add request headers from the rule sets in the same order */
list_for_each_entry(wl, &px->req_add, list) {
+ if (wl->cond) {
+ int ret = acl_exec_cond(wl->cond, px, s, txn, ACL_DIR_REQ);
+ ret = acl_pass(ret);
+ if (((struct acl_cond *)wl->cond)->pol == ACL_COND_UNLESS)
+ ret = !ret;
+ if (!ret)
+ continue;
+ }
+
if (unlikely(http_header_add_tail(req, &txn->req, &txn->hdr_idx, wl->s) < 0))
goto return_bad_req;
}