diff --git a/doc/configuration.txt b/doc/configuration.txt index 971c26e8f..bb7d56794 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -12218,6 +12218,12 @@ query : string using the "found" matching method. This fetch is the completemnt of "path" which stops before the question mark. +req.hdr_names([]) : string + This builds a string made from the concatenation of all header names as they + appear in the request when the rule is evaluated. The default delimiter is + the comma (',') but it may be overridden as an optional argument . In + this case, only the first character of is considered. + req.ver : string req_ver : string (deprecated) Returns the version string from the HTTP request, for example "1.1". This can @@ -12314,6 +12320,12 @@ shdr_ip([[,]]) : ip (deprecated) Negative values indicate positions relative to the last one, with -1 being the last one. This can be useful to learn some data into a stick table. +res.hdr_names([]) : string + This builds a string made from the concatenation of all header names as they + appear in the response when the rule is evaluated. The default delimiter is + the comma (',') but it may be overridden as an optional argument . In + this case, only the first character of is considered. + res.hdr_val([[,]]) : integer shdr_val([[,]]) : integer (deprecated) This extracts the last occurrence of header in an HTTP response, and diff --git a/src/proto_http.c b/src/proto_http.c index 0a6ef9f7d..4484bcf48 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -10232,6 +10232,39 @@ smp_fetch_fhdr_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int return 1; } +static int +smp_fetch_hdr_names(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + const struct arg *args, struct sample *smp, const char *kw) +{ + struct http_txn *txn = l7; + struct hdr_idx *idx = &txn->hdr_idx; + struct hdr_ctx ctx; + const struct http_msg *msg = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) ? &txn->req : &txn->rsp; + struct chunk *temp; + char del = ','; + + if (args && args->type == ARGT_STR) + del = *args[0].data.str.str; + + CHECK_HTTP_MESSAGE_FIRST(); + + temp = get_trash_chunk(); + + ctx.idx = 0; + while (http_find_next_header(msg->chn->buf->p, idx, &ctx)) { + if (temp->len) + temp->str[temp->len++] = del; + memcpy(temp->str + temp->len, ctx.line, ctx.del); + temp->len += ctx.del; + } + + smp->type = SMP_T_STR; + smp->data.str.str = temp->str; + smp->data.str.len = temp->len; + smp->flags = SMP_F_VOL_HDR; + return 1; +} + /* Fetch an HTTP header. A pointer to the beginning of the value is returned. * Accepts an optional argument of type string containing the header field name, * and an optional argument of type signed or unsigned integer to request an @@ -11884,6 +11917,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "req.hdr", smp_fetch_hdr, ARG2(0,STR,SINT), val_hdr, SMP_T_STR, SMP_USE_HRQHV }, { "req.hdr_cnt", smp_fetch_hdr_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_HRQHV }, { "req.hdr_ip", smp_fetch_hdr_ip, ARG2(0,STR,SINT), val_hdr, SMP_T_IPV4, SMP_USE_HRQHV }, + { "req.hdr_names", smp_fetch_hdr_names, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRQHV }, { "req.hdr_val", smp_fetch_hdr_val, ARG2(0,STR,SINT), val_hdr, SMP_T_UINT, SMP_USE_HRQHV }, /* explicit req.{cook,hdr} are used to force the fetch direction to be response-only */ @@ -11896,6 +11930,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "res.hdr", smp_fetch_hdr, ARG2(0,STR,SINT), val_hdr, SMP_T_STR, SMP_USE_HRSHV }, { "res.hdr_cnt", smp_fetch_hdr_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_HRSHV }, { "res.hdr_ip", smp_fetch_hdr_ip, ARG2(0,STR,SINT), val_hdr, SMP_T_IPV4, SMP_USE_HRSHV }, + { "res.hdr_names", smp_fetch_hdr_names, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRSHV }, { "res.hdr_val", smp_fetch_hdr_val, ARG2(0,STR,SINT), val_hdr, SMP_T_UINT, SMP_USE_HRSHV }, /* scook is valid only on the response and is used for ACL compatibility */