From eb27ec756975af2258d94645241e5e64ff07164b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 20 Feb 2015 13:55:29 +0100 Subject: [PATCH] MINOR: http: add the new sample fetches req.hdr_names and res.hdr_names These new sample fetches retrieve the list of header names as they appear in the request or response. This can be used for debugging, for statistics as well as an aid to better detect the presence of proxies or plugins on some browsers, which alter the request compared to a regular browser by adding or reordering headers. --- doc/configuration.txt | 12 ++++++++++++ src/proto_http.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) 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 */