From: Willy Tarreau Date: Sun, 31 Jan 2010 13:30:44 +0000 (+0100) Subject: [MEDIUM] http: add support for conditional request header addition X-Git-Tag: v1.4-rc1~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8abd4cd526cabe5d7c84d80c27088e715142742e;p=thirdparty%2Fhaproxy.git [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 e3d38f13bf..e6cffa9773 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -3578,7 +3578,7 @@ redispatch (deprecated) See also : "option redispatch" -reqadd +reqadd [{if | unless} ] 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 @@ reqadd must be escaped using a backslash ('\'). Please refer to section 6 about HTTP header manipulation for more information. + 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 followed by a line feed will be added after the last header of an HTTP request. @@ -3594,7 +3597,12 @@ reqadd 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 [{if | unless} ] diff --git a/src/cfgparse.c b/src/cfgparse.c index 4e724b2e05..c7f549d3eb 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3738,7 +3738,24 @@ stats_error_parsing: 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 975963504b..1ee230712c 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2851,6 +2851,15 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s /* 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; }