diff --git a/doc/configuration.txt b/doc/configuration.txt index a0e49ddb3..bf95d051a 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25201,7 +25201,7 @@ http_first_req boolean method integer path string pathq string -query string +query([]) string req.hdr_names([]) string req.ver string req_ver string @@ -25661,13 +25661,20 @@ pathq : string accept-unsafe-violations-in-http-request", then this fragment part will be accepted and will also appear in the path. -query : string +query([]) : string This extracts the request's query string, which starts after the first question mark. If no question mark is present, this fetch returns nothing. If a question mark is present but nothing follows, it returns an empty string. This means it's possible to easily know whether a query string is present using the "found" matching method. This fetch is the complement of "path" - which stops before the question mark. + which stops before the question mark and of "query_string", which include the + question mark. + + An optional parameter may be used to customize the return value. Following + options are supported: + + - with_qm : Include the question mark at the beginning ot the query string, + if not empty. req.hdr_names([]) : string This builds a string made from the concatenation of all header names as they diff --git a/src/http_fetch.c b/src/http_fetch.c index ad1e8c543..28fe8ae7a 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -1284,6 +1284,9 @@ static int smp_fetch_query(const struct arg *args, struct sample *smp, const cha return 0; } while (*ptr++ != '?'); + if (ptr != end && args[0].type == ARGT_SINT && args[0].data.sint == 1) + ptr--; + smp->data.type = SMP_T_STR; smp->data.u.str.area = ptr; smp->data.u.str.data = end - ptr; @@ -2224,6 +2227,27 @@ int val_hdr(struct arg *arg, char **err_msg) return 1; } +int val_query(struct arg *args, char **err_msg) +{ + if (args[0].type == ARGT_STOP) + return 1; + + if (args[0].type != ARGT_STR) { + memprintf(err_msg, "first argument must be a string"); + return 0; + } + + if (chunk_strcmp(&args[0].data.str, "with_qm") != 0) { + memprintf(err_msg, "supported options are: 'with_qm'"); + return 0; + } + + chunk_destroy(&args[0].data.str); + args[0].type = ARGT_SINT; + args[0].data.sint = 1; + return 1; + +} /************************************************************************/ /* All supported sample fetch keywords must be declared here. */ /************************************************************************/ @@ -2274,7 +2298,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "method", smp_fetch_meth, 0, NULL, SMP_T_METH, SMP_USE_HRQHP }, { "path", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "pathq", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, - { "query", smp_fetch_query, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, + { "query", smp_fetch_query, ARG1(0,STR), val_query, SMP_T_STR, SMP_USE_HRQHV }, /* HTTP protocol on the request path */ { "req.proto_http", smp_fetch_proto_http, 0, NULL, SMP_T_BOOL, SMP_USE_HRQHP },