MINOR: http_act: Add -m flag for del-header name matching method
This patch adds -m flag which allows to specify header name
matching method when deleting headers from http request/response.
Currently beg, end, sub, str and reg are supported.
This is related to GitHub issue #909
diff --git a/src/http_act.c b/src/http_act.c
index 27db478..13a5c37 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -1438,20 +1438,67 @@
return ACT_RET_PRS_OK;
}
-/* Parse a "del-header" action. It takes an header name as argument. It returns
- * ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
+/* This function executes a del-header action with selected matching mode for
+ * header name. It finds the matching method to be performed in <.action>, previously
+ * filled by function parse_http_del_header(). On success, it returns ACT_RET_CONT.
+ * Otherwise ACT_RET_ERR is returned.
+ */
+static enum act_return http_action_del_header(struct act_rule *rule, struct proxy *px,
+ struct session *sess, struct stream *s, int flags)
+{
+ struct http_hdr_ctx ctx;
+ struct http_msg *msg = ((rule->from == ACT_F_HTTP_REQ) ? &s->txn->req : &s->txn->rsp);
+ struct htx *htx = htxbuf(&msg->chn->buf);
+ enum act_return ret = ACT_RET_CONT;
+
+ /* remove all occurrences of the header */
+ ctx.blk = NULL;
+ switch (rule->action) {
+ case PAT_MATCH_STR:
+ while (http_find_header(htx, rule->arg.http.str, &ctx, 1))
+ http_remove_header(htx, &ctx);
+ break;
+ case PAT_MATCH_BEG:
+ while (http_find_pfx_header(htx, rule->arg.http.str, &ctx, 1))
+ http_remove_header(htx, &ctx);
+ break;
+ case PAT_MATCH_END:
+ while (http_find_sfx_header(htx, rule->arg.http.str, &ctx, 1))
+ http_remove_header(htx, &ctx);
+ break;
+ case PAT_MATCH_SUB:
+ while (http_find_sub_header(htx, rule->arg.http.str, &ctx, 1))
+ http_remove_header(htx, &ctx);
+ break;
+ case PAT_MATCH_REG:
+ while (http_match_header(htx, rule->arg.http.re, &ctx, 1))
+ http_remove_header(htx, &ctx);
+ break;
+ default:
+ return ACT_RET_ERR;
+ }
+ return ret;
+}
+
+/* Parse a "del-header" action. It takes string as a required argument,
+ * optional flag (currently only -m) and optional matching method of input string
+ * with header name to be deleted. Default matching method is exact match (-m str).
+ * It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
*/
static enum act_parse_ret parse_http_del_header(const char **args, int *orig_arg, struct proxy *px,
struct act_rule *rule, char **err)
{
int cur_arg;
+ int pat_idx;
- rule->action = ACT_HTTP_DEL_HDR;
+ /* set exact matching (-m str) as default */
+ rule->action = PAT_MATCH_STR;
+ rule->action_ptr = http_action_del_header;
rule->release_ptr = release_http_action;
cur_arg = *orig_arg;
if (!*args[cur_arg]) {
- memprintf(err, "expects exactly 1 arguments");
+ memprintf(err, "expects at least 1 argument");
return ACT_RET_PRS_ERR;
}
@@ -1459,7 +1506,32 @@
rule->arg.http.str.len = strlen(rule->arg.http.str.ptr);
px->conf.args.ctx = (rule->from == ACT_F_HTTP_REQ ? ARGC_HRQ : ARGC_HRS);
+ if (strcmp(args[cur_arg+1], "-m") == 0) {
+ cur_arg++;
+ if (!*args[cur_arg+1]) {
+ memprintf(err, "-m flag expects exactly 1 argument");
+ return ACT_RET_PRS_ERR;
+ }
+
+ cur_arg++;
+ pat_idx = pat_find_match_name(args[cur_arg]);
+ switch (pat_idx) {
+ case PAT_MATCH_REG:
+ if (!(rule->arg.http.re = regex_comp(rule->arg.http.str.ptr, 1, 1, err)))
+ return ACT_RET_PRS_ERR;
+ /* fall through */
+ case PAT_MATCH_STR:
+ case PAT_MATCH_BEG:
+ case PAT_MATCH_END:
+ case PAT_MATCH_SUB:
+ rule->action = pat_idx;
+ break;
+ default:
+ memprintf(err, "-m with unsupported matching method '%s'", args[cur_arg]);
+ return ACT_RET_PRS_ERR;
+ }
+ }
+
- LIST_INIT(&rule->arg.http.fmt);
*orig_arg = cur_arg + 1;
return ACT_RET_PRS_OK;
}
diff --git a/src/http_ana.c b/src/http_ana.c
index 7a9cd0b..d89b7d5 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -2838,14 +2838,10 @@
{
struct session *sess = strm_sess(s);
struct http_txn *txn = s->txn;
- struct htx *htx;
struct act_rule *rule;
- struct http_hdr_ctx ctx;
enum rule_result rule_ret = HTTP_RULE_RES_CONT;
int act_opts = 0;
- htx = htxbuf(&s->req.buf);
-
/* If "the current_rule_list" match the executed rule list, we are in
* resume condition. If a resume is needed it is always in the action
* and never in the ACL or converters. In this case, we initialise the
@@ -2958,13 +2954,6 @@
s->logs.level = rule->arg.http.i;
break;
- case ACT_HTTP_DEL_HDR:
- /* remove all occurrences of the header */
- ctx.blk = NULL;
- while (http_find_header(htx, rule->arg.http.str, &ctx, 1))
- http_remove_header(htx, &ctx);
- break;
-
/* other flags exists, but normally, they never be matched. */
default:
break;
@@ -2994,14 +2983,10 @@
{
struct session *sess = strm_sess(s);
struct http_txn *txn = s->txn;
- struct htx *htx;
struct act_rule *rule;
- struct http_hdr_ctx ctx;
enum rule_result rule_ret = HTTP_RULE_RES_CONT;
int act_opts = 0;
- htx = htxbuf(&s->res.buf);
-
/* If "the current_rule_list" match the executed rule list, we are in
* resume condition. If a resume is needed it is always in the action
* and never in the ACL or converters. In this case, we initialise the
@@ -3102,13 +3087,6 @@
s->logs.level = rule->arg.http.i;
break;
- case ACT_HTTP_DEL_HDR:
- /* remove all occurrences of the header */
- ctx.blk = NULL;
- while (http_find_header(htx, rule->arg.http.str, &ctx, 1))
- http_remove_header(htx, &ctx);
- break;
-
case ACT_HTTP_REDIR:
rule_ret = HTTP_RULE_RES_ABRT;
if (!http_apply_redirect_rule(rule->arg.redir, s, txn))